devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
339 lines (286 loc) • 10.9 kB
JavaScript
"use strict";
var $ = require("../../core/renderer"),
dataUtils = require("../../core/element_data"),
Callbacks = require("../../core/utils/callbacks"),
commonUtils = require("../../core/utils/common"),
windowUtils = require("../../core/utils/window"),
getDefaultAlignment = require("../../core/utils/position").getDefaultAlignment,
extend = require("../../core/utils/extend").extend,
Widget = require("../widget/ui.widget"),
ValidationMixin = require("../validation/validation_mixin"),
Overlay = require("../overlay");
var READONLY_STATE_CLASS = "dx-state-readonly",
INVALID_CLASS = "dx-invalid",
INVALID_MESSAGE = "dx-invalid-message",
INVALID_MESSAGE_AUTO = "dx-invalid-message-auto",
INVALID_MESSAGE_ALWAYS = "dx-invalid-message-always",
VALIDATION_TARGET = "dx-validation-target",
VALIDATION_MESSAGE_MIN_WIDTH = 100;
/**
* @name Editor
* @publicName Editor
* @type object
* @inherits Widget
* @module ui/editor/editor
* @export default
* @hidden
*/
var Editor = Widget.inherit({
_init: function _init() {
this.callBase();
this.validationRequest = Callbacks();
var $element = this.$element();
if ($element) {
dataUtils.data($element[0], VALIDATION_TARGET, this);
}
},
_getDefaultOptions: function _getDefaultOptions() {
return extend(this.callBase(), {
/**
* @name EditorOptions.value
* @publicName value
* @type any
* @default null
* @fires EditorOptions.onValueChanged
*/
value: null,
/**
* @name EditorOptions.name
* @publicName name
* @type string
* @default ""
* @hidden
*/
name: "",
/**
* @name EditorOptions.onValueChanged
* @publicName onValueChanged
* @extends Action
* @type function(e)
* @type_function_param1 e:object
* @type_function_param1_field4 value:object
* @type_function_param1_field5 previousValue:object
* @type_function_param1_field6 jQueryEvent:jQuery.Event:deprecated(event)
* @type_function_param1_field7 event:event
* @action
*/
onValueChanged: null,
/**
* @name EditorOptions.readOnly
* @publicName readOnly
* @type boolean
* @default false
*/
readOnly: false,
/**
* @name EditorOptions.isValid
* @publicName isValid
* @type boolean
* @default true
*/
isValid: true,
/**
* @name EditorOptions.validationError
* @publicName validationError
* @type object
* @ref
* @default undefined
*/
validationError: null,
/**
* @name EditorOptions.validationMessageMode
* @publicName validationMessageMode
* @type Enums.ValidationMessageMode
* @default "auto"
*/
validationMessageMode: "auto",
validationBoundary: undefined,
validationMessageOffset: { h: 0, v: 0 }
});
},
_attachKeyboardEvents: function _attachKeyboardEvents() {
if (this.option("readOnly")) {
return;
}
this.callBase();
if (this._keyboardProcessor) {
this._attachChildKeyboardEvents();
}
},
_attachChildKeyboardEvents: commonUtils.noop,
_setOptionsByReference: function _setOptionsByReference() {
this.callBase();
extend(this._optionsByReference, {
validationError: true
});
},
_createValueChangeAction: function _createValueChangeAction() {
this._valueChangeAction = this._createActionByOption("onValueChanged", {
excludeValidators: ["disabled", "readOnly"]
});
},
_suppressValueChangeAction: function _suppressValueChangeAction() {
this._valueChangeActionSuppressed = true;
},
_resumeValueChangeAction: function _resumeValueChangeAction() {
this._valueChangeActionSuppressed = false;
},
_initMarkup: function _initMarkup() {
this._toggleReadOnlyState();
this._setSubmitElementName(this.option("name"));
this.callBase();
this._renderValidationState();
},
_raiseValueChangeAction: function _raiseValueChangeAction(value, previousValue) {
if (!this._valueChangeAction) {
this._createValueChangeAction();
}
this._valueChangeAction(this._valueChangeArgs(value, previousValue));
},
_valueChangeArgs: function _valueChangeArgs(value, previousValue) {
return {
value: value,
previousValue: previousValue,
event: this._valueChangeEventInstance
};
},
_saveValueChangeEvent: function _saveValueChangeEvent(e) {
this._valueChangeEventInstance = e;
},
_renderValidationState: function _renderValidationState() {
var isValid = this.option("isValid"),
validationError = this.option("validationError"),
validationMessageMode = this.option("validationMessageMode"),
$element = this.$element();
$element.toggleClass(INVALID_CLASS, !isValid);
this.setAria("invalid", !isValid || undefined);
if (!windowUtils.hasWindow()) {
return;
}
if (this._$validationMessage) {
this._$validationMessage.remove();
this._$validationMessage = null;
}
if (!isValid && validationError && validationError.message) {
this._$validationMessage = $("<div>").addClass(INVALID_MESSAGE).html(validationError.message).appendTo($element);
this._validationMessage = this._createComponent(this._$validationMessage, Overlay, {
integrationOptions: {},
templatesRenderAsynchronously: false,
target: this._getValidationMessageTarget(),
shading: false,
width: 'auto',
height: 'auto',
container: $element,
position: this._getValidationMessagePosition("below"),
closeOnOutsideClick: false,
closeOnTargetScroll: false,
animation: null,
visible: true,
propagateOutsideClick: true,
_checkParentVisibility: false
});
this._$validationMessage.toggleClass(INVALID_MESSAGE_AUTO, validationMessageMode === "auto").toggleClass(INVALID_MESSAGE_ALWAYS, validationMessageMode === "always");
this._setValidationMessageMaxWidth();
}
},
_setValidationMessageMaxWidth: function _setValidationMessageMaxWidth() {
if (!this._validationMessage) {
return;
}
if (this._getValidationMessageTarget().outerWidth() === 0) {
this._validationMessage.option("maxWidth", "100%");
return;
}
var validationMessageMaxWidth = Math.max(VALIDATION_MESSAGE_MIN_WIDTH, this._getValidationMessageTarget().outerWidth());
this._validationMessage.option("maxWidth", validationMessageMaxWidth);
},
_getValidationMessageTarget: function _getValidationMessageTarget() {
return this.$element();
},
_getValidationMessagePosition: function _getValidationMessagePosition(positionRequest) {
var rtlEnabled = this.option("rtlEnabled"),
messagePositionSide = getDefaultAlignment(rtlEnabled),
messageOriginalOffset = this.option("validationMessageOffset"),
messageOffset = { h: messageOriginalOffset.h, v: messageOriginalOffset.v },
verticalPositions = positionRequest === "below" ? [" top", " bottom"] : [" bottom", " top"];
if (rtlEnabled) messageOffset.h = -messageOffset.h;
if (positionRequest !== "below") messageOffset.v = -messageOffset.v;
return {
offset: messageOffset,
boundary: this.option("validationBoundary"),
my: messagePositionSide + verticalPositions[0],
at: messagePositionSide + verticalPositions[1],
collision: "none flip"
};
},
_toggleReadOnlyState: function _toggleReadOnlyState() {
this.$element().toggleClass(READONLY_STATE_CLASS, !!this.option("readOnly"));
this.setAria("readonly", this.option("readOnly") || undefined);
},
_dispose: function _dispose() {
var element = this.$element()[0];
dataUtils.data(element, VALIDATION_TARGET, null);
this.callBase();
},
_setSubmitElementName: function _setSubmitElementName(name) {
var $submitElement = this._getSubmitElement();
if (!$submitElement) {
return;
}
if (name.length > 0) {
$submitElement.attr("name", name);
} else {
$submitElement.removeAttr("name");
}
},
_getSubmitElement: function _getSubmitElement() {
return null;
},
_optionChanged: function _optionChanged(args) {
switch (args.name) {
case "onValueChanged":
this._createValueChangeAction();
break;
case "isValid":
case "validationError":
case "validationBoundary":
case "validationMessageMode":
this._renderValidationState();
break;
case "readOnly":
this._toggleReadOnlyState();
this._refreshFocusState();
break;
case "value":
if (!this._valueChangeActionSuppressed) {
this._raiseValueChangeAction(args.value, args.previousValue);
this._saveValueChangeEvent(undefined);
}
if (args.value != args.previousValue) {
// jshint ignore:line
this.validationRequest.fire({
value: args.value,
editor: this
});
}
break;
case "width":
this.callBase(args);
this._setValidationMessageMaxWidth();
break;
case "name":
this._setSubmitElementName(args.value);
break;
default:
this.callBase(args);
}
},
/**
* @name EditorMethods.reset
* @publicName reset()
*/
reset: function reset() {
this.option("value", null);
}
}).include(ValidationMixin);
module.exports = Editor;