Clicking in a focused input should open autocomplete results popup (bug 173569). Patch by dean_tessman@hotmail.com, r=me.

This commit is contained in:
bryner%brianryner.com 2004-07-29 08:42:54 +00:00
Родитель 7f304859c1
Коммит b5ff05df21
5 изменённых файлов: 198 добавлений и 39 удалений

Просмотреть файл

@ -20,6 +20,7 @@
*
* Contributor(s):
* Joe Hewitt <hewitt@netscape.com> (Original Author)
* Dean Tessman <dean_tessman@hotmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -87,7 +88,7 @@ interface nsIAutoCompleteController : nsISupports
* means of changing the text value, including typing a character, backspacing, deleting, or
* pasting in an entirely new value.
*/
void handleText();
void handleText(in boolean aIgnoreSelection);
/*
* Notify the controller that the user wishes to enter the current text
@ -136,4 +137,9 @@ interface nsIAutoCompleteController : nsISupports
* Get a the style hint for the result at a given index in the last completed search
*/
AString getStyleAt(in long index);
/*
* Set the current search string, but don't start searching
*/
void setSearchString(in AString aSearchString);
};

Просмотреть файл

@ -164,7 +164,7 @@ nsAutoCompleteController::StartSearch(const nsAString &aSearchString)
}
NS_IMETHODIMP
nsAutoCompleteController::HandleText()
nsAutoCompleteController::HandleText(PRBool aIgnoreSelection)
{
// Stop current search in case it's async.
StopSearch();
@ -208,7 +208,10 @@ nsAutoCompleteController::HandleText()
return NS_OK;
}
// Kick off the search, but only if the cursor is at the end of the textbox
if (aIgnoreSelection) {
StartSearchTimer();
} else {
// Kick off the search only if the cursor is at the end of the textbox
PRInt32 selectionStart;
mInput->GetSelectionStart(&selectionStart);
PRInt32 selectionEnd;
@ -216,6 +219,7 @@ nsAutoCompleteController::HandleText()
if (selectionStart == selectionEnd && selectionStart == (PRInt32) mSearchString.Length())
StartSearchTimer();
}
return NS_OK;
}
@ -337,7 +341,7 @@ nsAutoCompleteController::HandleDelete(PRBool *_retval)
mInput->GetPopupOpen(&isOpen);
if (!isOpen || mRowCount <= 0) {
// Nothing left to delete, proceed as normal
HandleText();
HandleText(PR_FALSE);
return NS_OK;
}
@ -438,6 +442,14 @@ nsAutoCompleteController::GetStyleAt(PRInt32 aIndex, nsAString & _retval)
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteController::SetSearchString(const nsAString &aSearchString)
{
mSearchString = aSearchString;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
//// nsIAutoCompleteObserver
@ -810,7 +822,7 @@ nsAutoCompleteController::StartSearchTimer()
mInput->GetTimeout(&timeout);
mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->InitWithCallback(this, 0, timeout);
mTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
return NS_OK;
}

Просмотреть файл

@ -21,6 +21,7 @@
*
* Contributor(s):
* Joe Hewitt <hewitt@netscape.com> (Original Author)
* Dean Tessman <dean_tessman@hotmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -67,6 +68,7 @@
#include "nsIDOMDocumentEvent.h"
#include "nsIDOMHTMLFormElement.h"
#include "nsPasswordManager.h"
#include "nsIDOMMouseEvent.h"
NS_INTERFACE_MAP_BEGIN(nsFormFillController)
NS_INTERFACE_MAP_ENTRY(nsIFormFillController)
@ -75,6 +77,7 @@ NS_INTERFACE_MAP_BEGIN(nsFormFillController)
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFormFillController)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFocusListener)
NS_INTERFACE_MAP_END
@ -106,7 +109,7 @@ nsFormFillController::~nsFormFillController()
nsCOMPtr<nsIDocShell> docShell;
mDocShells->GetElementAt(i, getter_AddRefs(docShell));
nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(docShell);
RemoveFocusListener(domWindow);
RemoveWindowListeners(domWindow);
}
}
@ -175,7 +178,7 @@ nsFormFillController::AttachToBrowser(nsIDocShell *aDocShell, nsIAutoCompletePop
// Listen for focus events on the domWindow of the docShell
nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(aDocShell);
AddFocusListener(domWindow);
AddWindowListeners(domWindow);
return NS_OK;
}
@ -190,7 +193,7 @@ nsFormFillController::DetachFromBrowser(nsIDocShell *aDocShell)
nsCOMPtr<nsIDocShell> docShell;
mDocShells->GetElementAt(index, getter_AddRefs(docShell));
nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(docShell);
RemoveFocusListener(domWindow);
RemoveWindowListeners(domWindow);
mDocShells->RemoveElementAt(index);
mPopups->RemoveElementAt(index);
@ -507,7 +510,9 @@ nsFormFillController::Focus(nsIDOMEvent* aEvent)
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(target);
if (input) {
if (!input)
return NS_OK;
nsAutoString type;
input->GetType(type);
@ -524,7 +529,6 @@ nsFormFillController::Focus(nsIDOMEvent* aEvent)
if (!form || !autocomplete.LowerCaseEqualsLiteral("off"))
StartControllingInput(input);
}
}
return NS_OK;
}
@ -556,7 +560,13 @@ nsFormFillController::KeyUp(nsIDOMEvent* aEvent)
NS_IMETHODIMP
nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
{
NS_ASSERTION(mController, "should have a controller!");
if (!mFocusedInput || !mController)
return NS_OK;
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
if (!keyEvent)
return NS_ERROR_FAILURE;
PRBool cancel = PR_FALSE;
@ -577,7 +587,7 @@ nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
// fall through
}
case nsIDOMKeyEvent::DOM_VK_BACK_SPACE:
mController->HandleText();
mController->HandleText(PR_FALSE);
break;
case nsIDOMKeyEvent::DOM_VK_UP:
mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_UP, &cancel);
@ -623,6 +633,9 @@ nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
NS_IMETHODIMP
nsFormFillController::Submit(nsIDOMEvent* aEvent)
{
if (mFocusedInput)
StopControllingInput();
return NS_OK;
}
@ -647,18 +660,109 @@ nsFormFillController::Select(nsIDOMEvent* aEvent)
NS_IMETHODIMP
nsFormFillController::Input(nsIDOMEvent* aEvent)
{
if (mSuppressOnInput)
if (mSuppressOnInput || !mController)
return NS_OK;
return mController->HandleText();
return mController->HandleText(PR_FALSE);
}
////////////////////////////////////////////////////////////////////////
//// nsIDOMMouseListener
NS_IMETHODIMP
nsFormFillController::MouseDown(nsIDOMEvent* aMouseEvent)
{
mIgnoreClick = PR_FALSE;
nsCOMPtr<nsIDOMEventTarget> target;
aMouseEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMHTMLInputElement> targetInput = do_QueryInterface(target);
if (targetInput && targetInput != mFocusedInput) {
// A new input will be taking focus. Ignore the first click
// so that the popup is not shown.
mIgnoreClick = PR_TRUE;
return NS_OK;
}
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::MouseUp(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::MouseClick(nsIDOMEvent* aMouseEvent)
{
if (mIgnoreClick) {
mIgnoreClick = PR_FALSE;
return NS_OK;
}
if (!mFocusedInput)
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aMouseEvent));
if (!mouseEvent)
return NS_ERROR_FAILURE;
PRUint16 button;
mouseEvent->GetButton(&button);
if (button != 0)
return NS_OK;
PRBool isOpen = PR_FALSE;
GetPopupOpen(&isOpen);
if (isOpen)
return NS_OK;
nsCOMPtr<nsIAutoCompleteInput> input;
mController->GetInput(getter_AddRefs(input));
if (!input)
return NS_OK;
nsAutoString value;
input->GetTextValue(value);
if (value.Length() > 0) {
// Show the popup with a filtered result set
mController->SetSearchString(NS_LITERAL_STRING(""));
mController->HandleText(PR_TRUE);
} else {
// Show the popup with the complete result set. Can't use HandleText()
// because it doesn't display the popup if the input is blank.
PRBool cancel = PR_FALSE;
mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_DOWN, &cancel);
}
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::MouseDblClick(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::MouseOver(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::MouseOut(nsIDOMEvent* aMouseEvent)
{
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
//// nsFormFillController
void
nsFormFillController::AddFocusListener(nsIDOMWindow *aWindow)
nsFormFillController::AddWindowListeners(nsIDOMWindow *aWindow)
{
if (!aWindow)
return;
@ -670,14 +774,32 @@ nsFormFillController::AddFocusListener(nsIDOMWindow *aWindow)
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(chromeEventHandler));
if (target)
if (!target)
return;
target->AddEventListener(NS_LITERAL_STRING("focus"),
NS_STATIC_CAST(nsIDOMFocusListener *, this),
PR_TRUE);
target->AddEventListener(NS_LITERAL_STRING("blur"),
NS_STATIC_CAST(nsIDOMFocusListener *, this),
PR_TRUE);
target->AddEventListener(NS_LITERAL_STRING("mousedown"),
NS_STATIC_CAST(nsIDOMMouseListener *, this),
PR_TRUE);
target->AddEventListener(NS_LITERAL_STRING("click"),
NS_STATIC_CAST(nsIDOMMouseListener *, this),
PR_TRUE);
target->AddEventListener(NS_LITERAL_STRING("input"),
NS_STATIC_CAST(nsIDOMFormListener *, this),
PR_TRUE);
}
void
nsFormFillController::RemoveFocusListener(nsIDOMWindow *aWindow)
nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow)
{
if (!aWindow)
return;
@ -691,46 +813,54 @@ nsFormFillController::RemoveFocusListener(nsIDOMWindow *aWindow)
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(chromeEventHandler));
if (!target)
return;
target->RemoveEventListener(NS_LITERAL_STRING("focus"),
NS_STATIC_CAST(nsIDOMFocusListener *, this),
PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("blur"),
NS_STATIC_CAST(nsIDOMFocusListener *, this),
PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("mousedown"),
NS_STATIC_CAST(nsIDOMMouseListener *, this),
PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("click"),
NS_STATIC_CAST(nsIDOMMouseListener *, this),
PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("input"),
NS_STATIC_CAST(nsIDOMFormListener *, this),
PR_TRUE);
}
void
nsFormFillController::AddKeyListener(nsIDOMHTMLInputElement *aInput)
{
if (aInput) {
mFocusedInput = aInput;
if (!aInput)
return;
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(aInput);
target->AddEventListener(NS_LITERAL_STRING("input"),
NS_STATIC_CAST(nsIDOMFormListener *, this),
PR_TRUE);
target->AddEventListener(NS_LITERAL_STRING("keypress"),
NS_STATIC_CAST(nsIDOMKeyListener *, this),
PR_TRUE);
}
}
void
nsFormFillController::RemoveKeyListener()
{
if (mFocusedInput) {
if (!mFocusedInput)
return;
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mFocusedInput);
target->RemoveEventListener(NS_LITERAL_STRING("input"),
NS_STATIC_CAST(nsIDOMFormListener *, this),
PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("keypress"),
NS_STATIC_CAST(nsIDOMKeyListener *, this),
PR_TRUE);
mFocusedInput = nsnull;
}
}
void
@ -748,8 +878,8 @@ nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput)
// Cache the popup for the focused docShell
mPopups->GetElementAt(index, getter_AddRefs(mFocusedPopup));
// Start listening for key events
AddKeyListener(aInput);
mFocusedInput = aInput;
// Now we are the autocomplete controller's bitch
mController->SetInput(this);

Просмотреть файл

@ -21,6 +21,7 @@
*
* Contributor(s):
* Joe Hewitt <hewitt@netscape.com> (Original Author)
* Dean Tessman <dean_tessman@hotmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -47,6 +48,7 @@
#include "nsIDOMFocusListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMFormListener.h"
#include "nsIDOMMouseListener.h"
#include "nsCOMPtr.h"
#include "nsISupportsArray.h"
#include "nsIDocShell.h"
@ -59,16 +61,15 @@ class nsFormFillController : public nsIFormFillController,
public nsIAutoCompleteSearch,
public nsIDOMFocusListener,
public nsIDOMKeyListener,
public nsIDOMFormListener
public nsIDOMFormListener,
public nsIDOMMouseListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIFORMFILLCONTROLLER
NS_DECL_NSIAUTOCOMPLETESEARCH
NS_DECL_NSIAUTOCOMPLETEINPUT
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
NS_DECL_NSIDOMEVENTLISTENER
// nsIDOMFocusListener
NS_IMETHOD Focus(nsIDOMEvent* aEvent);
@ -86,12 +87,20 @@ public:
NS_IMETHOD Select(nsIDOMEvent* aEvent);
NS_IMETHOD Input(nsIDOMEvent* aEvent);
// nsIDOMMouseListener
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
nsFormFillController();
virtual ~nsFormFillController();
protected:
void AddFocusListener(nsIDOMWindow *aWindow);
void RemoveFocusListener(nsIDOMWindow *aWindow);
void AddWindowListeners(nsIDOMWindow *aWindow);
void RemoveWindowListeners(nsIDOMWindow *aWindow);
void AddKeyListener(nsIDOMHTMLInputElement *aInput);
void RemoveKeyListener();
@ -121,6 +130,7 @@ protected:
PRPackedBool mCompleteDefaultIndex;
PRPackedBool mForceComplete;
PRPackedBool mSuppressOnInput;
PRPackedBool mIgnoreClick;
};
#endif // __nsFormFillController__

Просмотреть файл

@ -21,6 +21,7 @@
#
# Contributor(s):
# Pierre Chanial (p_ch@verizon.net)
# Dean Tessman (dean_tessman@hotmail.com)
#
# Alternatively, the contents of this file may be used under the
# terms of the GNU General Public License Version 2 or later (the
@ -424,7 +425,7 @@
<handlers>
<handler event="input"
action="if (!this.mIgnoreInput) this.mController.handleText();"/>
action="if (!this.mIgnoreInput) this.mController.handleText(false);"/>
<handler event="keypress" phase="capturing"
action="return this.onKeyPress(event);"/>