Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #303 Infinite loop on datepicker #308

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/aria/widgets/form/Select.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -188,9 +188,9 @@ Aria.classDefinition({
this._updateState(); this._updateState();
if (this._cfg.formatError && this._cfg.validationEvent === 'onBlur') {// show if (this._cfg.formatError && this._cfg.validationEvent === 'onBlur') {// show
// errortip on blur used for debug purposes // errortip on blur used for debug purposes
this._validationPopupShow(this); this._validationPopupShow();
} else { // dispose of error tip } else { // dispose of error tip
this._validationPopupHide(this); this._validationPopupHide();
if (this._cfg.directOnBlurValidation) { if (this._cfg.directOnBlurValidation) {
if (this._cfg.bind) { if (this._cfg.bind) {
var bind = this._cfg.bind.value; var bind = this._cfg.bind.value;
Expand Down Expand Up @@ -219,7 +219,7 @@ Aria.classDefinition({
if (this._cfg) { if (this._cfg) {
if (this._cfg.validationEvent === 'onFocus' if (this._cfg.validationEvent === 'onFocus'
&& ((this._cfg.formatError && this._cfg.formatErrorMessages.length) || (this._cfg.error && this._cfg.errorMessages.length))) { && ((this._cfg.formatError && this._cfg.formatErrorMessages.length) || (this._cfg.error && this._cfg.errorMessages.length))) {
this._validationPopupShow(this); this._validationPopupShow();
} }
} }
this._updateState(); this._updateState();
Expand All @@ -231,9 +231,9 @@ Aria.classDefinition({
} }
this.evalCallback(this._cfg.onvalidate); this.evalCallback(this._cfg.onvalidate);
if (arg.popup && (this._cfg.error)) {// show errortip onfocus if (arg.popup && (this._cfg.error)) {// show errortip onfocus
this._validationPopupShow(this); this._validationPopupShow();
} else { // dispose of error tip } else { // dispose of error tip
this._validationPopupHide(this); this._validationPopupHide();


} }
}, },
Expand Down Expand Up @@ -318,7 +318,7 @@ Aria.classDefinition({
this.changeProperty("error", false); this.changeProperty("error", false);
if (!(this._cfg.formatError && this._cfg.formatErrorMessages.length) if (!(this._cfg.formatError && this._cfg.formatErrorMessages.length)
|| (this._cfg.error && this._cfg.errorMessages.length)) { || (this._cfg.error && this._cfg.errorMessages.length)) {
this._validationPopupHide(this); this._validationPopupHide();
} }
if (this._cfg.onchange) { if (this._cfg.onchange) {
this.evalCallback(this._cfg.onchange); this.evalCallback(this._cfg.onchange);
Expand Down
234 changes: 143 additions & 91 deletions src/aria/widgets/form/TextInput.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -197,40 +197,97 @@ Aria.classDefinition({
}, },


/** /**
* Internal method to process the input block markup inside the frame * Get the text value of the input field. If available it tries to use the internal valid value, otherwise uses
* @param {aria.templates.MarkupWriter} out the writer Object to use to output markup * the invalid text. If none of them is a non empty string it return the prefilled value. This method doesn't
* @protected * handle helptext, as this value is not just text but also style.
* @return {String}
*/ */
_inputWithFrameMarkup : function (out) { _getText : function () {
var cfg = this._cfg, skinObj = this._skinObj, hts = this._helpTextSet, htc = this._skinObj.helpText, color = this._getTextFieldColor(), report; var cfg = this._cfg;
var stringUtils = aria.utils.String;


var inlineStyle = ['padding:', skinObj.innerPaddingTop, 'px ', skinObj.innerPaddingRight, 'px ', // invalid text and value shouldn't be set at the same time
skinObj.innerPaddingBottom, 'px ', skinObj.innerPaddingLeft, 'px;position:relative;margin:0;']; var text = cfg.invalidText || "";
if (!this._simpleHTML) {
inlineStyle.push("background-color:transparent;border-width:0px;vertical-align:top;"); if (text && cfg.value) {
// There's both a value and an invalid text, prefer the value
this.setProperty("invalidText", null);
text = "";
} }


// check value to set appropriate state and text // Validate the value in the configuration
var text = cfg.invalidText || "";
var res = this.checkValue({ var res = this.checkValue({
text : text, text : text,
value : cfg.value, value : cfg.value,
performCheckOnly : true performCheckOnly : true
}); });

if (res.report) { if (res.report) {
report = res.report; var report = res.report;
if (!text && report.text != null) { if (!text && report.text != null) {
text = '' + report.text; // String cast text = '' + report.text; // String cast of valid value
} }
report.$dispose(); report.$dispose();
} }
if (!text) { if (!text) {
var prefillText = (cfg.prefill && this.controller && this.controller.getDisplayTextFromValue) text = this._getPrefilledText(cfg.prefill);
? this.controller.getDisplayTextFromValue(cfg.prefill) }
: cfg.prefill;
text = prefillText; return text;
},

/**
* Set a given text as value for the text input. This method handles helptext for non password fields.
* @param {String} value Text to be set, if empty uses the value from <code>this._getText</code> or the
* helptext
*/
_setText : function (value) {
if (value == null) {
value = this._getText();
}

// _getText only handles valid / invalid values and prefills, not the helptext
if (!value && !this._isPassword) {
// We don't want to handle helptext in password fields, first remove any text
this.getTextInputField().value = "";
this.setHelpText(true);
} else if (value) {
this.getTextInputField().value = value;
}
},

/**
* Get the text value that should be prefilled in the widget. It takes a default value that could be anything
* (like dates). For non string objects it delegates the string resolution to the controller.
* @param {Object} value
* @return {String}
* @protected
*/
_getPrefilledText : function (value) {
if (value && this.controller && this.controller.getDisplayTextFromValue) {
return this.controller.getDisplayTextFromValue(this._cfg.prefill);
} else {
return value;
}
},

/**
* Internal method to process the input block markup inside the frame
* @param {aria.templates.MarkupWriter} out the writer Object to use to output markup
* @protected
*/
_inputWithFrameMarkup : function (out) {
var cfg = this._cfg, skinObj = this._skinObj, hts = this._helpTextSet, htc = this._skinObj.helpText, color = this._getTextFieldColor();
var stringUtils = aria.utils.String;

var inlineStyle = ['padding:', skinObj.innerPaddingTop, 'px ', skinObj.innerPaddingRight, 'px ',
skinObj.innerPaddingBottom, 'px ', skinObj.innerPaddingLeft, 'px;position:relative;margin:0;'];
if (!this._simpleHTML) {
inlineStyle.push("background-color:transparent;border-width:0px;vertical-align:top;");
} }

// check value to set appropriate state and text
var text = this._getText();

if (hts) { if (hts) {
// FIXME : re-activate helpText in password field in IE // FIXME : re-activate helpText in password field in IE
if (this._isIE7OrLess && this._isPassword) { if (this._isIE7OrLess && this._isPassword) {
Expand Down Expand Up @@ -309,16 +366,27 @@ Aria.classDefinition({
}, },


/** /**
* Check that the value displayed in the field is correct If not, set the field in error * Check that the value displayed in the field is correct. If not, set the field in error and store its invalid
* @param {JSON cfg} arg - optional arguments to control the check behavior * text
* @param {Object} arg - optional arguments to control the behavior
* *
* <pre> * <pre>
* { * {
* text: {String} (default:null) - display text, * text: {String} (default:null) - display text,
* value: {Object} - internal widget value, * value: {Object} - internal widget value,
* performCheckOnly: {Boolean} - perfom only value/text check do not update th widget display, * performCheckOnly: {Boolean} - perfom only value/text check do not update th widget display,
* resetErrorIfOK: {Boolean} (default:true) - tells if error display must be removed if check is OK * resetErrorIfOK: {Boolean} (default:true) - tells if error display must be removed if check is OK
* (usefull when check is done on 'strange' events like mouseover } * (usefull when check is done on 'strange' events like mouseover)
* }
* </pre>
*
* @return {Object}
*
* <pre>
* {
* isValid : {Boolean} Whether the value is valid or not
* report : {Object} Controller's report, if any
* }
* </pre> * </pre>
*/ */
checkValue : function (arg) { checkValue : function (arg) {
Expand All @@ -338,60 +406,55 @@ Aria.classDefinition({
this.changeProperty("formatError", false); this.changeProperty("formatError", false);
} }


if (this.controller) { var result = {
isValid : true,
report : null
};


var hasErrors = (this._cfg.formatErrorMessages.length ? true : false); if (!this.controller) {
var report; // There's no controller so we assume the value to be valid
// if (value != null || performCheckOnly) { return result;
if (value != null) { }
report = this.controller.checkValue(value);
} else {
report = this.controller.checkText(text, hasErrors);
}


if (report) { var hasErrors = (this._cfg.formatErrorMessages.length ? true : false);
if (report.errorMessages.length) { var report;
this.changeProperty("invalidText", text);
if (this._cfg.directOnBlurValidation && !performCheckOnly) { if (value != null) {
this.changeProperty("formatErrorMessages", report.errorMessages); report = this.controller.checkValue(value);
} } else {
} else if (this._cfg.formatError === false report = this.controller.checkText(text, hasErrors);
&& (aria.utils.Type.isArray(this._cfg.formatErrorMessages) && this._cfg.formatErrorMessages.length)) { }
this.changeProperty("invalidText", null);
this.changeProperty("formatErrorMessages", []); if (!report) {
} else { // No report means that the controller is handling the value asynchronously, consider it as valid
if (report.ok) { return result;
this.changeProperty("invalidText", null); }
}
} if (report.errorMessages.length) {
if (performCheckOnly) { if (!performCheckOnly) {
return { this.changeProperty("value", null);
isValid : report.ok, this.changeProperty("invalidText", text);
report : report if (this._cfg.directOnBlurValidation) {
}; this.changeProperty("formatErrorMessages", report.errorMessages);
} else {
this._reactToControllerReport(report, arg);
return;
} }
} else {
return {
isValid : true,
report : null
};
} }
} else if (this._cfg.formatError === false && aria.utils.Type.isArray(this._cfg.formatErrorMessages)
&& this._cfg.formatErrorMessages.length) {
this.changeProperty("invalidText", null);
this.changeProperty("formatErrorMessages", []);
} else if (report.ok && !performCheckOnly) {
this.changeProperty("invalidText", null);
}


} else { if (performCheckOnly) {
return { return {
isValid : true, isValid : report.ok,
report : null report : report
}; };
} else {
this._reactToControllerReport(report, arg);
return;
} }

return {
isValid : true,
report : null
};

}, },


/** /**
Expand Down Expand Up @@ -580,7 +643,7 @@ Aria.classDefinition({
return; return;
} }


// in case things have change the field, try to set an helptext // in case things have changed the field, try to set an helptext
this.setHelpText(true); this.setHelpText(true);
if (((aria.utils.Type.isArray(cfg.value) && aria.utils.Array.isEmpty(cfg.value)) || !cfg.value) if (((aria.utils.Type.isArray(cfg.value) && aria.utils.Array.isEmpty(cfg.value)) || !cfg.value)
&& cfg.prefill && cfg.prefill + "") { && cfg.prefill && cfg.prefill + "") {
Expand All @@ -606,7 +669,7 @@ Aria.classDefinition({
if (!res || !res.isValid) { if (!res || !res.isValid) {
var textField = this.getTextInputField(); var textField = this.getTextInputField();
if (textField) { if (textField) {
textField.value = newValue; this._setText(newValue);
} }
} }
if (res && res.report) { if (res && res.report) {
Expand Down Expand Up @@ -732,9 +795,9 @@ Aria.classDefinition({
} }


if (arg.popup && (this._cfg.error)) { if (arg.popup && (this._cfg.error)) {
this._validationPopupShow(this); this._validationPopupShow();
} else { } else {
this._validationPopupHide(this); this._validationPopupHide();
} }
}, },


Expand Down Expand Up @@ -817,7 +880,7 @@ Aria.classDefinition({
cfg = this._cfg cfg = this._cfg
if (cfg.validationEvent === 'onFocus' if (cfg.validationEvent === 'onFocus'
&& ((cfg.formatError && cfg.formatErrorMessages.length) || (cfg.error && cfg.errorMessages.length))) { && ((cfg.formatError && cfg.formatErrorMessages.length) || (cfg.error && cfg.errorMessages.length))) {
this._validationPopupShow(this); this._validationPopupShow();
} }
} }
this._updateState(); this._updateState();
Expand Down Expand Up @@ -871,10 +934,10 @@ Aria.classDefinition({


if (cfg.formatError && cfg.validationEvent === 'onBlur') { if (cfg.formatError && cfg.validationEvent === 'onBlur') {
// show errortip on blur used for debug purposes // show errortip on blur used for debug purposes
this._validationPopupShow(this); this._validationPopupShow();
} else { } else {
// dispose of error tip // dispose of error tip
this._validationPopupHide(this); this._validationPopupHide();
if (cfg.directOnBlurValidation) { if (cfg.directOnBlurValidation) {
if (cfg.bind) { if (cfg.bind) {
var bind = cfg.bind.value; var bind = cfg.bind.value;
Expand Down Expand Up @@ -914,18 +977,12 @@ Aria.classDefinition({
_setAutomaticBindings : function (cfg) { _setAutomaticBindings : function (cfg) {
this.$InputWithFrame._setAutomaticBindings.call(this, cfg); this.$InputWithFrame._setAutomaticBindings.call(this, cfg);
var value = null, prefill = null, metaDataObject; var value = null, prefill = null, metaDataObject;
if (cfg) { if (cfg && cfg.bind) {
if (cfg.bind) { value = cfg.bind.value;
value = cfg.bind.value; // get any binding on the value prefill = cfg.bind.prefill;
// property
prefill = cfg.bind.prefill; // get any binding on the
// prefill property
}
} }


if (value && value.inside) { // only add the meta data convention if (value && value.inside) {
// if a value property has been
// bound
metaDataObject = aria.utils.Data._getMeta(value.inside, value.to, false); metaDataObject = aria.utils.Data._getMeta(value.inside, value.to, false);
if (!cfg.bind.invalidText) { if (!cfg.bind.invalidText) {
cfg.bind.invalidText = { cfg.bind.invalidText = {
Expand All @@ -934,10 +991,7 @@ Aria.classDefinition({
}; };
} }
} }
if (prefill && prefill.inside) { // only add the meta data if (prefill && prefill.inside) {
// convention if a prefill
// property has been
// bound
metaDataObject = aria.utils.Data._getMeta(prefill.inside, prefill.to, false); metaDataObject = aria.utils.Data._getMeta(prefill.inside, prefill.to, false);
if (!cfg.bind.prefillError) { if (!cfg.bind.prefillError) {
cfg.bind.prefillError = { cfg.bind.prefillError = {
Expand Down Expand Up @@ -1085,9 +1139,7 @@ Aria.classDefinition({
if (value == null) { if (value == null) {
prefillText = ""; prefillText = "";
} else { } else {
prefillText = (this.controller && this.controller.getDisplayTextFromValue) prefillText = this._getPrefilledText(value);
? this.controller.getDisplayTextFromValue(value)
: value;
} }
if (cfg.prefillError) { if (cfg.prefillError) {
prefillText = ""; prefillText = "";
Expand Down
1 change: 1 addition & 0 deletions test/aria/widgets/WidgetsTestSuite.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ Aria.classDefinition({
this.addTests("test.aria.widgets.form.TextareaTest"); this.addTests("test.aria.widgets.form.TextareaTest");
this.addTests("test.aria.widgets.form.TextInputTest"); this.addTests("test.aria.widgets.form.TextInputTest");
this.addTests("test.aria.widgets.form.multiselect.issue223.MultiSelect"); this.addTests("test.aria.widgets.form.multiselect.issue223.MultiSelect");
this.addTests("test.aria.widgets.form.datepicker.DatePickerTestSuite");
} }
}); });
Loading