2016-07-09 05:42:33 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#ifndef mozilla_HTMLEditor_h
|
|
|
|
#define mozilla_HTMLEditor_h
|
|
|
|
|
|
|
|
#include "mozilla/Attributes.h"
|
2018-01-26 08:38:05 +03:00
|
|
|
#include "mozilla/ComposerCommandsUpdater.h"
|
2016-07-08 08:03:31 +03:00
|
|
|
#include "mozilla/CSSEditUtils.h"
|
2017-08-02 22:37:44 +03:00
|
|
|
#include "mozilla/ManualNAC.h"
|
2016-09-26 15:03:25 +03:00
|
|
|
#include "mozilla/StyleSheet.h"
|
2016-07-09 05:54:50 +03:00
|
|
|
#include "mozilla/TextEditor.h"
|
2017-02-08 12:14:24 +03:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2016-07-09 05:42:33 +03:00
|
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
#include "mozilla/dom/File.h"
|
|
|
|
|
|
|
|
#include "nsAttrName.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsICSSLoaderObserver.h"
|
|
|
|
#include "nsIDocumentObserver.h"
|
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "nsIEditorMailSupport.h"
|
|
|
|
#include "nsIEditorStyleSheets.h"
|
|
|
|
#include "nsIEditorUtils.h"
|
|
|
|
#include "nsIHTMLAbsPosEditor.h"
|
|
|
|
#include "nsIHTMLEditor.h"
|
|
|
|
#include "nsIHTMLInlineTableEditor.h"
|
|
|
|
#include "nsIHTMLObjectResizer.h"
|
|
|
|
#include "nsITableEditor.h"
|
|
|
|
#include "nsPoint.h"
|
|
|
|
#include "nsStubMutationObserver.h"
|
|
|
|
#include "nsTArray.h"
|
|
|
|
|
|
|
|
class nsDocumentFragment;
|
2018-04-06 08:53:05 +03:00
|
|
|
class nsHTMLDocument;
|
2016-07-09 05:42:33 +03:00
|
|
|
class nsITransferable;
|
|
|
|
class nsIClipboard;
|
|
|
|
class nsILinkHandler;
|
|
|
|
class nsTableWrapperFrame;
|
|
|
|
class nsRange;
|
|
|
|
|
|
|
|
namespace mozilla {
|
2017-08-08 04:57:19 +03:00
|
|
|
class AutoSelectionSetterAfterTableEdit;
|
2016-07-09 05:42:33 +03:00
|
|
|
class HTMLEditorEventListener;
|
2018-01-26 09:14:04 +03:00
|
|
|
class ResizerSelectionListener;
|
2016-07-09 05:42:33 +03:00
|
|
|
class TypeInState;
|
2018-01-12 13:01:04 +03:00
|
|
|
enum class EditAction : int32_t;
|
2016-07-09 05:42:33 +03:00
|
|
|
struct PropItem;
|
|
|
|
template<class T> class OwningNonNull;
|
|
|
|
namespace dom {
|
|
|
|
class DocumentFragment;
|
2018-04-20 19:53:17 +03:00
|
|
|
class Event;
|
2018-03-20 07:16:05 +03:00
|
|
|
class MouseEvent;
|
2016-07-09 05:42:33 +03:00
|
|
|
} // namespace dom
|
|
|
|
namespace widget {
|
|
|
|
struct IMEState;
|
|
|
|
} // namespace widget
|
|
|
|
|
2016-08-24 15:53:52 +03:00
|
|
|
enum class ParagraphSeparator { div, p, br };
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
/**
|
|
|
|
* The HTML editor implementation.<br>
|
|
|
|
* Use to edit HTML document represented as a DOM tree.
|
|
|
|
*/
|
2016-07-09 05:54:50 +03:00
|
|
|
class HTMLEditor final : public TextEditor
|
2016-07-09 05:42:33 +03:00
|
|
|
, public nsIHTMLEditor
|
|
|
|
, public nsIHTMLObjectResizer
|
|
|
|
, public nsIHTMLAbsPosEditor
|
|
|
|
, public nsITableEditor
|
|
|
|
, public nsIHTMLInlineTableEditor
|
|
|
|
, public nsIEditorStyleSheets
|
|
|
|
, public nsICSSLoaderObserver
|
|
|
|
, public nsStubMutationObserver
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
enum BlockTransformationType
|
|
|
|
{
|
|
|
|
eNoOp,
|
|
|
|
eReplaceParent = 1,
|
|
|
|
eInsertParent = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
const char16_t kNBSP = 160;
|
|
|
|
|
|
|
|
public:
|
|
|
|
enum ResizingRequestID
|
|
|
|
{
|
|
|
|
kX = 0,
|
|
|
|
kY = 1,
|
|
|
|
kWidth = 2,
|
|
|
|
kHeight = 3
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
2016-07-09 05:54:50 +03:00
|
|
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, TextEditor)
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
HTMLEditor();
|
|
|
|
|
|
|
|
bool GetReturnInParagraphCreatesNewParagraph();
|
|
|
|
Element* GetSelectionContainer();
|
|
|
|
|
2018-01-26 11:25:45 +03:00
|
|
|
// nsISelectionListener overrides
|
2018-05-08 20:52:35 +03:00
|
|
|
NS_DECL_NSISELECTIONLISTENER
|
2018-01-26 11:25:45 +03:00
|
|
|
|
2016-07-09 05:54:50 +03:00
|
|
|
// TextEditor overrides
|
2018-02-07 09:28:04 +03:00
|
|
|
virtual nsresult Init(nsIDocument& aDoc, Element* aRoot,
|
|
|
|
nsISelectionController* aSelCon, uint32_t aFlags,
|
|
|
|
const nsAString& aValue) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
NS_IMETHOD BeginningOfDocument() override;
|
2017-02-08 14:18:17 +03:00
|
|
|
virtual nsresult HandleKeyPressEvent(
|
|
|
|
WidgetKeyboardEvent* aKeyboardEvent) override;
|
2018-01-09 16:41:42 +03:00
|
|
|
virtual nsIContent* GetFocusedContent() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
|
|
|
|
virtual bool IsActiveInDOMWindow() override;
|
2018-01-09 16:41:42 +03:00
|
|
|
virtual dom::EventTarget* GetDOMEventTarget() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual Element* GetEditorRoot() override;
|
|
|
|
virtual already_AddRefed<nsIContent> FindSelectionRoot(
|
|
|
|
nsINode *aNode) override;
|
2017-01-17 11:17:06 +03:00
|
|
|
virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
|
2016-07-08 07:10:13 +03:00
|
|
|
using EditorBase::IsEditable;
|
2016-12-20 13:24:08 +03:00
|
|
|
virtual nsresult RemoveAttributeOrEquivalent(
|
|
|
|
Element* aElement,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-12-20 13:24:08 +03:00
|
|
|
bool aSuppressTransaction) override;
|
|
|
|
virtual nsresult SetAttributeOrEquivalent(Element* aElement,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-12-20 13:24:08 +03:00
|
|
|
const nsAString& aValue,
|
|
|
|
bool aSuppressTransaction) override;
|
|
|
|
using EditorBase::RemoveAttributeOrEquivalent;
|
|
|
|
using EditorBase::SetAttributeOrEquivalent;
|
2018-05-22 12:23:21 +03:00
|
|
|
virtual bool CanPasteTransferable(nsITransferable* aTransferable) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// nsStubMutationObserver overrides
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
|
|
|
|
|
|
|
// nsIHTMLEditor methods
|
|
|
|
NS_DECL_NSIHTMLEDITOR
|
|
|
|
|
|
|
|
// nsIHTMLObjectResizer methods (implemented in HTMLObjectResizer.cpp)
|
|
|
|
NS_DECL_NSIHTMLOBJECTRESIZER
|
|
|
|
|
|
|
|
// nsIHTMLAbsPosEditor methods (implemented in HTMLAbsPositionEditor.cpp)
|
|
|
|
NS_DECL_NSIHTMLABSPOSEDITOR
|
|
|
|
|
|
|
|
// nsIHTMLInlineTableEditor methods (implemented in HTMLInlineTableEditor.cpp)
|
|
|
|
NS_DECL_NSIHTMLINLINETABLEEDITOR
|
|
|
|
|
|
|
|
// XXX Following methods are not overriding but defined here...
|
|
|
|
nsresult LoadHTML(const nsAString& aInputString);
|
|
|
|
|
|
|
|
nsresult GetCSSBackgroundColorState(bool* aMixed, nsAString& aOutColor,
|
|
|
|
bool aBlockLevel);
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult GetHTMLBackgroundColorState(bool* aMixed, nsAString& outColor);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// nsIEditorStyleSheets methods
|
2017-01-27 05:11:09 +03:00
|
|
|
NS_DECL_NSIEDITORSTYLESHEETS
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// nsIEditorMailSupport methods
|
|
|
|
NS_DECL_NSIEDITORMAILSUPPORT
|
|
|
|
|
|
|
|
// nsITableEditor methods
|
2017-01-27 05:11:09 +03:00
|
|
|
NS_DECL_NSITABLEEDITOR
|
|
|
|
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult GetLastCellInRow(nsINode* aRowNode,
|
|
|
|
nsINode** aCellNode);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult GetCellFromRange(nsRange* aRange, Element** aCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// Miscellaneous
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This sets background on the appropriate container element (table, cell,)
|
|
|
|
* or calls into nsTextEditor to set the page background.
|
|
|
|
*/
|
2018-04-16 18:02:39 +03:00
|
|
|
nsresult SetCSSBackgroundColorWithTransaction(const nsAString& aColor);
|
|
|
|
nsresult SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-10-26 16:54:30 +03:00
|
|
|
/**
|
|
|
|
* GetBlockNodeParent() returns parent or nearest ancestor of aNode if
|
|
|
|
* there is a block parent. If aAncestorLimiter is not nullptr,
|
|
|
|
* this stops looking for the result.
|
|
|
|
*/
|
|
|
|
static Element* GetBlockNodeParent(nsINode* aNode,
|
|
|
|
nsINode* aAncestorLimiter = nullptr);
|
|
|
|
/**
|
|
|
|
* GetBlock() returns aNode itself, or parent or nearest ancestor of aNode
|
|
|
|
* if there is a block parent. If aAncestorLimiter is not nullptr,
|
|
|
|
* this stops looking for the result.
|
|
|
|
*/
|
|
|
|
static Element* GetBlock(nsINode& aNode,
|
|
|
|
nsINode* aAncestorLimiter = nullptr);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
void IsNextCharInNodeWhitespace(nsIContent* aContent,
|
|
|
|
int32_t aOffset,
|
|
|
|
bool* outIsSpace,
|
|
|
|
bool* outIsNBSP,
|
|
|
|
nsIContent** outNode = nullptr,
|
|
|
|
int32_t* outOffset = 0);
|
|
|
|
void IsPrevCharInNodeWhitespace(nsIContent* aContent,
|
|
|
|
int32_t aOffset,
|
|
|
|
bool* outIsSpace,
|
|
|
|
bool* outIsNBSP,
|
|
|
|
nsIContent** outNode = nullptr,
|
|
|
|
int32_t* outOffset = 0);
|
|
|
|
|
2016-07-08 07:10:13 +03:00
|
|
|
// Overrides of EditorBase interface methods
|
2017-02-01 11:09:54 +03:00
|
|
|
virtual nsresult EndUpdateViewBatch() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-05-22 12:23:21 +03:00
|
|
|
virtual void PreDestroy(bool aDestroyingFrames) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-02-07 09:28:04 +03:00
|
|
|
virtual nsresult GetPreferredIMEState(widget::IMEState* aState) override;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
/**
|
|
|
|
* @param aElement Must not be null.
|
|
|
|
*/
|
|
|
|
static bool NodeIsBlockStatic(const nsINode* aElement);
|
|
|
|
|
2017-08-04 12:30:13 +03:00
|
|
|
// non-virtual methods of interface methods
|
|
|
|
bool AbsolutePositioningEnabled() const
|
|
|
|
{
|
|
|
|
return mIsAbsolutelyPositioningEnabled;
|
|
|
|
}
|
2018-02-01 04:55:25 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* returns the deepest absolutely positioned container of the selection
|
|
|
|
* if it exists or null.
|
|
|
|
*/
|
2018-01-30 07:42:52 +03:00
|
|
|
already_AddRefed<Element> GetAbsolutelyPositionedSelectionContainer();
|
2018-02-01 04:55:25 +03:00
|
|
|
|
2017-08-04 12:30:13 +03:00
|
|
|
Element* GetPositionedElement() const
|
|
|
|
{
|
|
|
|
return mAbsolutelyPositionedObject;
|
|
|
|
}
|
2018-02-01 04:55:25 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* extracts the selection from the normal flow of the document and
|
|
|
|
* positions it.
|
|
|
|
* @param aEnabled [IN] true to absolutely position the selection,
|
|
|
|
* false to put it back in the normal flow
|
|
|
|
*/
|
|
|
|
nsresult SetSelectionToAbsoluteOrStatic(bool aEnabled);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* extracts an element from the normal flow of the document and
|
|
|
|
* positions it, and puts it back in the normal flow.
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
* @param aEnabled [IN] true to absolutely position the element,
|
|
|
|
* false to put it back in the normal flow
|
|
|
|
*/
|
|
|
|
nsresult SetPositionToAbsoluteOrStatic(Element& aElement,
|
|
|
|
bool aEnabled);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* returns the absolute z-index of a positioned element. Never returns 'auto'
|
|
|
|
* @return the z-index of the element
|
|
|
|
* @param aElement [IN] the element.
|
|
|
|
*/
|
|
|
|
int32_t GetZIndex(Element& aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* adds aChange to the z-index of the currently positioned element.
|
|
|
|
* @param aChange [IN] relative change to apply to current z-index
|
|
|
|
*/
|
|
|
|
nsresult AddZIndex(int32_t aChange);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* adds aChange to the z-index of an arbitrary element.
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
* @param aChange [IN] relative change to apply to current z-index of
|
|
|
|
* the element
|
|
|
|
* @param aReturn [OUT] the new z-index of the element
|
|
|
|
*/
|
|
|
|
nsresult RelativeChangeElementZIndex(Element& aElement, int32_t aChange,
|
|
|
|
int32_t* aReturn);
|
2017-08-04 12:30:13 +03:00
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult SetInlineProperty(nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2017-08-25 08:40:45 +03:00
|
|
|
const nsAString& aValue);
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult GetInlineProperty(nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2017-08-25 08:40:45 +03:00
|
|
|
const nsAString& aValue,
|
|
|
|
bool* aFirst,
|
|
|
|
bool* aAny,
|
|
|
|
bool* aAll);
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult GetInlinePropertyWithAttrValue(nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttr,
|
2017-08-25 08:40:45 +03:00
|
|
|
const nsAString& aValue,
|
|
|
|
bool* aFirst,
|
|
|
|
bool* aAny,
|
|
|
|
bool* aAll,
|
|
|
|
nsAString& outValue);
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult RemoveInlineProperty(nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute);
|
2018-01-26 08:38:05 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SetComposerCommandsUpdater() sets or unsets mComposerCommandsUpdater.
|
|
|
|
* This will crash in debug build if the editor already has an instance
|
|
|
|
* but called with another instance.
|
|
|
|
*/
|
|
|
|
void SetComposerCommandsUpdater(
|
|
|
|
ComposerCommandsUpdater* aComposerCommandsUpdater)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!aComposerCommandsUpdater || !mComposerCommandsUpdater ||
|
|
|
|
aComposerCommandsUpdater == mComposerCommandsUpdater);
|
|
|
|
mComposerCommandsUpdater = aComposerCommandsUpdater;
|
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
protected:
|
|
|
|
virtual ~HTMLEditor();
|
|
|
|
|
2016-07-08 07:10:13 +03:00
|
|
|
using EditorBase::IsBlockNode;
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual bool IsBlockNode(nsINode *aNode) override;
|
|
|
|
|
Bug 662591 - HTMLEditor should set caret to start of first editable text node or before first editable inline node r=m_kato
Currently, HTMLEditor doesn't initialize caret position when it gets focus by
itself in most cases. Only when it's in designMode, it may move caret to the
first visible (not checking CSS actually).
In most cases, caret position is adjusted when EditorBase::InitializeSelection()
calls Selection::SetAncestorLimiter(). If selected range is outside of
new limiter, it moves caret to start of the new limiter. However, this is
really different behavior from the other browsers. The other browsers try
to move caret to the first editable text node or before the first editable
content such as <img>, <input>, etc.
This difference causes a serious incompatible issue with Draft.js. It doesn't
initialize caret position when it gets focus but it assumes that caret is
always set to before <br> element if there is no other content.
So, let's try to behave as what other browsers do as far as possible.
This patch makes editor behave as:
* if selection is already in the editing host except start of the editing host,
does nothing.
* if there is non-editable element before any editable node, move caret to
start of the editing host.
* if there is editable text node or element node which cannot have a text node,
move its start or before it.
* if there is no editable nodes which can contain text nodes, move caret to
start of the editing host.
Note that before applying this patch, in designMode, BeginningOfDocument() used
document element instead of <body> element. Therefore, it may set odd position
if <head> element has some text nodes with <script> or <style>. However,
this doesn't make sense and for making more consistent behavior between
designMode and contenteditable, this patch makes it use editing host (it's
<body> element if it's in designMode).
MozReview-Commit-ID: 5neYoTMq6Cc
--HG--
extra : rebase_source : c4d06b6864a221d7cd2833a007d73f7d67821e95
2018-03-02 08:20:25 +03:00
|
|
|
virtual void
|
|
|
|
InitializeSelectionAncestorLimit(Selection& aSelection,
|
|
|
|
nsIContent& aAncestorLimit) override;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
public:
|
|
|
|
// XXX Why don't we move following methods above for grouping by the origins?
|
|
|
|
NS_IMETHOD SetFlags(uint32_t aFlags) override;
|
|
|
|
|
|
|
|
NS_IMETHOD Paste(int32_t aSelectionType) override;
|
|
|
|
NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
|
|
|
|
|
|
|
|
NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
|
|
|
|
|
|
|
|
NS_IMETHOD DebugUnitTests(int32_t* outNumTests,
|
|
|
|
int32_t* outNumTestsFailed) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* All editor operations which alter the doc should be prefaced
|
|
|
|
* with a call to StartOperation, naming the action and direction.
|
|
|
|
*/
|
2018-04-11 11:37:49 +03:00
|
|
|
virtual nsresult StartOperation(EditAction opID,
|
|
|
|
nsIEditor::EDirection aDirection) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* All editor operations which alter the doc should be followed
|
|
|
|
* with a call to EndOperation.
|
|
|
|
*/
|
2018-04-11 11:37:49 +03:00
|
|
|
virtual nsresult EndOperation() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* returns true if aParentTag can contain a child of type aChildTag.
|
|
|
|
*/
|
2017-10-03 01:05:19 +03:00
|
|
|
virtual bool TagCanContainTag(nsAtom& aParentTag,
|
2017-10-26 19:27:44 +03:00
|
|
|
nsAtom& aChildTag) const override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if aNode is a container.
|
|
|
|
*/
|
|
|
|
virtual bool IsContainer(nsINode* aNode) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make the given selection span the entire document.
|
|
|
|
*/
|
|
|
|
virtual nsresult SelectEntireDocument(Selection* aSelection) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Join together any adjacent editable text nodes in the range.
|
|
|
|
*/
|
|
|
|
nsresult CollapseAdjacentTextNodes(nsRange* aRange);
|
|
|
|
|
|
|
|
virtual bool AreNodesSameType(nsIContent* aNode1,
|
|
|
|
nsIContent* aNode2) override;
|
|
|
|
|
2018-04-11 13:11:15 +03:00
|
|
|
/**
|
|
|
|
* DeleteSelectionWithTransaction() removes selected content or content
|
|
|
|
* around caret with transactions.
|
|
|
|
*
|
|
|
|
* @param aDirection How much range should be removed.
|
|
|
|
* @param aStripWrappers Whether the parent blocks should be removed
|
|
|
|
* when they become empty.
|
|
|
|
*/
|
|
|
|
virtual nsresult
|
|
|
|
DeleteSelectionWithTransaction(EDirection aAction,
|
|
|
|
EStripWrappers aStripWrappers) override;
|
2018-04-10 10:23:54 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* DeleteNodeWithTransaction() removes aNode from the DOM tree if it's
|
|
|
|
* modifiable. Note that this is not an override of same method of
|
|
|
|
* EditorBase.
|
|
|
|
*
|
|
|
|
* @param aNode The node to be removed from the DOM tree.
|
|
|
|
*/
|
|
|
|
nsresult DeleteNodeWithTransaction(nsINode& aNode);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
NS_IMETHOD DeleteNode(nsIDOMNode* aNode) override;
|
2018-04-10 10:23:54 +03:00
|
|
|
|
2018-04-10 10:50:06 +03:00
|
|
|
/**
|
|
|
|
* DeleteTextWithTransaction() removes text in the range from aCharData if
|
|
|
|
* it's modifiable. Note that this not an override of same method of
|
|
|
|
* EditorBase.
|
|
|
|
*
|
|
|
|
* @param aCharData The data node which should be modified.
|
|
|
|
* @param aOffset Start offset of removing text in aCharData.
|
|
|
|
* @param aLength Length of removing text.
|
|
|
|
*/
|
|
|
|
nsresult DeleteTextWithTransaction(dom::CharacterData& aTextNode,
|
|
|
|
uint32_t aOffset, uint32_t aLength);
|
|
|
|
|
2018-04-12 11:58:14 +03:00
|
|
|
/**
|
|
|
|
* InsertTextWithTransaction() inserts aStringToInsert at aPointToInsert.
|
|
|
|
*/
|
2017-11-08 19:00:36 +03:00
|
|
|
virtual nsresult
|
2018-04-12 11:58:14 +03:00
|
|
|
InsertTextWithTransaction(nsIDocument& aDocument,
|
|
|
|
const nsAString& aStringToInsert,
|
|
|
|
const EditorRawDOMPoint& aPointToInsert,
|
|
|
|
EditorRawDOMPoint* aPointAfterInsertedString =
|
|
|
|
nullptr) override;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual bool IsModifiableNode(nsINode* aNode) override;
|
|
|
|
|
|
|
|
NS_IMETHOD SelectAll() override;
|
|
|
|
|
|
|
|
// nsICSSLoaderObserver
|
2016-09-26 15:03:25 +03:00
|
|
|
NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet,
|
2016-07-09 05:42:33 +03:00
|
|
|
bool aWasAlternate, nsresult aStatus) override;
|
|
|
|
|
2018-04-16 17:43:36 +03:00
|
|
|
/**
|
|
|
|
* OnInputLineBreak() is called when user inputs a line break with
|
|
|
|
* Shift + Enter or something.
|
|
|
|
*/
|
|
|
|
nsresult OnInputLineBreak();
|
2017-11-28 16:28:07 +03:00
|
|
|
|
|
|
|
/**
|
2018-04-16 17:53:46 +03:00
|
|
|
* InsertNodeIntoProperAncestorWithTransaction() attempts to insert aNode
|
|
|
|
* into the document, at aPointToInsert. Checks with strict dtd to see if
|
|
|
|
* containment is allowed. If not allowed, will attempt to find a parent
|
|
|
|
* in the parent hierarchy of aPointToInsert.GetContainer() that will accept
|
|
|
|
* aNode as a child. If such a parent is found, will split the document
|
|
|
|
* tree from aPointToInsert up to parent, and then insert aNode.
|
|
|
|
* aPointToInsert is then adjusted to point to the actual location that
|
|
|
|
* aNode was inserted at. aSplitAtEdges specifies if the splitting process
|
|
|
|
* is allowed to result in empty nodes.
|
2017-11-28 16:28:07 +03:00
|
|
|
*
|
|
|
|
* @param aNode Node to insert.
|
|
|
|
* @param aPointToInsert Insertion point.
|
|
|
|
* @param aSplitAtEdges Splitting can result in empty nodes?
|
|
|
|
* @return Returns inserted point if succeeded.
|
|
|
|
* Otherwise, the result is not set.
|
|
|
|
*/
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
2017-11-28 16:28:07 +03:00
|
|
|
EditorDOMPoint
|
2018-04-16 17:53:46 +03:00
|
|
|
InsertNodeIntoProperAncestorWithTransaction(
|
|
|
|
nsIContent& aNode,
|
|
|
|
const EditorDOMPointBase<PT, CT>& aPointToInsert,
|
|
|
|
SplitAtEdges aSplitAtEdges);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-16 19:15:23 +03:00
|
|
|
/**
|
|
|
|
* CopyLastEditableChildStyles() clones inline container elements into
|
|
|
|
* aPreviousBlock to aNewBlock to keep using same style in it.
|
|
|
|
*
|
|
|
|
* @param aPreviousBlock The previous block element. All inline
|
|
|
|
* elements which are last sibling of each level
|
|
|
|
* are cloned to aNewBlock.
|
|
|
|
* @param aNewBlock New block container element.
|
|
|
|
* @param aNewBrElement If this method creates a new <br> element for
|
|
|
|
* placeholder, this is set to the new <br>
|
|
|
|
* element.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
CopyLastEditableChildStylesWithTransaction(Element& aPreviousBlock,
|
|
|
|
Element& aNewBlock,
|
|
|
|
RefPtr<Element>* aNewBrElement);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
/**
|
|
|
|
* Use this to assure that selection is set after attribute nodes when
|
|
|
|
* trying to collapse selection at begining of a block node
|
|
|
|
* e.g., when setting at beginning of a table cell
|
|
|
|
* This will stop at a table, however, since we don't want to
|
|
|
|
* "drill down" into nested tables.
|
|
|
|
* @param aSelection Optional. If null, we get current selection.
|
|
|
|
*/
|
|
|
|
void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
|
|
|
|
nsINode* aNode);
|
|
|
|
|
2017-12-20 09:07:37 +03:00
|
|
|
/**
|
|
|
|
* IsInVisibleTextFrames() returns true if all text in aText is in visible
|
|
|
|
* text frames. Callers have to guarantee that there is no pending reflow.
|
|
|
|
*/
|
|
|
|
bool IsInVisibleTextFrames(dom::Text& aText);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* IsVisibleTextNode() returns true if aText has visible text. If it has
|
|
|
|
* only whitespaces and they are collapsed, returns false.
|
|
|
|
*/
|
|
|
|
bool IsVisibleTextNode(Text& aText);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
/**
|
|
|
|
* aNode must be a non-null text node.
|
|
|
|
* outIsEmptyNode must be non-null.
|
|
|
|
*/
|
|
|
|
nsresult IsEmptyNode(nsINode* aNode, bool* outIsEmptyBlock,
|
|
|
|
bool aMozBRDoesntCount = false,
|
|
|
|
bool aListOrCellNotEmpty = false,
|
|
|
|
bool aSafeToAskFrames = false);
|
|
|
|
nsresult IsEmptyNodeImpl(nsINode* aNode,
|
|
|
|
bool* outIsEmptyBlock,
|
|
|
|
bool aMozBRDoesntCount,
|
|
|
|
bool aListOrCellNotEmpty,
|
|
|
|
bool aSafeToAskFrames,
|
|
|
|
bool* aSeenBR);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns TRUE if sheet was loaded, false if it wasn't.
|
|
|
|
*/
|
|
|
|
bool EnableExistingStyleSheet(const nsAString& aURL);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dealing with the internal style sheet lists.
|
|
|
|
*/
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* GetStyleSheetForURL(const nsAString& aURL);
|
|
|
|
void GetURLForStyleSheet(StyleSheet* aStyleSheet,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsAString& aURL);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a url + known style sheet to the internal lists.
|
|
|
|
*/
|
|
|
|
nsresult AddNewStyleSheetToList(const nsAString &aURL,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aStyleSheet);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult RemoveStyleSheetFromList(const nsAString &aURL);
|
|
|
|
|
2018-02-02 12:42:25 +03:00
|
|
|
bool IsCSSEnabled() const
|
2016-07-09 05:42:33 +03:00
|
|
|
{
|
|
|
|
// TODO: removal of mCSSAware and use only the presence of mCSSEditUtils
|
|
|
|
return mCSSAware && mCSSEditUtils && mCSSEditUtils->IsCSSPrefChecked();
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool HasAttributes(Element* aElement)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aElement);
|
|
|
|
uint32_t attrCount = aElement->GetAttrCount();
|
|
|
|
return attrCount > 1 ||
|
|
|
|
(1 == attrCount &&
|
|
|
|
!aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty));
|
|
|
|
}
|
|
|
|
|
2016-08-24 15:53:52 +03:00
|
|
|
ParagraphSeparator GetDefaultParagraphSeparator() const
|
|
|
|
{
|
|
|
|
return mDefaultParagraphSeparator;
|
|
|
|
}
|
|
|
|
void SetDefaultParagraphSeparator(ParagraphSeparator aSep)
|
|
|
|
{
|
|
|
|
mDefaultParagraphSeparator = aSep;
|
|
|
|
}
|
|
|
|
|
2018-01-10 06:47:16 +03:00
|
|
|
/**
|
|
|
|
* event callback when a mouse button is pressed
|
|
|
|
* @param aX [IN] horizontal position of the pointer
|
|
|
|
* @param aY [IN] vertical position of the pointer
|
|
|
|
* @param aTarget [IN] the element triggering the event
|
|
|
|
* @param aMouseEvent [IN] the event
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult OnMouseDown(int32_t aX, int32_t aY, Element* aTarget,
|
2018-04-20 19:53:17 +03:00
|
|
|
dom::Event* aMouseEvent);
|
2018-01-10 06:47:16 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* event callback when a mouse button is released
|
|
|
|
* @param aX [IN] horizontal position of the pointer
|
|
|
|
* @param aY [IN] vertical position of the pointer
|
|
|
|
* @param aTarget [IN] the element triggering the event
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult OnMouseUp(int32_t aX, int32_t aY, Element* aTarget);
|
2018-01-10 06:47:16 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* event callback when the mouse pointer is moved
|
|
|
|
* @param aMouseEvent [IN] the event
|
|
|
|
*/
|
2018-03-20 07:16:05 +03:00
|
|
|
nsresult OnMouseMove(dom::MouseEvent* aMouseEvent);
|
2018-01-10 06:47:16 +03:00
|
|
|
|
2018-01-19 10:41:41 +03:00
|
|
|
/**
|
|
|
|
* Modifies the table containing the selection according to the
|
|
|
|
* activation of an inline table editing UI element
|
|
|
|
* @param aUIAnonymousElement [IN] the inline table editing UI element
|
|
|
|
*/
|
2018-01-25 16:16:32 +03:00
|
|
|
nsresult DoInlineTableEditingAction(const Element& aUIAnonymousElement);
|
2018-01-19 10:41:41 +03:00
|
|
|
|
Bug 662591 - HTMLEditor should set caret to start of first editable text node or before first editable inline node r=m_kato
Currently, HTMLEditor doesn't initialize caret position when it gets focus by
itself in most cases. Only when it's in designMode, it may move caret to the
first visible (not checking CSS actually).
In most cases, caret position is adjusted when EditorBase::InitializeSelection()
calls Selection::SetAncestorLimiter(). If selected range is outside of
new limiter, it moves caret to start of the new limiter. However, this is
really different behavior from the other browsers. The other browsers try
to move caret to the first editable text node or before the first editable
content such as <img>, <input>, etc.
This difference causes a serious incompatible issue with Draft.js. It doesn't
initialize caret position when it gets focus but it assumes that caret is
always set to before <br> element if there is no other content.
So, let's try to behave as what other browsers do as far as possible.
This patch makes editor behave as:
* if selection is already in the editing host except start of the editing host,
does nothing.
* if there is non-editable element before any editable node, move caret to
start of the editing host.
* if there is editable text node or element node which cannot have a text node,
move its start or before it.
* if there is no editable nodes which can contain text nodes, move caret to
start of the editing host.
Note that before applying this patch, in designMode, BeginningOfDocument() used
document element instead of <body> element. Therefore, it may set odd position
if <head> element has some text nodes with <script> or <style>. However,
this doesn't make sense and for making more consistent behavior between
designMode and contenteditable, this patch makes it use editing host (it's
<body> element if it's in designMode).
MozReview-Commit-ID: 5neYoTMq6Cc
--HG--
extra : rebase_source : c4d06b6864a221d7cd2833a007d73f7d67821e95
2018-03-02 08:20:25 +03:00
|
|
|
/**
|
|
|
|
* MaybeCollapseSelectionAtFirstEditableNode() may collapse selection at
|
|
|
|
* proper position to staring to edit. If there is a non-editable node
|
|
|
|
* before any editable text nodes or inline elements which can have text
|
|
|
|
* nodes as their children, collapse selection at start of the editing
|
|
|
|
* host. If there is an editable text node which is not collapsed, collapses
|
|
|
|
* selection at the start of the text node. If there is an editable inline
|
|
|
|
* element which cannot have text nodes as its child, collapses selection at
|
|
|
|
* before the element node. Otherwise, collapses selection at start of the
|
|
|
|
* editing host.
|
|
|
|
*
|
|
|
|
* @param aIgnoreIfSelectionInEditingHost
|
|
|
|
* This method does nothing if selection is in the
|
|
|
|
* editing host except if it's collapsed at start of
|
|
|
|
* the editing host.
|
|
|
|
* Note that if selection ranges were outside of
|
|
|
|
* current selection limiter, selection was collapsed
|
|
|
|
* at the start of the editing host therefore, if
|
|
|
|
* you call this with setting this to true, you can
|
|
|
|
* keep selection ranges if user has already been
|
|
|
|
* changed.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
MaybeCollapseSelectionAtFirstEditableNode(
|
|
|
|
bool aIgnoreIfSelectionInEditingHost);
|
|
|
|
|
2018-04-06 08:53:05 +03:00
|
|
|
nsHTMLDocument* GetHTMLDocument() const;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
protected:
|
|
|
|
class BlobReader final : public nsIEditorBlobListener
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor,
|
2018-04-06 08:53:05 +03:00
|
|
|
bool aIsSafe, nsIDocument* aSourceDoc,
|
2018-03-27 14:19:35 +03:00
|
|
|
nsINode* aDestinationNode, int32_t aDestOffset,
|
2016-07-09 05:42:33 +03:00
|
|
|
bool aDoDeleteSelection);
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIEDITORBLOBLISTENER
|
|
|
|
|
|
|
|
private:
|
|
|
|
~BlobReader()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<dom::BlobImpl> mBlob;
|
|
|
|
RefPtr<HTMLEditor> mHTMLEditor;
|
|
|
|
bool mIsSafe;
|
2018-04-06 08:53:05 +03:00
|
|
|
nsCOMPtr<nsIDocument> mSourceDoc;
|
2018-03-27 14:19:35 +03:00
|
|
|
nsCOMPtr<nsINode> mDestinationNode;
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t mDestOffset;
|
|
|
|
bool mDoDeleteSelection;
|
|
|
|
};
|
|
|
|
|
Bug 1463327 - part 2: Change scope of some methods of TextEditor which won't be called by non-helper classes of editing to protected r=m_kato
TextEditor has 2 type of public methods. One is true-public methods. I.e.,
they should be able to be called by anybody. E.g., command handlers, event
listeners, or JS via nsIEditor interface. The other is semi-public methods.
They are not called by the above examples but called by other classes which
are helper classes to handle edit actions. E.g., TextEditRules, HTMLEditRules,
HTMLEditUtils, CSSEditUtils and Transaction classes.
When we will implement InputEvent.inputType, we need to create new stack
class and create its instance at every true-public methods to manage current
inputType (like TextEditRules::AutoSafeEditorData). Therefore, it should not
happen that new code starts to call semi-public methods without the new
stack class instance.
For preventing this issue, we should make TextEditor have only the true-public
methods as public. The other public methods should be protected and their
users should be friend classes. Then, we can protect such method from external
classes.
Note that this patch just moves the methods without any changes in TextEditor.h.
MozReview-Commit-ID: Db3H6d1V8IU
--HG--
extra : rebase_source : d928a6bb378d02944c5a207de83211c33bb63613
2018-05-22 10:40:44 +03:00
|
|
|
virtual nsresult InitRules() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
virtual void CreateEventListeners() override;
|
|
|
|
virtual nsresult InstallEventListeners() override;
|
|
|
|
virtual void RemoveEventListeners() override;
|
|
|
|
|
|
|
|
bool ShouldReplaceRootElement();
|
2017-08-28 21:57:46 +03:00
|
|
|
void NotifyRootChanged();
|
2018-01-30 08:25:36 +03:00
|
|
|
Element* GetBodyElement();
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the focused node of this editor.
|
|
|
|
* @return If the editor has focus, this returns the focused node.
|
|
|
|
* Otherwise, returns null.
|
|
|
|
*/
|
|
|
|
already_AddRefed<nsINode> GetFocusedNode();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return TRUE if aElement is a table-related elemet and caret was set.
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
bool SetCaretInTableCell(dom::Element* aElement);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-07-14 09:48:40 +03:00
|
|
|
nsresult TabInTable(bool inIsShift, bool* outHandled);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-11-21 08:38:19 +03:00
|
|
|
/**
|
2018-04-16 17:43:36 +03:00
|
|
|
* InsertBrElementAtSelectionWithTransaction() inserts a new <br> element at
|
|
|
|
* selection. If there is non-collapsed selection ranges, the selected
|
|
|
|
* ranges is deleted first.
|
2017-11-21 08:38:19 +03:00
|
|
|
*/
|
2018-04-16 17:43:36 +03:00
|
|
|
nsresult InsertBrElementAtSelectionWithTransaction();
|
2017-01-23 06:39:47 +03:00
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
// Table Editing (implemented in nsTableEditor.cpp)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert a new cell after or before supplied aCell.
|
|
|
|
* Optional: If aNewCell supplied, returns the newly-created cell (addref'd,
|
|
|
|
* of course)
|
|
|
|
* This doesn't change or use the current selection.
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult InsertCell(Element* aCell, int32_t aRowSpan,
|
2018-01-25 07:31:01 +03:00
|
|
|
int32_t aColSpan, bool aAfter, bool aIsHeader,
|
2018-04-27 06:35:18 +03:00
|
|
|
Element** aNewCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helpers that don't touch the selection or do batch transactions.
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult DeleteRow(Element* aTable, int32_t aRowIndex);
|
|
|
|
nsresult DeleteColumn(Element* aTable, int32_t aColIndex);
|
|
|
|
nsresult DeleteCellContents(Element* aCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Move all contents from aCellToMerge into aTargetCell (append at end).
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult MergeCells(RefPtr<Element> aTargetCell,
|
|
|
|
RefPtr<Element> aCellToMerge,
|
2018-01-25 07:31:01 +03:00
|
|
|
bool aDeleteCellToMerge);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult DeleteTable2(Element* aTable, Selection* aSelection);
|
|
|
|
nsresult SetColSpan(Element* aCell, int32_t aColSpan);
|
|
|
|
nsresult SetRowSpan(Element* aCell, int32_t aRowSpan);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper used to get nsTableWrapperFrame for a table.
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
nsTableWrapperFrame* GetTableFrame(Element* aTable);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Needed to do appropriate deleting when last cell or row is about to be
|
|
|
|
* deleted. This doesn't count cells that don't start in the given row (are
|
|
|
|
* spanning from row above).
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
int32_t GetNumberOfCellsInRow(Element* aTable, int32_t rowIndex);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Test if all cells in row or column at given index are selected.
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
bool AllCellsInRowSelected(Element* aTable, int32_t aRowIndex,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aNumberOfColumns);
|
2018-04-27 06:35:18 +03:00
|
|
|
bool AllCellsInColumnSelected(Element* aTable, int32_t aColIndex,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aNumberOfRows);
|
|
|
|
|
|
|
|
bool IsEmptyCell(Element* aCell);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Most insert methods need to get the same basic context data.
|
|
|
|
* Any of the pointers may be null if you don't need that datum (for more
|
|
|
|
* efficiency).
|
|
|
|
* Input: *aCell is a known cell,
|
|
|
|
* if null, cell is obtained from the anchor node of the selection.
|
|
|
|
* Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is
|
|
|
|
* null.
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult GetCellContext(Selection** aSelection, Element** aTable,
|
|
|
|
Element** aCell, nsINode** aCellParent,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t* aCellOffset, int32_t* aRowIndex,
|
|
|
|
int32_t* aColIndex);
|
|
|
|
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult GetCellSpansAt(Element* aTable, int32_t aRowIndex,
|
2018-01-25 07:31:01 +03:00
|
|
|
int32_t aColIndex, int32_t& aActualRowSpan,
|
|
|
|
int32_t& aActualColSpan);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult SplitCellIntoColumns(Element* aTable, int32_t aRowIndex,
|
2018-01-25 07:31:01 +03:00
|
|
|
int32_t aColIndex, int32_t aColSpanLeft,
|
|
|
|
int32_t aColSpanRight,
|
2018-04-27 06:35:18 +03:00
|
|
|
Element** aNewCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult SplitCellIntoRows(Element* aTable, int32_t aRowIndex,
|
2018-01-25 07:31:01 +03:00
|
|
|
int32_t aColIndex, int32_t aRowSpanAbove,
|
2018-04-27 06:35:18 +03:00
|
|
|
int32_t aRowSpanBelow, Element** aNewCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult CopyCellBackgroundColor(Element* aDestCell,
|
|
|
|
Element* aSourceCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Reduce rowspan/colspan when cells span into nonexistent rows/columns.
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult FixBadRowSpan(Element* aTable, int32_t aRowIndex,
|
2018-01-25 07:31:01 +03:00
|
|
|
int32_t& aNewRowCount);
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult FixBadColSpan(Element* aTable, int32_t aColIndex,
|
2018-01-25 07:31:01 +03:00
|
|
|
int32_t& aNewColCount);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fallback method: Call this after using ClearSelection() and you
|
|
|
|
* failed to set selection to some other content in the document.
|
|
|
|
*/
|
|
|
|
nsresult SetSelectionAtDocumentStart(Selection* aSelection);
|
|
|
|
|
|
|
|
// End of Table Editing utilities
|
|
|
|
|
|
|
|
static Element* GetEnclosingTable(nsINode* aNode);
|
|
|
|
static nsIDOMNode* GetEnclosingTable(nsIDOMNode* aNode);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Content-based query returns true if <aProperty aAttribute=aValue> effects
|
|
|
|
* aNode. If <aProperty aAttribute=aValue> contains aNode, but
|
|
|
|
* <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
|
|
|
|
* more deeply nested than the first, then the first does not effect aNode.
|
|
|
|
*
|
|
|
|
* @param aNode The target of the query
|
|
|
|
* @param aProperty The property that we are querying for
|
|
|
|
* @param aAttribute The attribute of aProperty, example: color in
|
|
|
|
* <FONT color="blue"> May be null.
|
|
|
|
* @param aValue The value of aAttribute, example: blue in
|
|
|
|
* <FONT color="blue"> May be null. Ignored if aAttribute
|
|
|
|
* is null.
|
|
|
|
* @param outValue [OUT] the value of the attribute, if aIsSet is true
|
2017-10-12 10:28:28 +03:00
|
|
|
* @return true if <aProperty aAttribute=aValue> effects
|
|
|
|
* aNode.
|
2016-07-09 05:42:33 +03:00
|
|
|
*
|
|
|
|
* The nsIContent variant returns aIsSet instead of using an out parameter.
|
|
|
|
*/
|
|
|
|
bool IsTextPropertySetByContent(nsINode* aNode,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString* aValue,
|
|
|
|
nsAString* outValue = nullptr);
|
|
|
|
|
|
|
|
// Methods for handling plaintext quotations
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult PasteAsPlaintextQuotation(int32_t aSelectionType);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert a string as quoted text, replacing the selected text (if any).
|
|
|
|
* @param aQuotedText The string to insert.
|
|
|
|
* @param aAddCites Whether to prepend extra ">" to each line
|
|
|
|
* (usually true, unless those characters
|
|
|
|
* have already been added.)
|
|
|
|
* @return aNodeInserted The node spanning the insertion, if applicable.
|
|
|
|
* If aAddCites is false, this will be null.
|
|
|
|
*/
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult InsertAsPlaintextQuotation(const nsAString& aQuotedText,
|
|
|
|
bool aAddCites,
|
|
|
|
nsIDOMNode** aNodeInserted);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2016-10-26 05:10:29 +03:00
|
|
|
nsresult InsertObject(const nsACString& aType, nsISupports* aObject,
|
|
|
|
bool aIsSafe,
|
2018-04-06 08:53:05 +03:00
|
|
|
nsIDocument* aSourceDoc,
|
2018-03-27 14:19:35 +03:00
|
|
|
nsINode* aDestinationNode,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aDestOffset,
|
|
|
|
bool aDoDeleteSelection);
|
|
|
|
|
|
|
|
// factored methods for handling insertion of data from transferables
|
|
|
|
// (drag&drop or clipboard)
|
Bug 1463327 - part 2: Change scope of some methods of TextEditor which won't be called by non-helper classes of editing to protected r=m_kato
TextEditor has 2 type of public methods. One is true-public methods. I.e.,
they should be able to be called by anybody. E.g., command handlers, event
listeners, or JS via nsIEditor interface. The other is semi-public methods.
They are not called by the above examples but called by other classes which
are helper classes to handle edit actions. E.g., TextEditRules, HTMLEditRules,
HTMLEditUtils, CSSEditUtils and Transaction classes.
When we will implement InputEvent.inputType, we need to create new stack
class and create its instance at every true-public methods to manage current
inputType (like TextEditRules::AutoSafeEditorData). Therefore, it should not
happen that new code starts to call semi-public methods without the new
stack class instance.
For preventing this issue, we should make TextEditor have only the true-public
methods as public. The other public methods should be protected and their
users should be friend classes. Then, we can protect such method from external
classes.
Note that this patch just moves the methods without any changes in TextEditor.h.
MozReview-Commit-ID: Db3H6d1V8IU
--HG--
extra : rebase_source : d928a6bb378d02944c5a207de83211c33bb63613
2018-05-22 10:40:44 +03:00
|
|
|
virtual nsresult PrepareTransferable(nsITransferable** transferable) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult PrepareHTMLTransferable(nsITransferable** transferable);
|
|
|
|
nsresult InsertFromTransferable(nsITransferable* transferable,
|
2018-04-06 08:53:05 +03:00
|
|
|
nsIDocument* aSourceDoc,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString& aContextStr,
|
|
|
|
const nsAString& aInfoStr,
|
|
|
|
bool havePrivateHTMLFlavor,
|
|
|
|
bool aDoDeleteSelection);
|
2017-02-01 11:09:54 +03:00
|
|
|
virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
|
|
|
|
int32_t aIndex,
|
2018-04-06 08:53:05 +03:00
|
|
|
nsIDocument* aSourceDoc,
|
2018-03-27 14:19:35 +03:00
|
|
|
nsINode* aDestinationNode,
|
2017-02-01 11:09:54 +03:00
|
|
|
int32_t aDestOffset,
|
|
|
|
bool aDoDeleteSelection) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
bool HavePrivateHTMLFlavor(nsIClipboard* clipboard );
|
|
|
|
nsresult ParseCFHTML(nsCString& aCfhtml, char16_t** aStuffToPaste,
|
|
|
|
char16_t** aCfcontext);
|
|
|
|
|
2018-01-30 07:10:52 +03:00
|
|
|
bool IsInLink(nsINode* aNode, nsCOMPtr<nsINode>* outLink = nullptr);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false);
|
|
|
|
nsresult CreateDOMFragmentFromPaste(const nsAString& aInputString,
|
|
|
|
const nsAString& aContextStr,
|
|
|
|
const nsAString& aInfoStr,
|
2018-01-30 07:10:51 +03:00
|
|
|
nsCOMPtr<nsINode>* outFragNode,
|
|
|
|
nsCOMPtr<nsINode>* outStartNode,
|
|
|
|
nsCOMPtr<nsINode>* outEndNode,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t* outStartOffset,
|
|
|
|
int32_t* outEndOffset,
|
|
|
|
bool aTrustedInput);
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult ParseFragment(const nsAString& aStr, nsAtom* aContextLocalName,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIDocument* aTargetDoc,
|
|
|
|
dom::DocumentFragment** aFragment, bool aTrustedInput);
|
|
|
|
void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment,
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& outNodeList,
|
2017-07-11 17:10:42 +03:00
|
|
|
nsINode* aStartContainer,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aStartOffset,
|
2017-07-11 18:09:37 +03:00
|
|
|
nsINode* aEndContainer,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aEndOffset);
|
|
|
|
nsresult CreateTagStack(nsTArray<nsString>& aTagStack,
|
|
|
|
nsIDOMNode* aNode);
|
|
|
|
enum class StartOrEnd { start, end };
|
|
|
|
void GetListAndTableParents(StartOrEnd aStartOrEnd,
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& aNodeList,
|
|
|
|
nsTArray<OwningNonNull<Element>>& outArray);
|
|
|
|
int32_t DiscoverPartialListsAndTables(
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
|
|
|
|
nsTArray<OwningNonNull<Element>>& aListsAndTables);
|
|
|
|
nsINode* ScanForListAndTableStructure(
|
|
|
|
StartOrEnd aStartOrEnd,
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& aNodes,
|
|
|
|
Element& aListOrTable);
|
|
|
|
void ReplaceOrphanedStructure(
|
|
|
|
StartOrEnd aStartOrEnd,
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& aNodeArray,
|
|
|
|
nsTArray<OwningNonNull<Element>>& aListAndTableArray,
|
|
|
|
int32_t aHighWaterMark);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Small utility routine to test if a break node is visible to user.
|
|
|
|
*/
|
2017-07-21 10:10:10 +03:00
|
|
|
bool IsVisibleBRElement(nsINode* aNode);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
2017-12-05 09:36:49 +03:00
|
|
|
* GetBetterInsertionPointFor() returns better insertion point to insert
|
|
|
|
* aNodeToInsert.
|
|
|
|
*
|
|
|
|
* @param aNodeToInsert The node to insert.
|
|
|
|
* @param aPointToInsert A candidate point to insert the node.
|
|
|
|
* @return Better insertion point if next visible node
|
|
|
|
* is a <br> element and previous visible node
|
|
|
|
* is neither none, another <br> element nor
|
|
|
|
* different block level element.
|
|
|
|
*/
|
|
|
|
EditorRawDOMPoint
|
|
|
|
GetBetterInsertionPointFor(nsINode& aNodeToInsert,
|
|
|
|
const EditorRawDOMPoint& aPointToInsert);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
2018-04-16 14:33:27 +03:00
|
|
|
* MakeDefinitionListItemWithTransaction() replaces parent list of current
|
|
|
|
* selection with <dl> or create new <dl> element and creates a definition
|
|
|
|
* list item whose name is aTagName.
|
|
|
|
*
|
|
|
|
* @param aTagName Must be nsGkAtoms::dt or nsGkAtoms::dd.
|
|
|
|
*/
|
|
|
|
nsresult MakeDefinitionListItemWithTransaction(nsAtom& aTagName);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* InsertBasicBlockWithTransaction() inserts a block element whose name
|
|
|
|
* is aTagName at selection.
|
|
|
|
*
|
|
|
|
* @param aTagName A block level element name. Must NOT be
|
|
|
|
* nsGkAtoms::dt nor nsGkAtoms::dd.
|
2016-07-09 05:42:33 +03:00
|
|
|
*/
|
2018-04-16 14:33:27 +03:00
|
|
|
nsresult InsertBasicBlockWithTransaction(nsAtom& aTagName);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Increase/decrease the font size of selection.
|
|
|
|
*/
|
|
|
|
enum class FontSize { incr, decr };
|
|
|
|
nsresult RelativeFontChange(FontSize aDir);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper routines for font size changing.
|
|
|
|
*/
|
|
|
|
nsresult RelativeFontChangeOnTextNode(FontSize aDir,
|
|
|
|
Text& aTextNode,
|
|
|
|
int32_t aStartOffset,
|
|
|
|
int32_t aEndOffset);
|
|
|
|
nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
|
|
|
|
nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper routines for inline style.
|
|
|
|
*/
|
|
|
|
nsresult SetInlinePropertyOnTextNode(Text& aData,
|
|
|
|
int32_t aStartOffset,
|
|
|
|
int32_t aEndOffset,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom& aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString& aValue);
|
|
|
|
nsresult SetInlinePropertyOnNode(nsIContent& aNode,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom& aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString& aValue);
|
|
|
|
|
|
|
|
nsresult PromoteInlineRange(nsRange& aRange);
|
|
|
|
nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
|
|
|
|
nsresult SplitStyleAboveRange(nsRange* aRange,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIContent** aOutLeftNode = nullptr,
|
|
|
|
nsIContent** aOutRightNode = nullptr);
|
|
|
|
nsresult RemoveStyleInside(nsIContent& aNode,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const bool aChildrenOnly = false);
|
|
|
|
|
|
|
|
bool NodeIsProperty(nsINode& aNode);
|
|
|
|
bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset);
|
|
|
|
bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset);
|
2017-12-26 06:25:45 +03:00
|
|
|
bool IsOnlyAttribute(const Element* aElement, nsAtom* aAttribute);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-12 16:23:04 +03:00
|
|
|
/**
|
|
|
|
* RemoveBlockContainerWithTransaction() removes aElement from the DOM tree
|
|
|
|
* but moves its all children to its parent node and if its parent needs <br>
|
|
|
|
* element to have at least one line-height, this inserts <br> element
|
|
|
|
* automatically.
|
|
|
|
*
|
|
|
|
* @param aElement Block element to be removed.
|
|
|
|
*/
|
|
|
|
nsresult RemoveBlockContainerWithTransaction(Element& aElement);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsIContent* GetPriorHTMLSibling(nsINode* aNode);
|
|
|
|
|
|
|
|
nsIContent* GetNextHTMLSibling(nsINode* aNode);
|
|
|
|
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
/**
|
|
|
|
* GetPreviousHTMLElementOrText*() methods are similar to
|
|
|
|
* EditorBase::GetPreviousElementOrText*() but this won't return nodes
|
|
|
|
* outside active editing host.
|
|
|
|
*/
|
|
|
|
nsIContent* GetPreviousHTMLElementOrText(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetPreviousHTMLElementOrTextInternal(aNode, false);
|
|
|
|
}
|
|
|
|
nsIContent* GetPreviousHTMLElementOrTextInBlock(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetPreviousHTMLElementOrTextInternal(aNode, true);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetPreviousHTMLElementOrText(const EditorDOMPointBase<PT, CT>& aPoint)
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
{
|
|
|
|
return GetPreviousHTMLElementOrTextInternal(aPoint, false);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
nsIContent*
|
2018-03-20 08:05:47 +03:00
|
|
|
GetPreviousHTMLElementOrTextInBlock(const EditorDOMPointBase<PT, CT>& aPoint)
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
{
|
|
|
|
return GetPreviousHTMLElementOrTextInternal(aPoint, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetPreviousHTMLElementOrTextInternal() methods are common implementation
|
|
|
|
* of above methods. Please don't use this method directly.
|
|
|
|
*/
|
|
|
|
nsIContent* GetPreviousHTMLElementOrTextInternal(nsINode& aNode,
|
|
|
|
bool aNoBlockCrossing);
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
nsIContent*
|
2018-03-20 08:05:47 +03:00
|
|
|
GetPreviousHTMLElementOrTextInternal(const EditorDOMPointBase<PT, CT>& aPoint,
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
bool aNoBlockCrossing);
|
|
|
|
|
2017-11-09 17:31:59 +03:00
|
|
|
/**
|
|
|
|
* GetPreviousEditableHTMLNode*() methods are similar to
|
|
|
|
* EditorBase::GetPreviousEditableNode() but this won't return nodes outside
|
|
|
|
* active editing host.
|
|
|
|
*/
|
|
|
|
nsIContent* GetPreviousEditableHTMLNode(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetPreviousEditableHTMLNodeInternal(aNode, false);
|
|
|
|
}
|
|
|
|
nsIContent* GetPreviousEditableHTMLNodeInBlock(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetPreviousEditableHTMLNodeInternal(aNode, true);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetPreviousEditableHTMLNode(const EditorDOMPointBase<PT, CT>& aPoint)
|
2017-11-09 17:31:59 +03:00
|
|
|
{
|
|
|
|
return GetPreviousEditableHTMLNodeInternal(aPoint, false);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
2017-11-09 17:31:59 +03:00
|
|
|
nsIContent* GetPreviousEditableHTMLNodeInBlock(
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint)
|
2017-11-09 17:31:59 +03:00
|
|
|
{
|
|
|
|
return GetPreviousEditableHTMLNodeInternal(aPoint, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetPreviousEditableHTMLNodeInternal() methods are common implementation
|
|
|
|
* of above methods. Please don't use this method directly.
|
|
|
|
*/
|
|
|
|
nsIContent* GetPreviousEditableHTMLNodeInternal(nsINode& aNode,
|
|
|
|
bool aNoBlockCrossing);
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
2017-11-09 17:31:59 +03:00
|
|
|
nsIContent* GetPreviousEditableHTMLNodeInternal(
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint,
|
2017-11-09 17:31:59 +03:00
|
|
|
bool aNoBlockCrossing);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
/**
|
|
|
|
* GetNextHTMLElementOrText*() methods are similar to
|
|
|
|
* EditorBase::GetNextElementOrText*() but this won't return nodes outside
|
|
|
|
* active editing host.
|
|
|
|
*
|
|
|
|
* Note that same as EditorBase::GetTextEditableNode(), methods which take
|
|
|
|
* |const EditorRawDOMPoint&| start to search from the node pointed by it.
|
|
|
|
* On the other hand, methods which take |nsINode&| start to search from
|
|
|
|
* next node of aNode.
|
|
|
|
*/
|
|
|
|
nsIContent* GetNextHTMLElementOrText(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetNextHTMLElementOrTextInternal(aNode, false);
|
|
|
|
}
|
|
|
|
nsIContent* GetNextHTMLElementOrTextInBlock(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetNextHTMLElementOrTextInternal(aNode, true);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetNextHTMLElementOrText(const EditorDOMPointBase<PT, CT>& aPoint)
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
{
|
|
|
|
return GetNextHTMLElementOrTextInternal(aPoint, false);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetNextHTMLElementOrTextInBlock(const EditorDOMPointBase<PT, CT>& aPoint)
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
{
|
|
|
|
return GetNextHTMLElementOrTextInternal(aPoint, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetNextHTMLNodeInternal() methods are common implementation
|
|
|
|
* of above methods. Please don't use this method directly.
|
|
|
|
*/
|
|
|
|
nsIContent* GetNextHTMLElementOrTextInternal(nsINode& aNode,
|
|
|
|
bool aNoBlockCrossing);
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetNextHTMLElementOrTextInternal(const EditorDOMPointBase<PT, CT>& aPoint,
|
|
|
|
bool aNoBlockCrossing);
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
|
2017-11-09 18:12:22 +03:00
|
|
|
/**
|
|
|
|
* GetNextEditableHTMLNode*() methods are similar to
|
|
|
|
* EditorBase::GetNextEditableNode() but this won't return nodes outside
|
|
|
|
* active editing host.
|
|
|
|
*
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
* Note that same as EditorBase::GetTextEditableNode(), methods which take
|
2017-11-09 18:12:22 +03:00
|
|
|
* |const EditorRawDOMPoint&| start to search from the node pointed by it.
|
|
|
|
* On the other hand, methods which take |nsINode&| start to search from
|
|
|
|
* next node of aNode.
|
|
|
|
*/
|
|
|
|
nsIContent* GetNextEditableHTMLNode(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetNextEditableHTMLNodeInternal(aNode, false);
|
|
|
|
}
|
|
|
|
nsIContent* GetNextEditableHTMLNodeInBlock(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetNextEditableHTMLNodeInternal(aNode, true);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent* GetNextEditableHTMLNode(const EditorDOMPointBase<PT, CT>& aPoint)
|
2017-11-09 18:12:22 +03:00
|
|
|
{
|
|
|
|
return GetNextEditableHTMLNodeInternal(aPoint, false);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
2017-11-09 18:12:22 +03:00
|
|
|
nsIContent* GetNextEditableHTMLNodeInBlock(
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint)
|
2017-11-09 18:12:22 +03:00
|
|
|
{
|
|
|
|
return GetNextEditableHTMLNodeInternal(aPoint, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetNextEditableHTMLNodeInternal() methods are common implementation
|
|
|
|
* of above methods. Please don't use this method directly.
|
|
|
|
*/
|
|
|
|
nsIContent* GetNextEditableHTMLNodeInternal(nsINode& aNode,
|
2018-03-20 08:05:47 +03:00
|
|
|
bool aNoBlockCrossing);
|
|
|
|
template<typename PT, typename CT>
|
2017-11-09 18:12:22 +03:00
|
|
|
nsIContent* GetNextEditableHTMLNodeInternal(
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint,
|
2017-11-09 18:12:22 +03:00
|
|
|
bool aNoBlockCrossing);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-01-11 13:07:33 +03:00
|
|
|
bool IsFirstEditableChild(nsINode* aNode);
|
|
|
|
bool IsLastEditableChild(nsINode* aNode);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIContent* GetFirstEditableChild(nsINode& aNode);
|
|
|
|
nsIContent* GetLastEditableChild(nsINode& aNode);
|
|
|
|
|
|
|
|
nsIContent* GetFirstEditableLeaf(nsINode& aNode);
|
|
|
|
nsIContent* GetLastEditableLeaf(nsINode& aNode);
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult GetInlinePropertyBase(nsAtom& aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString* aValue,
|
|
|
|
bool* aFirst,
|
|
|
|
bool* aAny,
|
|
|
|
bool* aAll,
|
2017-08-25 09:59:17 +03:00
|
|
|
nsAString* outValue);
|
2016-07-09 05:42:33 +03:00
|
|
|
bool HasStyleOrIdOrClass(Element* aElement);
|
|
|
|
nsresult RemoveElementIfNoStyleOrIdOrClass(Element& aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether the outer window of the DOM event target has focus or not.
|
|
|
|
*/
|
|
|
|
bool OurWindowHasFocus();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function is used to insert a string of HTML input optionally with some
|
|
|
|
* context information into the editable field. The HTML input either comes
|
|
|
|
* from a transferable object created as part of a drop/paste operation, or
|
|
|
|
* from the InsertHTML method. We may want the HTML input to be sanitized
|
|
|
|
* (for example, if it's coming from a transferable object), in which case
|
|
|
|
* aTrustedInput should be set to false, otherwise, the caller should set it
|
|
|
|
* to true, which means that the HTML will be inserted in the DOM verbatim.
|
|
|
|
*
|
|
|
|
* aClearStyle should be set to false if you want the paste to be affected by
|
|
|
|
* local style (e.g., for the insertHTML command).
|
|
|
|
*/
|
|
|
|
nsresult DoInsertHTMLWithContext(const nsAString& aInputString,
|
|
|
|
const nsAString& aContextStr,
|
|
|
|
const nsAString& aInfoStr,
|
|
|
|
const nsAString& aFlavor,
|
2018-04-06 08:53:05 +03:00
|
|
|
nsIDocument* aSourceDoc,
|
2018-03-27 14:19:35 +03:00
|
|
|
nsINode* aDestNode,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aDestOffset,
|
|
|
|
bool aDeleteSelection,
|
|
|
|
bool aTrustedInput,
|
|
|
|
bool aClearStyle = true);
|
|
|
|
|
|
|
|
nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aProperty, nsAtom* aAttribute);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
/**
|
|
|
|
* sets the position of an element; warning it does NOT check if the
|
|
|
|
* element is already positioned or not and that's on purpose.
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
* @param aX [IN] the x position in pixels.
|
|
|
|
* @param aY [IN] the y position in pixels.
|
|
|
|
*/
|
|
|
|
void SetTopAndLeft(Element& aElement, int32_t aX, int32_t aY);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-08-08 04:57:19 +03:00
|
|
|
/**
|
|
|
|
* Reset a selected cell or collapsed selection (the caret) after table
|
|
|
|
* editing.
|
|
|
|
*
|
|
|
|
* @param aTable A table in the document.
|
|
|
|
* @param aRow The row ...
|
|
|
|
* @param aCol ... and column defining the cell where we will try to
|
|
|
|
* place the caret.
|
|
|
|
* @param aSelected If true, we select the whole cell instead of setting
|
|
|
|
* caret.
|
|
|
|
* @param aDirection If cell at (aCol, aRow) is not found, search for
|
|
|
|
* previous cell in the same column (aPreviousColumn) or
|
|
|
|
* row (ePreviousRow) or don't search for another cell
|
|
|
|
* (aNoSearch). If no cell is found, caret is place just
|
|
|
|
* before table; and if that fails, at beginning of
|
|
|
|
* document. Thus we generally don't worry about the
|
|
|
|
* return value and can use the
|
|
|
|
* AutoSelectionSetterAfterTableEdit stack-based object to
|
|
|
|
* insure we reset the caret in a table-editing method.
|
|
|
|
*/
|
2018-04-27 06:35:18 +03:00
|
|
|
void SetSelectionAfterTableEdit(Element* aTable,
|
2017-08-08 04:57:19 +03:00
|
|
|
int32_t aRow, int32_t aCol,
|
|
|
|
int32_t aDirection, bool aSelected);
|
|
|
|
|
2018-01-30 07:27:59 +03:00
|
|
|
/**
|
|
|
|
* A more C++-friendly version of nsIHTMLEditor::GetSelectedElement
|
|
|
|
* that just returns null on errors.
|
|
|
|
*/
|
|
|
|
already_AddRefed<dom::Element> GetSelectedElement(const nsAString& aTagName);
|
|
|
|
|
2018-04-12 11:20:21 +03:00
|
|
|
/**
|
|
|
|
* RemoveStyleSheetWithTransaction() removes the given URL stylesheet
|
|
|
|
* from mStyleSheets and mStyleSheetURLs.
|
|
|
|
*/
|
|
|
|
nsresult RemoveStyleSheetWithTransaction(const nsAString& aURL);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
protected:
|
|
|
|
RefPtr<TypeInState> mTypeInState;
|
2018-01-26 08:38:05 +03:00
|
|
|
RefPtr<ComposerCommandsUpdater> mComposerCommandsUpdater;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
bool mCRInParagraphCreatesParagraph;
|
|
|
|
|
|
|
|
bool mCSSAware;
|
2017-02-08 12:14:24 +03:00
|
|
|
UniquePtr<CSSEditUtils> mCSSEditUtils;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// Used by GetFirstSelectedCell and GetNextSelectedCell
|
|
|
|
int32_t mSelectedCellIndex;
|
|
|
|
|
|
|
|
nsString mLastStyleSheetURL;
|
|
|
|
nsString mLastOverrideStyleSheetURL;
|
|
|
|
|
|
|
|
// Maintain a list of associated style sheets and their urls.
|
|
|
|
nsTArray<nsString> mStyleSheetURLs;
|
2016-09-26 15:03:25 +03:00
|
|
|
nsTArray<RefPtr<StyleSheet>> mStyleSheets;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
protected:
|
|
|
|
// ANONYMOUS UTILS
|
|
|
|
void RemoveListenerAndDeleteRef(const nsAString& aEvent,
|
|
|
|
nsIDOMEventListener* aListener,
|
|
|
|
bool aUseCapture,
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr aElement,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIPresShell* aShell);
|
2017-08-02 22:37:44 +03:00
|
|
|
void DeleteRefToAnonymousNode(ManualNACPtr aContent,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIPresShell* aShell);
|
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
nsresult ShowResizersInner(Element& aResizedElement);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the offset of an element's frame to its absolute containing block.
|
|
|
|
*/
|
2017-08-07 08:09:51 +03:00
|
|
|
nsresult GetElementOrigin(Element& aElement,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t& aX, int32_t& aY);
|
2017-08-07 08:09:51 +03:00
|
|
|
nsresult GetPositionAndDimensions(Element& aElement,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t& aX, int32_t& aY,
|
|
|
|
int32_t& aW, int32_t& aH,
|
|
|
|
int32_t& aBorderLeft,
|
|
|
|
int32_t& aBorderTop,
|
|
|
|
int32_t& aMarginLeft,
|
|
|
|
int32_t& aMarginTop);
|
|
|
|
|
2018-03-01 14:36:58 +03:00
|
|
|
bool IsInObservedSubtree(nsIContent* aChild);
|
2016-11-30 01:07:27 +03:00
|
|
|
|
2017-08-28 21:57:46 +03:00
|
|
|
void UpdateRootElement();
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
// resizing
|
Bug 1452538 - Add telemetry probes HTMLEditors which have shown Gecko build-in editing UIs and count of user interaction with them r=Ehsan
Gecko has some built-in UIs:
* to edit size of objects like <img>, <table> and absolute positioned elements.
* to edit position of absolute positioned elements.
* to add/remove table columns and rows.
Currently, those UIs are available in both designMode editor and contenteditable
editor only on Gecko. I.e., the other browsers' users cannot modify as such
without web apps implement such function. So, for compatibility with the
other browsers, we should hide those UIs by default. On the other hand, if
this is too risky for backward compatibility, we should not do that.
So, before doing that, we should collect actual usage data of object resizers,
inline table editing UI, positioning UI of absolute positioned elements with
telemetry probes.
This patch adds 3 sets of probes for each UI. One is percentage of showing
each UI in all instantiated HTMLEditor. The other is number of user interaction
of each UI in HTMLEditors which has shown the UI.
This patch makes all new probes as "opt-out" because they are really important
data since used for deciding whether those UIs are necessary or unnecessary.
MozReview-Commit-ID: B9Y6GTiCPw6
--HG--
extra : rebase_source : 00e49f31712e24cb269ad3aa65c7d13b7cccb3a5
2018-04-09 11:31:23 +03:00
|
|
|
// If the instance has shown resizers at least once, mHasShownResizers is
|
|
|
|
// set to true.
|
|
|
|
bool mHasShownResizers;
|
2016-07-09 05:42:33 +03:00
|
|
|
bool mIsObjectResizingEnabled;
|
|
|
|
bool mIsResizing;
|
|
|
|
bool mPreserveRatio;
|
|
|
|
bool mResizedObjectIsAnImage;
|
|
|
|
|
|
|
|
// absolute positioning
|
|
|
|
bool mIsAbsolutelyPositioningEnabled;
|
|
|
|
bool mResizedObjectIsAbsolutelyPositioned;
|
Bug 1452538 - Add telemetry probes HTMLEditors which have shown Gecko build-in editing UIs and count of user interaction with them r=Ehsan
Gecko has some built-in UIs:
* to edit size of objects like <img>, <table> and absolute positioned elements.
* to edit position of absolute positioned elements.
* to add/remove table columns and rows.
Currently, those UIs are available in both designMode editor and contenteditable
editor only on Gecko. I.e., the other browsers' users cannot modify as such
without web apps implement such function. So, for compatibility with the
other browsers, we should hide those UIs by default. On the other hand, if
this is too risky for backward compatibility, we should not do that.
So, before doing that, we should collect actual usage data of object resizers,
inline table editing UI, positioning UI of absolute positioned elements with
telemetry probes.
This patch adds 3 sets of probes for each UI. One is percentage of showing
each UI in all instantiated HTMLEditor. The other is number of user interaction
of each UI in HTMLEditors which has shown the UI.
This patch makes all new probes as "opt-out" because they are really important
data since used for deciding whether those UIs are necessary or unnecessary.
MozReview-Commit-ID: B9Y6GTiCPw6
--HG--
extra : rebase_source : 00e49f31712e24cb269ad3aa65c7d13b7cccb3a5
2018-04-09 11:31:23 +03:00
|
|
|
// If the instance has shown grabber at least once, mHasShownGrabber is
|
|
|
|
// set to true.
|
|
|
|
bool mHasShownGrabber;
|
2016-07-09 05:42:33 +03:00
|
|
|
bool mGrabberClicked;
|
|
|
|
bool mIsMoving;
|
|
|
|
|
|
|
|
bool mSnapToGridEnabled;
|
|
|
|
|
|
|
|
// inline table editing
|
Bug 1452538 - Add telemetry probes HTMLEditors which have shown Gecko build-in editing UIs and count of user interaction with them r=Ehsan
Gecko has some built-in UIs:
* to edit size of objects like <img>, <table> and absolute positioned elements.
* to edit position of absolute positioned elements.
* to add/remove table columns and rows.
Currently, those UIs are available in both designMode editor and contenteditable
editor only on Gecko. I.e., the other browsers' users cannot modify as such
without web apps implement such function. So, for compatibility with the
other browsers, we should hide those UIs by default. On the other hand, if
this is too risky for backward compatibility, we should not do that.
So, before doing that, we should collect actual usage data of object resizers,
inline table editing UI, positioning UI of absolute positioned elements with
telemetry probes.
This patch adds 3 sets of probes for each UI. One is percentage of showing
each UI in all instantiated HTMLEditor. The other is number of user interaction
of each UI in HTMLEditors which has shown the UI.
This patch makes all new probes as "opt-out" because they are really important
data since used for deciding whether those UIs are necessary or unnecessary.
MozReview-Commit-ID: B9Y6GTiCPw6
--HG--
extra : rebase_source : 00e49f31712e24cb269ad3aa65c7d13b7cccb3a5
2018-04-09 11:31:23 +03:00
|
|
|
// If the instance has shown inline table editor at least once,
|
|
|
|
// mHasShownInlineTableEditor is set to true.
|
|
|
|
bool mHasShownInlineTableEditor;
|
2016-07-09 05:42:33 +03:00
|
|
|
bool mIsInlineTableEditingEnabled;
|
|
|
|
|
|
|
|
// resizing
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mTopLeftHandle;
|
|
|
|
ManualNACPtr mTopHandle;
|
|
|
|
ManualNACPtr mTopRightHandle;
|
|
|
|
ManualNACPtr mLeftHandle;
|
|
|
|
ManualNACPtr mRightHandle;
|
|
|
|
ManualNACPtr mBottomLeftHandle;
|
|
|
|
ManualNACPtr mBottomHandle;
|
|
|
|
ManualNACPtr mBottomRightHandle;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsCOMPtr<Element> mActivatedHandle;
|
|
|
|
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mResizingShadow;
|
|
|
|
ManualNACPtr mResizingInfo;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-27 06:35:18 +03:00
|
|
|
RefPtr<Element> mResizedObject;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP;
|
|
|
|
nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP;
|
|
|
|
|
|
|
|
int32_t mOriginalX;
|
|
|
|
int32_t mOriginalY;
|
|
|
|
|
|
|
|
int32_t mResizedObjectX;
|
|
|
|
int32_t mResizedObjectY;
|
|
|
|
int32_t mResizedObjectWidth;
|
|
|
|
int32_t mResizedObjectHeight;
|
|
|
|
|
|
|
|
int32_t mResizedObjectMarginLeft;
|
|
|
|
int32_t mResizedObjectMarginTop;
|
|
|
|
int32_t mResizedObjectBorderLeft;
|
|
|
|
int32_t mResizedObjectBorderTop;
|
|
|
|
|
|
|
|
int32_t mXIncrementFactor;
|
|
|
|
int32_t mYIncrementFactor;
|
|
|
|
int32_t mWidthIncrementFactor;
|
|
|
|
int32_t mHeightIncrementFactor;
|
|
|
|
|
Bug 1452538 - Add telemetry probes HTMLEditors which have shown Gecko build-in editing UIs and count of user interaction with them r=Ehsan
Gecko has some built-in UIs:
* to edit size of objects like <img>, <table> and absolute positioned elements.
* to edit position of absolute positioned elements.
* to add/remove table columns and rows.
Currently, those UIs are available in both designMode editor and contenteditable
editor only on Gecko. I.e., the other browsers' users cannot modify as such
without web apps implement such function. So, for compatibility with the
other browsers, we should hide those UIs by default. On the other hand, if
this is too risky for backward compatibility, we should not do that.
So, before doing that, we should collect actual usage data of object resizers,
inline table editing UI, positioning UI of absolute positioned elements with
telemetry probes.
This patch adds 3 sets of probes for each UI. One is percentage of showing
each UI in all instantiated HTMLEditor. The other is number of user interaction
of each UI in HTMLEditors which has shown the UI.
This patch makes all new probes as "opt-out" because they are really important
data since used for deciding whether those UIs are necessary or unnecessary.
MozReview-Commit-ID: B9Y6GTiCPw6
--HG--
extra : rebase_source : 00e49f31712e24cb269ad3aa65c7d13b7cccb3a5
2018-04-09 11:31:23 +03:00
|
|
|
// When resizers, grabber and/or inline table editor are operated by user
|
|
|
|
// actually, the following counters are increased.
|
|
|
|
uint32_t mResizerUsedCount;
|
|
|
|
uint32_t mGrabberUsedCount;
|
|
|
|
uint32_t mInlineTableEditorUsedCount;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
int8_t mInfoXIncrement;
|
|
|
|
int8_t mInfoYIncrement;
|
|
|
|
|
|
|
|
nsresult SetAllResizersPosition();
|
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
/**
|
|
|
|
* Shows active resizers around an element's frame
|
|
|
|
* @param aResizedElement [IN] a DOM Element
|
|
|
|
*/
|
|
|
|
nsresult ShowResizers(Element& aResizedElement);
|
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
ManualNACPtr CreateResizer(int16_t aLocation, nsIContent& aParentContent);
|
2016-07-09 05:42:33 +03:00
|
|
|
void SetAnonymousElementPosition(int32_t aX, int32_t aY,
|
2016-11-24 09:58:01 +03:00
|
|
|
Element* aResizer);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
ManualNACPtr CreateShadow(nsIContent& aParentContent,
|
|
|
|
Element& aOriginalObject);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult SetShadowPosition(Element* aShadow, Element* aOriginalObject,
|
|
|
|
int32_t aOriginalObjectX,
|
|
|
|
int32_t aOriginalObjectY);
|
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
ManualNACPtr CreateResizingInfo(nsIContent& aParentContent);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
|
|
|
|
int32_t aW, int32_t aH);
|
|
|
|
|
|
|
|
int32_t GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID);
|
2018-04-27 06:35:18 +03:00
|
|
|
nsresult StartResizing(Element* aHandle);
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t GetNewResizingX(int32_t aX, int32_t aY);
|
|
|
|
int32_t GetNewResizingY(int32_t aX, int32_t aY);
|
|
|
|
int32_t GetNewResizingWidth(int32_t aX, int32_t aY);
|
|
|
|
int32_t GetNewResizingHeight(int32_t aX, int32_t aY);
|
|
|
|
void HideShadowAndInfo();
|
|
|
|
void SetFinalSize(int32_t aX, int32_t aY);
|
|
|
|
void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH,
|
|
|
|
bool aPreserveRatio);
|
|
|
|
void HideAnonymousEditingUIs();
|
|
|
|
|
|
|
|
// absolute positioning
|
|
|
|
int32_t mPositionedObjectX;
|
|
|
|
int32_t mPositionedObjectY;
|
|
|
|
int32_t mPositionedObjectWidth;
|
|
|
|
int32_t mPositionedObjectHeight;
|
|
|
|
|
|
|
|
int32_t mPositionedObjectMarginLeft;
|
|
|
|
int32_t mPositionedObjectMarginTop;
|
|
|
|
int32_t mPositionedObjectBorderLeft;
|
|
|
|
int32_t mPositionedObjectBorderTop;
|
|
|
|
|
|
|
|
nsCOMPtr<Element> mAbsolutelyPositionedObject;
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mGrabber;
|
|
|
|
ManualNACPtr mPositioningShadow;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
int32_t mGridSize;
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
nsresult SetPositionToAbsolute(Element& aElement);
|
|
|
|
nsresult SetPositionToStatic(Element& aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sets the z-index of an element.
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
* @param aZorder [IN] the z-index
|
|
|
|
*/
|
|
|
|
void SetZIndex(Element& aElement, int32_t aZorder);
|
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
/**
|
|
|
|
* shows a grabber attached to an arbitrary element. The grabber is an image
|
|
|
|
* positioned on the left hand side of the top border of the element. Draggin
|
|
|
|
* and dropping it allows to change the element's absolute position in the
|
|
|
|
* document. See chrome://editor/content/images/grabber.gif
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
*/
|
2018-02-01 04:55:25 +03:00
|
|
|
nsresult ShowGrabber(Element& aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* hide the grabber if it shown.
|
|
|
|
*/
|
|
|
|
void HideGrabber();
|
2018-01-30 07:42:52 +03:00
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
ManualNACPtr CreateGrabber(nsIContent& aParentContent);
|
2018-03-19 08:14:45 +03:00
|
|
|
nsresult StartMoving();
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult SetFinalPosition(int32_t aX, int32_t aY);
|
|
|
|
void AddPositioningOffset(int32_t& aX, int32_t& aY);
|
|
|
|
void SnapToGrid(int32_t& newX, int32_t& newY);
|
|
|
|
nsresult GrabberClicked();
|
|
|
|
nsresult EndMoving();
|
2018-01-30 07:42:52 +03:00
|
|
|
nsresult GetTemporaryStyleForFocusedPositionedElement(Element& aElement,
|
|
|
|
nsAString& aReturn);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// inline table editing
|
2017-12-15 19:14:54 +03:00
|
|
|
RefPtr<Element> mInlineEditedCell;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mAddColumnBeforeButton;
|
|
|
|
ManualNACPtr mRemoveColumnButton;
|
|
|
|
ManualNACPtr mAddColumnAfterButton;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mAddRowBeforeButton;
|
|
|
|
ManualNACPtr mRemoveRowButton;
|
|
|
|
ManualNACPtr mAddRowAfterButton;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-01-19 10:41:41 +03:00
|
|
|
/**
|
|
|
|
* Shows inline table editing UI around a table cell
|
|
|
|
* @param aCell [IN] a DOM Element being a table cell, td or th
|
|
|
|
*/
|
2017-12-15 19:14:54 +03:00
|
|
|
nsresult ShowInlineTableEditingUI(Element* aCell);
|
|
|
|
|
2018-01-19 10:41:41 +03:00
|
|
|
/**
|
|
|
|
* Hide all inline table editing UI
|
|
|
|
*/
|
|
|
|
nsresult HideInlineTableEditingUI();
|
|
|
|
|
2016-11-24 09:58:01 +03:00
|
|
|
void AddMouseClickListener(Element* aElement);
|
|
|
|
void RemoveMouseClickListener(Element* aElement);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsILinkHandler> mLinkHandler;
|
|
|
|
|
2017-04-06 15:02:42 +03:00
|
|
|
ParagraphSeparator mDefaultParagraphSeparator;
|
2016-08-24 15:53:52 +03:00
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
public:
|
2017-08-08 04:57:19 +03:00
|
|
|
friend class AutoSelectionSetterAfterTableEdit;
|
2016-07-09 05:42:33 +03:00
|
|
|
friend class HTMLEditorEventListener;
|
|
|
|
friend class HTMLEditRules;
|
|
|
|
friend class TextEditRules;
|
|
|
|
friend class WSRunObject;
|
|
|
|
|
|
|
|
private:
|
Bug 1463327 - part 1: Change scope of some methods of EditorBase which won't be called by non-helper classes of editing to protected r=m_kato
EditorBase (and other editor classes) have 2 type of public methods. One is
true-public methods. I.e., they should be able to be called by anybody.
E.g., command handlers, event listeners, or JS via nsIEditor interface.
The other is semi-public methods. They are not called by the above examples
but called by other classes which are helper classes to handle edit actions.
E.g., TextEditRules, HTMLEditRules, HTMLEditUtils, CSSEditUtils and Transaction
classes.
When we will implement InputEvent.inputType, we need to create new stack
class and create its instance at every true-public methods to manage current
inputType (like TextEditRules::AutoSafeEditorData). Therefore, it should not
happen that new code starts to call semi-public methods without the new
stack class instance.
For preventing this issue, we should make EditorBase have only the true-public
methods as public. The other public methods should be protected and their
users should be friend classes. Then, we can protect such method from external
classes.
Note that this patch just moves the methods without any changes in EditorBase.h
(except removes GetName() since there is no body of this method and removes
IterDirection since it's unused).
MozReview-Commit-ID: HBseKLL6pxx
--HG--
extra : rebase_source : 2251ff659d831d01a6778d38f4e2714fcf2d6ef4
2018-05-22 10:08:43 +03:00
|
|
|
/**
|
|
|
|
* IsEmptyTextNode() returns true if aNode is a text node and does not have
|
|
|
|
* any visible characters.
|
|
|
|
*/
|
|
|
|
bool IsEmptyTextNode(nsINode& aNode);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
bool IsSimpleModifiableNode(nsIContent* aContent,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString* aValue);
|
|
|
|
nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom& aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString& aValue);
|
|
|
|
typedef enum { eInserted, eAppended } InsertedOrAppended;
|
2018-03-01 14:36:58 +03:00
|
|
|
void DoContentInserted(nsIContent* aChild, InsertedOrAppended);
|
2016-07-09 05:42:33 +03:00
|
|
|
already_AddRefed<Element> GetElementOrParentByTagName(
|
|
|
|
const nsAString& aTagName, nsINode* aNode);
|
|
|
|
already_AddRefed<Element> CreateElementWithDefaults(
|
|
|
|
const nsAString& aTagName);
|
2016-11-24 10:12:04 +03:00
|
|
|
/**
|
|
|
|
* Returns an anonymous Element of type aTag,
|
2017-08-07 08:09:51 +03:00
|
|
|
* child of aParentContent. If aIsCreatedHidden is true, the class
|
2016-11-24 10:12:04 +03:00
|
|
|
* "hidden" is added to the created element. If aAnonClass is not
|
|
|
|
* the empty string, it becomes the value of the attribute "_moz_anonclass"
|
|
|
|
* @return a Element
|
|
|
|
* @param aTag [IN] desired type of the element to create
|
2017-08-07 08:09:51 +03:00
|
|
|
* @param aParentContent [IN] the parent node of the created anonymous
|
2016-11-24 10:12:04 +03:00
|
|
|
* element
|
|
|
|
* @param aAnonClass [IN] contents of the _moz_anonclass attribute
|
|
|
|
* @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
|
|
|
|
* is to be added to the created anonymous
|
|
|
|
* element
|
|
|
|
*/
|
2017-10-03 01:05:19 +03:00
|
|
|
ManualNACPtr CreateAnonymousElement(nsAtom* aTag,
|
2017-08-07 08:09:51 +03:00
|
|
|
nsIContent& aParentContent,
|
2017-08-02 22:37:44 +03:00
|
|
|
const nsAString& aAnonClass,
|
|
|
|
bool aIsCreatedHidden);
|
2016-07-09 05:42:33 +03:00
|
|
|
};
|
|
|
|
|
2017-08-04 09:01:36 +03:00
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
mozilla::HTMLEditor*
|
|
|
|
nsIEditor::AsHTMLEditor()
|
2017-08-04 00:18:50 +03:00
|
|
|
{
|
2017-08-04 09:01:36 +03:00
|
|
|
return static_cast<mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
|
|
|
|
static_cast<mozilla::HTMLEditor*>(this) : nullptr;
|
2017-08-04 00:18:50 +03:00
|
|
|
}
|
|
|
|
|
2017-08-04 09:01:36 +03:00
|
|
|
const mozilla::HTMLEditor*
|
|
|
|
nsIEditor::AsHTMLEditor() const
|
2017-08-04 00:18:50 +03:00
|
|
|
{
|
2017-08-04 09:01:36 +03:00
|
|
|
return static_cast<const mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
|
|
|
|
static_cast<const mozilla::HTMLEditor*>(this) : nullptr;
|
2017-08-04 00:18:50 +03:00
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
#endif // #ifndef mozilla_HTMLEditor_h
|