[XForms] add in and out of range support. Bug 300248, r=doronr+allan

This commit is contained in:
aaronr%us.ibm.com 2006-05-24 03:45:45 +00:00
Родитель e1c4f6768f
Коммит 39c067bbb6
17 изменённых файлов: 529 добавлений и 51 удалений

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

@ -148,6 +148,7 @@ XPIDLSRCS = \
nsIXFormsUploadUIElement.idl \
nsIXFormsCopyElement.idl \
nsIXFormsEphemeralMessageUI.idl \
nsIXFormsRangeConditionAccessors.idl \
$(NULL)
# XForms source files
@ -207,6 +208,7 @@ CPPSRCS = \
nsXFormsAccessors.cpp \
nsXFormsRangeAccessors.cpp \
nsXFormsCopyElement.cpp \
nsXFormsRangeConditionAccessors.cpp \
$(NULL)
# Standard Mozilla make rules

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

@ -103,4 +103,11 @@ interface nsIXFormsControl : nsIXFormsContextControl
* model bind element, ie. it has a |bind| attribute.
*/
readonly attribute boolean usesModelBinding;
/**
* These represent the default intrinsic states for controls when they are
* enabled and disabled.
*/
readonly attribute long defaultIntrinsicState;
readonly attribute long disabledIntrinsicState;
};

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

@ -36,15 +36,15 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsIXFormsAccessors.idl"
#include "nsIXFormsRangeConditionAccessors.idl"
/**
* Accessors provided by XForms \<range\> controls.
*
* @see http://www.w3.org/TR/xforms/slice8.html#ui-range
*/
[scriptable, uuid(8a6c4540-4c2b-4591-af0e-ef147543eee7)]
interface nsIXFormsRangeAccessors : nsIXFormsAccessors
[scriptable, uuid(8003219f-275f-4e37-a008-76b9ba2e7cee)]
interface nsIXFormsRangeAccessors : nsIXFormsRangeConditionAccessors
{
/** The start of the range interval */
DOMString getRangeStart();

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

@ -0,0 +1,71 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIXFormsAccessors.idl"
/**
* Accessors provided by XForms \<range\>, \<select\> and \<select1\> controls.
*
*/
[scriptable, uuid(5034a86c-083f-47c6-9ff2-74baff8968bc)]
interface nsIXFormsRangeConditionAccessors : nsIXFormsAccessors
{
/**
* @see http://www.w3.org/TR/xforms/slice4.html#evt-in-range
*/
boolean isInRange();
/**
* Used to tell the XForms processor whether the control can represent all
* of data in the bound node. For example, if there are 3 different
* space-seperated values in the instance data bound to a xf:select1 and the
* select1 only has one item, then the data must be out of the range of
* the control.
*
* @param aInRange If false, the control should be styled as defined by
* out-of-range pseudo-class. If the control was
* previously in-range, then the xforms-out-of-range
* event should be dispatched.
* If true, the control should be styled as defined by
* in-range pseudo-class or the default style matching
* the control. If the data was previously out-of-range,
* then the xforms-in-range event should be dispatched.
*/
void setInRange(in boolean aInRange);
};

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

@ -192,7 +192,9 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute,
nsCOMPtr<nsIXTFElementWrapper> wrapper(do_QueryInterface(mElement));
NS_ENSURE_STATE(wrapper);
return wrapper->SetIntrinsicState(kDisabledIntrinsicState);
PRInt32 iState;
GetDisabledIntrinsicState(&iState);
return wrapper->SetIntrinsicState(iState);
}
return NS_OK;
@ -251,6 +253,22 @@ nsXFormsControlStubBase::SetOnDeferredBindList(PRBool aPutOnList)
return NS_OK;
}
NS_IMETHODIMP
nsXFormsControlStubBase::GetDefaultIntrinsicState(PRInt32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
*aState = kDefaultIntrinsicState;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsControlStubBase::GetDisabledIntrinsicState(PRInt32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
*aState = kDisabledIntrinsicState;
return NS_OK;
}
nsresult
nsXFormsControlStubBase::MaybeAddToModel(nsIModelElementPrivate *aOldModel,
nsIXFormsControl *aParent)
@ -622,7 +640,9 @@ nsXFormsControlStubBase::DocumentChanged(nsIDOMDocument *aNewDocument)
if (aNewDocument && !mModel && mElement) {
nsCOMPtr<nsIXTFElementWrapper> xtfWrap(do_QueryInterface(mElement));
NS_ENSURE_STATE(xtfWrap);
xtfWrap->SetIntrinsicState(kDefaultIntrinsicState);
PRInt32 iState;
GetDefaultIntrinsicState(&iState);
xtfWrap->SetIntrinsicState(iState);
}
return ForceModelDetach(mHasParent && aNewDocument);

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

@ -94,6 +94,8 @@ public:
NS_IMETHOD TryFocus(PRBool* aOK);
NS_IMETHOD IsEventTarget(PRBool *aOK);
NS_IMETHOD GetUsesModelBinding(PRBool *aRes);
NS_IMETHOD GetDefaultIntrinsicState(PRInt32 *aRes);
NS_IMETHOD GetDisabledIntrinsicState(PRInt32 *aRes);
nsresult Create(nsIXTFElementWrapper *aWrapper);
// for nsIXTFElement

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

@ -79,6 +79,7 @@
#include "nsXFormsControlStub.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIEventStateManager.h"
#define XFORMS_LAZY_INSTANCE_BINDING \
"chrome://xforms/content/xforms.xml#xforms-lazy-instance"
@ -1110,8 +1111,13 @@ nsXFormsModelElement::SetStates(nsIXFormsControl *aControl,
ns = mMDG.GetNodeState(aNode);
NS_ENSURE_STATE(ns);
iState = ns->GetIntrinsicState();
nsCOMPtr<nsIContent> content(do_QueryInterface(element));
NS_ENSURE_STATE(content);
PRInt32 rangeState = content->IntrinsicState() &
(NS_EVENT_STATE_INRANGE | NS_EVENT_STATE_OUTOFRANGE);
iState = ns->GetIntrinsicState() | rangeState;
} else {
iState = kDefaultIntrinsicState;
aControl->GetDefaultIntrinsicState(&iState);
}
nsresult rv = xtfWrap->SetIntrinsicState(iState);
@ -1321,19 +1327,26 @@ nsXFormsModelElement::Refresh()
#ifdef DEBUG
printf("nsXFormsModelElement::Refresh()\n");
#endif
nsPostRefresh postRefresh = nsPostRefresh();
if (!mDocumentLoaded) {
return NS_OK;
}
// XXXbeaufour: Can we somehow suspend redraw / "screen update" while doing
// the refresh? That should save a lot of time, and avoid flickering of
// controls.
// Kick off refreshing on root node
nsresult rv = RefreshSubTree(mFormControls.FirstChild(), PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// Using brackets here to provide a scope for the
// nsPostRefresh. We want to make sure that nsPostRefresh's destructor
// runs (and thus processes the postrefresh and containerpostrefresh lists)
// before we clear the dispatch flags
{
nsPostRefresh postRefresh = nsPostRefresh();
if (!mDocumentLoaded) {
return NS_OK;
}
// Kick off refreshing on root node
nsresult rv = RefreshSubTree(mFormControls.FirstChild(), PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
// Clear refresh structures
mChangedNodes.Clear();

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

@ -43,7 +43,7 @@
#include "nsXFormsUtils.h"
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsRangeAccessors,
nsXFormsAccessors,
nsXFormsRangeConditionAccessors,
nsIXFormsRangeAccessors,
nsIClassInfo)
@ -95,6 +95,7 @@ nsXFormsRangeAccessors::GetRangeStep(nsAString &aStep)
static const nsIID sScriptingIIDs[] = {
NS_IXFORMSACCESSORS_IID,
NS_IXFORMSRANGECONDITIONACCESSORS_IID,
NS_IXFORMSRANGEACCESSORS_IID
};

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

@ -37,26 +37,26 @@
* ***** END LICENSE BLOCK ***** */
#include "nsIXFormsRangeAccessors.h"
#include "nsXFormsAccessors.h"
#include "nsXFormsRangeConditionAccessors.h"
/**
* Implementation for the accessors for a range element,
* nsIXFormsRangeAccessors.
*
* @todo Support out-of/in-range events (XXX)
*/
class nsXFormsRangeAccessors : public nsXFormsAccessors,
class nsXFormsRangeAccessors : public nsXFormsRangeConditionAccessors,
public nsIXFormsRangeAccessors
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIXFORMSRANGEACCESSORS
NS_FORWARD_NSIXFORMSRANGECONDITIONACCESSORS(nsXFormsRangeConditionAccessors::)
NS_FORWARD_NSIXFORMSACCESSORS(nsXFormsAccessors::)
// Constructor
nsXFormsRangeAccessors(nsIDelegateInternal* aDelegate,
nsIDOMElement* aElement)
: nsXFormsAccessors(aDelegate, aElement)
: nsXFormsRangeConditionAccessors(aDelegate, aElement)
{
}

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

@ -0,0 +1,116 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsRangeConditionAccessors.h"
#include "nsIContent.h"
#include "nsIDOMElement.h"
#include "nsIXTFElementWrapper.h"
#include "nsIXFormsControl.h"
#include "nsIEventStateManager.h"
#include "nsXFormsUtils.h"
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsRangeConditionAccessors,
nsXFormsAccessors,
nsIXFormsRangeConditionAccessors,
nsIClassInfo)
// nsXFormsRangeConditionAccessors
NS_IMETHODIMP
nsXFormsRangeConditionAccessors::IsInRange(PRBool *aInRange)
{
return GetState(NS_EVENT_STATE_INRANGE, aInRange);
}
NS_IMETHODIMP
nsXFormsRangeConditionAccessors::SetInRange(PRBool aInRange)
{
PRBool currRange;
nsresult rv = IsInRange(&currRange);
NS_ENSURE_SUCCESS(rv, rv);
if (currRange == aInRange) {
return NS_OK;
}
/* when this call changes the control's previous in or out of range state,
* then we need to set the state to the new value and dispatch
* xforms-in-range or xforms-out-of-range
*/
nsCOMPtr<nsIXFormsControl> control(do_QueryInterface(mDelegate));
NS_ENSURE_STATE(control);
nsCOMPtr<nsIDOMElement> element;
control->GetElement(getter_AddRefs(element));
nsCOMPtr<nsIXTFElementWrapper> xtfWrap(do_QueryInterface(element));
NS_ENSURE_STATE(xtfWrap);
nsCOMPtr<nsIContent> content(do_QueryInterface(element));
NS_ENSURE_STATE(content);
PRInt32 state = content->IntrinsicState();
if (!aInRange) {
state &= ~NS_EVENT_STATE_INRANGE;
state |= NS_EVENT_STATE_OUTOFRANGE;
} else {
state &= ~NS_EVENT_STATE_OUTOFRANGE;
state |= NS_EVENT_STATE_INRANGE;
}
rv = xtfWrap->SetIntrinsicState(state);
NS_ENSURE_SUCCESS(rv, rv);
nsXFormsUtils::DispatchEvent(element,
aInRange ? eEvent_InRange : eEvent_OutOfRange);
return NS_OK;
}
// nsIClassInfo implementation
static const nsIID sScriptingIIDs[] = {
NS_IXFORMSACCESSORS_IID,
NS_IXFORMSRANGECONDITIONACCESSORS_IID
};
NS_IMETHODIMP
nsXFormsRangeConditionAccessors::GetInterfaces(PRUint32 *aCount,
nsIID * **aArray)
{
return nsXFormsUtils::CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}

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

@ -0,0 +1,65 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIXFormsRangeConditionAccessors.h"
#include "nsXFormsAccessors.h"
/**
* Implementation for the accessors for elements that can be in or out of
* range. Specifically, select, select1 and range.
* nsIXFormsRangeConditionAccessors.
*
*/
class nsXFormsRangeConditionAccessors : public nsXFormsAccessors,
public nsIXFormsRangeConditionAccessors
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIXFORMSRANGECONDITIONACCESSORS
NS_FORWARD_NSIXFORMSACCESSORS(nsXFormsAccessors::)
// Constructor
nsXFormsRangeConditionAccessors(nsIDelegateInternal *aDelegate,
nsIDOMElement *aElement)
: nsXFormsAccessors(aDelegate, aElement)
{
}
// nsIClassInfo overrides
NS_IMETHOD GetInterfaces(PRUint32 *aCount, nsIID * **aArray);
};

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

@ -38,6 +38,7 @@
#include "nsXFormsDelegateStub.h"
#include "nsXFormsRangeAccessors.h"
#include "nsIEventStateManager.h"
/**
* Implementation of the XForms \<range\> element
@ -49,6 +50,10 @@ class nsXFormsRangeElement : public nsXFormsDelegateStub
{
public:
// nsIXFormsControl
NS_IMETHOD GetDefaultIntrinsicState(PRInt32 *aState);
NS_IMETHOD GetDisabledIntrinsicState(PRInt32 *aState);
// nsIXFormsDelegate overrides
NS_IMETHOD GetXFormsAccessors(nsIXFormsAccessors **aAccessor);
@ -57,6 +62,26 @@ public:
#endif
};
// nsIXFormsControl
NS_IMETHODIMP
nsXFormsRangeElement::GetDefaultIntrinsicState(PRInt32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsXFormsDelegateStub::GetDefaultIntrinsicState(aState);
*aState |= NS_EVENT_STATE_INRANGE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsRangeElement::GetDisabledIntrinsicState(PRInt32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsXFormsDelegateStub::GetDisabledIntrinsicState(aState);
*aState |= NS_EVENT_STATE_INRANGE;
return NS_OK;
}
// nsIXFormsDelegate
NS_IMETHODIMP

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

@ -56,6 +56,8 @@
#include "nsIDocument.h"
#include "nsNetUtil.h"
#include "nsXFormsModelElement.h"
#include "nsXFormsRangeConditionAccessors.h"
#include "nsIEventStateManager.h"
class nsXFormsSelect1Element : public nsXFormsDelegateStub
{
@ -73,6 +75,11 @@ public:
// nsIXFormsControl
NS_IMETHOD Refresh();
NS_IMETHOD GetDefaultIntrinsicState(PRInt32 *aState);
NS_IMETHOD GetDisabledIntrinsicState(PRInt32 *aState);
// nsIXFormsDelegate overrides
NS_IMETHOD GetXFormsAccessors(nsIXFormsAccessors **aAccessor);
nsXFormsSelect1Element(const nsAString& aType)
: nsXFormsDelegateStub(aType)
@ -154,6 +161,39 @@ nsXFormsSelect1Element::Refresh()
return nsXFormsDelegateStub::Refresh();
}
NS_IMETHODIMP
nsXFormsSelect1Element::GetDefaultIntrinsicState(PRInt32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsXFormsDelegateStub::GetDefaultIntrinsicState(aState);
*aState |= NS_EVENT_STATE_INRANGE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelect1Element::GetDisabledIntrinsicState(PRInt32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsXFormsDelegateStub::GetDisabledIntrinsicState(aState);
*aState |= NS_EVENT_STATE_INRANGE;
return NS_OK;
}
// nsIXFormsDelegate
NS_IMETHODIMP
nsXFormsSelect1Element::GetXFormsAccessors(nsIXFormsAccessors **aAccessor)
{
if (!mAccessor) {
mAccessor = new nsXFormsRangeConditionAccessors(this, mElement);
if (!mAccessor) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
NS_ADDREF(*aAccessor = mAccessor);
return NS_OK;
}
NS_HIDDEN_(nsresult)
NS_NewXFormsSelect1Element(nsIXTFElement **aResult)
{

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

@ -53,6 +53,8 @@
#include "nsIDocument.h"
#include "nsNetUtil.h"
#include "nsXFormsModelElement.h"
#include "nsXFormsRangeConditionAccessors.h"
#include "nsIEventStateManager.h"
class nsXFormsSelectElement : public nsXFormsDelegateStub
{
@ -68,6 +70,11 @@ public:
// nsIXFormsControl
NS_IMETHOD Refresh();
NS_IMETHOD GetDefaultIntrinsicState(PRInt32 *aState);
NS_IMETHOD GetDisabledIntrinsicState(PRInt32 *aState);
// nsIXFormsDelegate overrides
NS_IMETHOD GetXFormsAccessors(nsIXFormsAccessors **aAccessor);
#ifdef DEBUG_smaug
virtual const char* Name() { return "select"; }
@ -126,6 +133,39 @@ nsXFormsSelectElement::Refresh()
return nsXFormsDelegateStub::Refresh();
}
NS_IMETHODIMP
nsXFormsSelectElement::GetDefaultIntrinsicState(PRInt32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsXFormsDelegateStub::GetDefaultIntrinsicState(aState);
*aState |= NS_EVENT_STATE_INRANGE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectElement::GetDisabledIntrinsicState(PRInt32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsXFormsDelegateStub::GetDisabledIntrinsicState(aState);
*aState |= NS_EVENT_STATE_INRANGE;
return NS_OK;
}
// nsIXFormsDelegate
NS_IMETHODIMP
nsXFormsSelectElement::GetXFormsAccessors(nsIXFormsAccessors **aAccessor)
{
if (!mAccessor) {
mAccessor = new nsXFormsRangeConditionAccessors(this, mElement);
if (!mAccessor) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
NS_ADDREF(*aAccessor = mAccessor);
return NS_OK;
}
NS_HIDDEN_(nsresult)
NS_NewXFormsSelectElement(nsIXTFElement **aResult)
{

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

@ -211,12 +211,13 @@
this.ctx.fillRect(this.margin, mid - 1, this.barwidth, 3);
this.ctx.strokeRect(this.margin, mid - 1, this.barwidth, 3);
// check whether out-of-range state has changed, and dispatch event if it has
// Let the accessor know the outOfRange state. The accessor will
// take care of the control styling and dispatching the appropriate
// events if the in/out of range condition has changed from its
// previous state.
if (outOfRange != this.outOfRange) {
// XXX we need to set the style too
this.outOfRange = outOfRange;
var event = outOfRange ? "xforms-out-of-range" : "xforms-in-range";
this.dispatchXFormsNotificationEvent(event, this);
this.accessors.setInRange(!outOfRange);
}
// if out-of-range, we cannot represent the value

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

@ -244,14 +244,17 @@
}
}
var outOfRange = false;
var selectionOpen = this.selection == 'open';
// check if any default values were not found
for (var index in this._defaultHash) {
if (this._defaultHash[index].hits == 0) {
if (this.selection == 'open') {
if (selectionOpen) {
this.control.appendFreeEntryItem(index);
} else {
// XXX: some of default values not found, we need to throw an
// some of default values not found, we need to throw an
// xforms-out-of-range event, but only if the select is 'closed'.
outOfRange = true;
}
}
}
@ -259,16 +262,26 @@
// check if any default elements were not found
for (var j = 0; j < this._selectedElementArray.length; j++) {
if (this._selectedElementArray[j].hits == 0) {
if (this.selection == 'open') {
if (selectionOpen) {
// XXX: If the select is open, the missing elements should be added
// and selected per 8.1.10 in the spec.
} else {
// XXX: some of default values not found, we need to throw an
// some of default values not found, we need to throw an
// xforms-out-of-range event, but only if the select is 'closed'.
outOfRange = true;
}
}
}
// a control can't be out of range (or in range for that matter) if
// there is no selected value, so make sure that there is a bound
// node first.
if (!selectionOpen && this.accessors.hasBoundNode() &&
(outOfRange != this._outOfRange)) {
this._outOfRange = outOfRange;
this.accessors.setInRange(!outOfRange);
}
return true;
]]>
</body>
@ -301,11 +314,11 @@
// get an array of values selected in the bound node
var selectedArray = value.split(/\s/);
if (selectedArray.length == 1 && selectedArray[0] == "") {
// when the string is empty, split returns an array containing
// one empty string, rather than an empty array.
return;
}
// when the string is empty, split returns an array containing
// one empty string, rather than an empty array. We'll allow that
// into the defaultHash so that xforms-out-of-range will be
// correctly generated if none of the items in the select have
// an empty string as a value
for (var run = 0; run < selectedArray.length; run++) {
this._defaultHash[selectedArray[run]] = {hits: 0}
@ -337,12 +350,12 @@
// get an array of values selected in the bound node
var selectedArray = value.split(" ");
if (selectedArray.length == 1 && selectedArray[0] == "") {
// when the string is empty, split returns an array containing
// one empty string, rather than an empty array.
continue;
}
// when the string is empty, split returns an array containing
// one empty string, rather than an empty array. We'll allow
// that into the defaultHash so that xforms-out-of-range will be
// correctly generated if none of the items in the select have
// an empty string as a value
for (var run = 0; run < selectedArray.length; run++) {
this._defaultHash[selectedArray[run]] = {hits: 0}
}
@ -513,7 +526,9 @@
var item = options[i].control.
QueryInterface(Components.interfaces.nsIXFormsSelectChild);
if (item.isCopyItem)
break;
// _updateSelection is used only to select items when _defaultHash
// contains only text nodes. So we can ignore copyItems.
continue;
var value = item.value;
var selectionValue = value in this._defaultHash;
@ -521,12 +536,43 @@
if (selectionValue) {
this.control.addItemToSelection(options[i].option);
options[i].wasSelected = true;
this._defaultHash[value].hits++;
}
else {
this.control.removeItemFromSelection(options[i].option);
options[i].wasSelected = false;
}
}
// see if any of default values are not found. If so, we need to
// throw an xforms-out-of-range event and style the control as
// being out of range. But only if the select is 'closed'.
if (this.selection == 'open') {
return;
}
var outOfRange = false;
var length = 0;
for (var index in this._defaultHash) {
length++;
if (this._defaultHash[index].hits == 0) {
outOfRange = true;
}
}
if (length == 0) {
// this covers the scenario where some items were previously
// selected and the user selected a copyItem, yet because the
// bound node wasn't an element node the copyItem was deselected
// and the bound node was set to empty. If there is no selected
// item, then we must be out of range.
outOfRange = true;
}
if (this._outOfRange != outOfRange) {
this._outOfRange = outOfRange;
this.accessors.setInRange(!outOfRange);
}
]]>
</body>
</method>
@ -542,7 +588,7 @@
// store the values in a hash for quick access
this._defaultHash = new Object();
for (var run = 0; run < selectedArray.length; run++) {
this._defaultHash[selectedArray[run]] = {}
this._defaultHash[selectedArray[run]] = {hits: 0}
}
]]>
</body>
@ -778,6 +824,7 @@
<field name="_selectedElementArray">new Array()</field>
<field name="_defaultHash">null</field>
<field name="_accessorValueCache">null</field>
<field name="_outOfRange">false</field>
<method name="getControlElement">
<body>

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

@ -91,6 +91,7 @@
<field name="_lastSelectedItem">null</field>
<field name="popupOpen">false</field>
<field name="shouldHandleBlur">true</field>
<field name="_outOfRange">false</field>
<property name="selectionOpen" readonly="true">
<getter>
@ -598,8 +599,6 @@
// oh oh! We've already found a selectable node in the
// instance data and now we have another. That shouldn't
// happen.
// XXX generate xforms-out-of-range exception and style
// control as out-of-range
outOfRange = true;
}
newValue = string;
@ -609,11 +608,9 @@
// a node worth comparing. As such, look for an
// item with a copy element that might match this node.
if (newValue || nodeValue) {
// oh oh! We've already found a selectable node in the
// instance data and now we have another. That shouldn't
// happen.
// XXX generate xforms-out-of-range exception and style
// control as out-of-range
// oh oh! We've already found a selectable node in the
// instance data and now we have another. That shouldn't
// happen.
outOfRange = true;
}
nodeValue = child;
@ -627,6 +624,14 @@
}
if (outOfRange) {
// a control can't be out of range (or in range for that matter)
// if there is no selected value, so make sure that there is a
// bound node first.
if ((outOfRange != this._outOfRange) && boundNode) {
this._outOfRange = outOfRange;
this.accessors.setInRange(false);
}
// can't possibly work, no sense continuing.
this.inputField.value = "";
this._selected.setActive(false);
@ -673,14 +678,23 @@
this.selectItemByNode(nodeValue);
}
outOfRange = false;
if (this._selected) {
this.updateInputField();
this._lastSelectedItem = this._selected;
} else if (this.selectionOpen) {
this.inputField.value = newValue;
} else {
// @todo out-of-range (XXX)
this.inputField.value = "";
outOfRange = true;
}
// a control can't be out of range (or in range for that matter)
// if there is no selected value, so make sure that there is a
// bound node first.
if ((outOfRange != this._outOfRange) && boundNode) {
this._outOfRange = outOfRange;
this.accessors.setInRange(!outOfRange);
}
this.refreshWidth();
} catch (ex) {}
@ -810,8 +824,9 @@
// if aDispatchSelectEvents is true, then we need to make sure to
// dispatch the xforms-deselect and xforms-select events before we
// change the value of the bound node otherwise we'll get the
// event ordering wrong. aDispatchSelectEvents is a REQUIRED
// parameter, whether it be true or false.
// event ordering wrong. Similar with setting out of/in range (must
// happen after dispatch select/deselect). aDispatchSelectEvents is
// a REQUIRED parameter, whether it be true or false.
// aInBlur is not a required parameter. It is true if handleSelection
// was called from the blur handler.
@ -826,6 +841,10 @@
this.dispatchSelectEvents();
}
this.accessors.setValue(this.inputField.value);
// open selection can't be out of range
this._outOfRange = false;
this.accessors.setInRange(true);
return;
}
@ -854,6 +873,8 @@
this.dispatchSelectEvents();
}
this.accessors.setValue(envelope.nodeValue);
this._outOfRange = false;
this.accessors.setInRange(true);
return;
}
@ -872,11 +893,14 @@
this._selected.setActive(false);
this._selected = null;
this.inputField.value = "";
this.accessors.setValue("");
if (aDispatchSelectEvents == true) {
this.dispatchSelectEvents();
}
this.accessors.setValue("");
this._outOfRange = true;
this.accessors.setInRange(false);
return;
}
@ -892,11 +916,15 @@
this.dispatchSelectEvents();
}
this.accessors.setValue(contentEnvelope.textContent);
this._outOfRange = false;
this.accessors.setInRange(true);
} else {
if (aDispatchSelectEvents == true) {
this.dispatchSelectEvents();
}
this.accessors.setContent(contentEnvelope, true);
this._outOfRange = false;
this.accessors.setInRange(true);
}
}