📄 htmlediting.cpp
字号:
// there is no other option at this point than to // use the highest allowed position in the node return Position(node, maxCompliantOffset); } // Editing should never generate positions like this. if ((pos.offset() < maxCompliantOffset) && editingIgnoresContent(node)) { ASSERT_NOT_REACHED(); return node->parentNode() ? positionBeforeNode(node) : Position(node, 0); } if (pos.offset() == maxCompliantOffset && (editingIgnoresContent(node) || isTableElement(node))) return positionAfterNode(node); return Position(pos);}Position rangeCompliantEquivalent(const VisiblePosition& vpos){ return rangeCompliantEquivalent(vpos.deepEquivalent());}// This method is used to create positions in the DOM. It returns the maximum valid offset// in a node. It returns 1 for some elements even though they do not have children, which// creates technically invalid DOM Positions. Be sure to call rangeCompliantEquivalent// on a Position before using it to create a DOM Range, or an exception will be thrown.int maxDeepOffset(const Node *node){ ASSERT(node); if (!node) return 0; if (node->offsetInCharacters()) return node->maxCharacterOffset(); if (node->hasChildNodes()) return node->childNodeCount(); // NOTE: This should preempt the childNodeCount for, e.g., select nodes if (editingIgnoresContent(node)) return 1; return 0;}String stringWithRebalancedWhitespace(const String& string, bool startIsStartOfParagraph, bool endIsEndOfParagraph){ DEFINE_STATIC_LOCAL(String, twoSpaces, (" ")); DEFINE_STATIC_LOCAL(String, nbsp, ("\xa0")); DEFINE_STATIC_LOCAL(String, pattern, (" \xa0")); String rebalancedString = string; rebalancedString.replace(noBreakSpace, ' '); rebalancedString.replace('\n', ' '); rebalancedString.replace('\t', ' '); rebalancedString.replace(twoSpaces, pattern); if (startIsStartOfParagraph && rebalancedString[0] == ' ') rebalancedString.replace(0, 1, nbsp); int end = rebalancedString.length() - 1; if (endIsEndOfParagraph && rebalancedString[end] == ' ') rebalancedString.replace(end, 1, nbsp); return rebalancedString;}bool isTableStructureNode(const Node *node){ RenderObject *r = node->renderer(); return (r && (r->isTableCell() || r->isTableRow() || r->isTableSection() || r->isTableCol()));}const String& nonBreakingSpaceString(){ DEFINE_STATIC_LOCAL(String, nonBreakingSpaceString, (&noBreakSpace, 1)); return nonBreakingSpaceString;}// FIXME: need to dump thisbool isSpecialElement(const Node *n){ if (!n) return false; if (!n->isHTMLElement()) return false; if (n->isLink()) return true; RenderObject *renderer = n->renderer(); if (!renderer) return false; if (renderer->style()->display() == TABLE || renderer->style()->display() == INLINE_TABLE) return true; if (renderer->style()->isFloating()) return true; if (renderer->style()->position() != StaticPosition) return true; return false;}// Checks if a string is a valid tag for the FormatBlockCommand function of execCommand. Expects lower case strings.bool validBlockTag(const String& blockTag){ if (blockTag == "address" || blockTag == "blockquote" || blockTag == "dd" || blockTag == "div" || blockTag == "dl" || blockTag == "dt" || blockTag == "h1" || blockTag == "h2" || blockTag == "h3" || blockTag == "h4" || blockTag == "h5" || blockTag == "h6" || blockTag == "p" || blockTag == "pre") return true; return false;}static Node* firstInSpecialElement(const Position& pos){ Node* rootEditableElement = pos.node()->rootEditableElement(); for (Node* n = pos.node(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode()) if (isSpecialElement(n)) { VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM); VisiblePosition firstInElement = VisiblePosition(n, 0, DOWNSTREAM); if (isTableElement(n) && vPos == firstInElement.next()) return n; if (vPos == firstInElement) return n; } return 0;}static Node* lastInSpecialElement(const Position& pos){ Node* rootEditableElement = pos.node()->rootEditableElement(); for (Node* n = pos.node(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode()) if (isSpecialElement(n)) { VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM); VisiblePosition lastInElement = VisiblePosition(n, n->childNodeCount(), DOWNSTREAM); if (isTableElement(n) && vPos == lastInElement.previous()) return n; if (vPos == lastInElement) return n; } return 0;}bool isFirstVisiblePositionInSpecialElement(const Position& pos){ return firstInSpecialElement(pos);}Position positionBeforeContainingSpecialElement(const Position& pos, Node** containingSpecialElement){ Node* n = firstInSpecialElement(pos); if (!n) return pos; Position result = positionBeforeNode(n); if (result.isNull() || result.node()->rootEditableElement() != pos.node()->rootEditableElement()) return pos; if (containingSpecialElement) *containingSpecialElement = n; return result;}bool isLastVisiblePositionInSpecialElement(const Position& pos){ return lastInSpecialElement(pos);}Position positionAfterContainingSpecialElement(const Position& pos, Node **containingSpecialElement){ Node* n = lastInSpecialElement(pos); if (!n) return pos; Position result = positionAfterNode(n); if (result.isNull() || result.node()->rootEditableElement() != pos.node()->rootEditableElement()) return pos; if (containingSpecialElement) *containingSpecialElement = n; return result;}Position positionOutsideContainingSpecialElement(const Position &pos, Node **containingSpecialElement){ if (isFirstVisiblePositionInSpecialElement(pos)) return positionBeforeContainingSpecialElement(pos, containingSpecialElement); if (isLastVisiblePositionInSpecialElement(pos)) return positionAfterContainingSpecialElement(pos, containingSpecialElement); return pos;}Node* isFirstPositionAfterTable(const VisiblePosition& visiblePosition){ Position upstream(visiblePosition.deepEquivalent().upstream()); if (upstream.node() && upstream.node()->renderer() && upstream.node()->renderer()->isTable() && upstream.offset() == maxDeepOffset(upstream.node())) return upstream.node(); return 0;}Node* isLastPositionBeforeTable(const VisiblePosition& visiblePosition){ Position downstream(visiblePosition.deepEquivalent().downstream()); if (downstream.node() && downstream.node()->renderer() && downstream.node()->renderer()->isTable() && downstream.offset() == 0) return downstream.node(); return 0;}Position positionBeforeNode(const Node *node){ return Position(node->parentNode(), node->nodeIndex());}Position positionAfterNode(const Node *node){ return Position(node->parentNode(), node->nodeIndex() + 1);}bool isListElement(Node *n){ return (n && (n->hasTagName(ulTag) || n->hasTagName(olTag) || n->hasTagName(dlTag)));}Node* enclosingNodeWithTag(const Position& p, const QualifiedName& tagName){ if (p.isNull()) return 0; Node* root = highestEditableRoot(p); for (Node* n = p.node(); n; n = n->parentNode()) { if (root && !isContentEditable(n)) continue; if (n->hasTagName(tagName)) return n; if (n == root) return 0; } return 0;}Node* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*), bool onlyReturnEditableNodes){ if (p.isNull()) return 0; Node* root = highestEditableRoot(p); for (Node* n = p.node(); n; n = n->parentNode()) { // Don't return a non-editable node if the input position was editable, since // the callers from editing will no doubt want to perform editing inside the returned node. if (root && !isContentEditable(n) && onlyReturnEditableNodes) continue; if ((*nodeIsOfType)(n)) return n; if (n == root) return 0; } return 0;}Node* highestEnclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*)){ Node* highest = 0; Node* root = highestEditableRoot(p); for (Node* n = p.node(); n; n = n->parentNode()) { if ((*nodeIsOfType)(n)) highest = n; if (n == root) break; } return highest;}Node* enclosingTableCell(const Position& p){ return static_cast<Element*>(enclosingNodeOfType(p, isTableCell));}Node* enclosingAnchorElement(const Position& p){ if (p.isNull()) return 0; Node* node = p.node(); while (node && !(node->isElementNode() && node->isLink())) node = node->parentNode(); return node;}HTMLElement* enclosingList(Node* node){ if (!node) return 0; Node* root = highestEditableRoot(Position(node, 0)); for (Node* n = node->parentNode(); n; n = n->parentNode()) { if (n->hasTagName(ulTag) || n->hasTagName(olTag)) return static_cast<HTMLElement*>(n); if (n == root) return 0; } return 0;}Node* enclosingListChild(Node *node){ if (!node) return 0; // Check for a list item element, or for a node whose parent is a list element. Such a node // will appear visually as a list item (but without a list marker) Node* root = highestEditableRoot(Position(node, 0)); // FIXME: This function is inappropriately named if it starts with node instead of node->parentNode() for (Node* n = node; n && n->parentNode(); n = n->parentNode()) { if (n->hasTagName(liTag) || isListElement(n->parentNode())) return n; if (n == root || isTableCell(n)) return 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -