зеркало из https://github.com/mozilla/gecko-dev.git
Bug 50660 - Drag and drop for file upload form control r=jst,enndeakin
This commit is contained in:
Родитель
d1ba1be886
Коммит
4d6f07caf9
|
@ -1372,6 +1372,31 @@ nsHTMLInputElement::SetFiles(const nsCOMArray<nsIDOMFile>& aFiles,
|
|||
mFiles.Clear();
|
||||
mFiles.AppendObjects(aFiles);
|
||||
|
||||
AfterSetFiles(aSetValueChanged);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLInputElement::SetFiles(nsIDOMFileList* aFiles,
|
||||
bool aSetValueChanged)
|
||||
{
|
||||
mFiles.Clear();
|
||||
|
||||
if (aFiles) {
|
||||
PRUint32 listLength;
|
||||
aFiles->GetLength(&listLength);
|
||||
for (PRUint32 i = 0; i < listLength; i++) {
|
||||
nsCOMPtr<nsIDOMFile> file;
|
||||
aFiles->Item(i, getter_AddRefs(file));
|
||||
mFiles.AppendObject(file);
|
||||
}
|
||||
}
|
||||
|
||||
AfterSetFiles(aSetValueChanged);
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLInputElement::AfterSetFiles(bool aSetValueChanged)
|
||||
{
|
||||
// No need to flush here, if there's no frame at this point we
|
||||
// don't need to force creation of one just to tell it about this
|
||||
// new value. We just want the display to update as needed.
|
||||
|
|
|
@ -145,11 +145,11 @@ public:
|
|||
{
|
||||
return nsGenericHTMLElement::GetEditor(aEditor);
|
||||
}
|
||||
|
||||
// Forward nsIDOMHTMLElement
|
||||
NS_FORWARD_NSIDOMHTMLELEMENT_NOFOCUSCLICK(nsGenericHTMLFormElement::)
|
||||
NS_IMETHOD Focus();
|
||||
NS_IMETHOD Click();
|
||||
|
||||
// Forward nsIDOMHTMLElement
|
||||
NS_FORWARD_NSIDOMHTMLELEMENT_NOFOCUSCLICK(nsGenericHTMLFormElement::)
|
||||
NS_IMETHOD Focus();
|
||||
NS_IMETHOD Click();
|
||||
|
||||
NS_IMETHOD SetUserInput(const nsAString& aInput);
|
||||
|
||||
|
@ -218,6 +218,7 @@ public:
|
|||
void GetDisplayFileName(nsAString& aFileName) const;
|
||||
const nsCOMArray<nsIDOMFile>& GetFiles() const;
|
||||
void SetFiles(const nsCOMArray<nsIDOMFile>& aFiles, bool aSetValueChanged);
|
||||
void SetFiles(nsIDOMFileList* aFiles, bool aSetValueChanged);
|
||||
|
||||
void SetCheckedChangedInternal(PRBool aCheckedChanged);
|
||||
PRBool GetCheckedChanged() const {
|
||||
|
@ -457,6 +458,11 @@ protected:
|
|||
*/
|
||||
nsresult UpdateFileList();
|
||||
|
||||
/**
|
||||
* Called after calling one of the SetFiles() functions.
|
||||
*/
|
||||
void AfterSetFiles(bool aSetValueChanged);
|
||||
|
||||
/**
|
||||
* Determine whether the editor needs to be initialized explicitly for
|
||||
* a particular event.
|
||||
|
|
|
@ -93,6 +93,9 @@
|
|||
#include "nsDOMFile.h"
|
||||
#include "nsEventStates.h"
|
||||
|
||||
#include "nsIDOMDOMStringList.h"
|
||||
#include "nsIDOMDragEvent.h"
|
||||
|
||||
namespace dom = mozilla::dom;
|
||||
|
||||
#define SYNC_TEXT 0x1
|
||||
|
@ -136,6 +139,15 @@ nsFileControlFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
mTextFrame = nsnull;
|
||||
ENSURE_TRUE(mContent);
|
||||
|
||||
// Remove the drag events
|
||||
nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
|
||||
if (dragTarget) {
|
||||
dragTarget->RemoveEventListener(NS_LITERAL_STRING("drop"),
|
||||
mMouseListener, PR_FALSE);
|
||||
dragTarget->RemoveEventListener(NS_LITERAL_STRING("dragover"),
|
||||
mMouseListener, PR_FALSE);
|
||||
}
|
||||
|
||||
// remove mMouseListener as a mouse event listener (bug 40533, bug 355931)
|
||||
NS_NAMED_LITERAL_STRING(click, "click");
|
||||
|
||||
|
@ -258,6 +270,14 @@ nsFileControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
|||
if (!aElements.AppendElement(mTextContent))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Register the whole frame as an event listener of drag events
|
||||
nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
|
||||
NS_ENSURE_STATE(dragTarget);
|
||||
dragTarget->AddEventListener(NS_LITERAL_STRING("drop"),
|
||||
mMouseListener, PR_FALSE);
|
||||
dragTarget->AddEventListener(NS_LITERAL_STRING("dragover"),
|
||||
mMouseListener, PR_FALSE);
|
||||
|
||||
NS_NAMED_LITERAL_STRING(click, "click");
|
||||
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||
mContent->GetSystemEventGroup(getter_AddRefs(systemGroup));
|
||||
|
@ -498,6 +518,74 @@ nsFileControlFrame::BrowseMouseListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
|||
return input ? input->FireAsyncClickHandler() : NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when we receive any registered events on the control.
|
||||
* We've only registered for drop, dragover and click events, and click events
|
||||
* already call MouseClick() for us. Here, we handle file drops.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsFileControlFrame::BrowseMouseListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(mFrame, "We should have been unregistered");
|
||||
nsCOMPtr<nsIDOMNSUIEvent> uiEvent = do_QueryInterface(aEvent);
|
||||
NS_ENSURE_STATE(uiEvent);
|
||||
PRBool defaultPrevented = PR_FALSE;
|
||||
uiEvent->GetPreventDefault(&defaultPrevented);
|
||||
if (defaultPrevented) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
|
||||
if (!dragEvent || !IsValidDropData(dragEvent)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
if (eventType.EqualsLiteral("dragover")) {
|
||||
// Prevent default if we can accept this drag data
|
||||
aEvent->PreventDefault();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (eventType.EqualsLiteral("drop")) {
|
||||
aEvent->StopPropagation();
|
||||
aEvent->PreventDefault();
|
||||
|
||||
nsIContent* content = mFrame->GetContent();
|
||||
NS_ASSERTION(content, "The frame has no content???");
|
||||
|
||||
nsHTMLInputElement* inputElement = nsHTMLInputElement::FromContent(content);
|
||||
NS_ASSERTION(inputElement, "No input element for this file upload control frame!");
|
||||
|
||||
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
|
||||
dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
|
||||
|
||||
nsCOMPtr<nsIDOMFileList> fileList;
|
||||
dataTransfer->GetFiles(getter_AddRefs(fileList));
|
||||
inputElement->SetFiles(fileList, true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ PRBool
|
||||
nsFileControlFrame::BrowseMouseListener::IsValidDropData(nsIDOMDragEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
|
||||
aEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
|
||||
NS_ENSURE_TRUE(dataTransfer, PR_FALSE);
|
||||
|
||||
nsCOMPtr<nsIDOMDOMStringList> types;
|
||||
dataTransfer->GetTypes(getter_AddRefs(types));
|
||||
NS_ENSURE_TRUE(types, PR_FALSE);
|
||||
|
||||
// We only support dropping files onto a file upload control
|
||||
PRBool typeSupported;
|
||||
types->Contains(NS_LITERAL_STRING("Files"), &typeSupported);
|
||||
return typeSupported;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFileControlFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
|
||||
{
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "nsTextControlFrame.h"
|
||||
typedef nsTextControlFrame nsNewFrame;
|
||||
|
||||
class nsIDOMDragEvent;
|
||||
|
||||
class nsFileControlFrame : public nsBlockFrame,
|
||||
public nsIFormControlFrame,
|
||||
public nsIAnonymousContentCreator
|
||||
|
@ -169,6 +171,9 @@ protected:
|
|||
public:
|
||||
BrowseMouseListener(nsFileControlFrame* aFrame) : MouseListener(aFrame) {};
|
||||
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
static PRBool IsValidDropData(nsIDOMDragEvent* aEvent);
|
||||
};
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const
|
||||
|
|
Загрузка…
Ссылка в новой задаче