UNPKG

devexpress-reporting

Version:

DevExpress Reporting provides the capability to develop a reporting application to create and customize reports.

192 lines (191 loc) 8.85 kB
/** * DevExpress HTML/JS Reporting (viewer\editing\models\textEditingField.js) * Version: 24.2.6 * Build date: Mar 18, 2025 * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED * License: https://www.devexpress.com/Support/EULAs/universal.xml */ import { brickStyleSerializationsInfo } from '../../../common/metadata'; import { EditingFieldExtensions, ___isCancelFlag } from '../../../common/utils/editingFieldExtensions'; import { processTextEditorHotKeys, CssCalculator, $dx, extend, getParentContainer } from '@devexpress/analytics-core/analytics-internal-native'; import { createViewModelGenerator, currentModelSerializer, currentMultiPlatformEngine } from '@devexpress/analytics-core/analytics-serializer-native'; import { EditingFieldBase } from './editingFieldBase'; export class TextEditingFieldViewModelBase extends EditingFieldBase { constructor() { super(...arguments); this.canActivateEditor = true; } keypressAction(data, event) { this.field._editorValue = event.target['value']; processTextEditorHotKeys(event, { esc: () => { this.hideEditor(false, true); }, ctrlEnter: () => { this.hideEditor(true, true); } }); } createViewModel() { return createViewModelGenerator(super.createViewModel()) .generateProperty('textStyle', this.textStyle) .getViewModel(); } activateEditor(model, event, elementFocused = false) { const eventTarget = event?.currentTarget; if (!elementFocused) { setTimeout(() => { focusTextElement(eventTarget); }); } } } export class TextEditingFieldViewModel extends TextEditingFieldViewModelBase { constructor(field, pageWidth, pageHeight, page, bounds) { super(page); this.template = 'dxrp-editing-field-container'; this.wordWrap = true; this.canActivateEditor = true; const brickStyle = field.model().brickOptions; const style = { rtl: () => brickStyle.rtl }; currentModelSerializer().deserialize(style, JSON.parse(brickStyle.style), brickStyleSerializationsInfo); const cssCalculator = new CssCalculator(style, !!brickStyle.rtlLayout); const padding = cssCalculator.paddingsCss(); let verticalPadding = parseInt(padding['paddingTop']) + parseInt(padding['paddingBottom']); if (cssCalculator.borderCss()['borderTop'] !== 'none') { verticalPadding += currentMultiPlatformEngine.unwrap(style['borderWidth']); } if (cssCalculator.borderCss()['borderBottom'] !== 'none') { verticalPadding += currentMultiPlatformEngine.unwrap(style['borderWidth']); } this.breakOffsetStyle = { top: bounds.offset.y * -100 / bounds.height + '%', left: bounds.offset.x * -100 / bounds.width + '%' }; this.textStyle = extend({}, cssCalculator.fontCss(), cssCalculator.foreColorCss(), cssCalculator.textAlignmentCss()); this.field = field; if (brickStyle.wordWrap != undefined) { this.wordWrap = brickStyle.wordWrap; } this.hideEditor = (shouldCommit, preserveFocus) => { setTimeout(() => { if (shouldCommit && this.active) { if (editorOptions.onHideEditor) { editorOptions.onHideEditor(field); } else { field.setEditValue(field._editorValue); } } else { field._editorValue = field.getEditValue(); } if (preserveFocus) this.editingFieldElement.focus(); this.active = false; }, 1); }; const editor = EditingFieldExtensions.instance().editor(field.editorName()); const editorOptions = extend(true, {}, editor?.options || {}); this.data = createViewModelGenerator().createDefaultModel(this) .generateProperty('value', field._editorValue) .generateProperty('hideEditor', (shouldCommit) => this.hideEditor(shouldCommit, false)) .generateProperty('keypressAction', (data, event) => this.keypressAction(data, event)) .generateProperty('textStyle', this.textStyle) .generateProperty('options', editorOptions) .generateProperty('getPopupContainer', getParentContainer) .generateProperty('getOptions', (templateOptions) => extend({}, this.data.options, templateOptions)) .getViewModel(); const isCustomEditor = !!(editor && editor.template && editor.template !== 'dxrp-editing-field-datetime'); if (!isCustomEditor) { const self = this; this.data.options = extend(true, {}, editorOptions, { value: field._editorValue, onValueChanged: (event) => { if (!event.component[___isCancelFlag]) { editorOptions?.onValueChanged && editorOptions?.onValueChanged(event); this.field._editorValue = event.value; this.data.options.value = event.value; } }, onFocusOut: (e) => { self.hideEditor(true, false); } }); } if (editor) { this.editorTemplate = editor.template || 'dxrp-editing-field-mask'; } else { this.editorTemplate = 'dxrp-editing-field-text'; } this._updateContainerStyle = () => { if (!bounds) return; this.containerStyle = extend({ width: bounds.width + 'px', height: bounds.height + 'px', 'line-height': (bounds.height - verticalPadding) + 'px', top: bounds.top * 100 / pageHeight + '%', left: bounds.left * 100 / pageWidth + '%', cursor: this.field.readOnly ? 'auto' : 'text' }, this.active || !this.field.htmlValue ? cssCalculator.borderCss() : { border: 'none' }, isCustomEditor && this.active || (!!this.field.htmlValue && !this.active) ? { padding: 0 } : cssCalculator.paddingsCss(), { 'border-color': 'transparent' }); }; const borderWidth = currentMultiPlatformEngine.unwrap(style['borderWidth']); const borders = currentMultiPlatformEngine.unwrap(style['borders']); if (borderWidth && borderWidth > 0 && borders !== 'None') { this.borderStyle = { left: '-' + borderWidth + 'px', top: '-' + borderWidth + 'px', paddingRight: (borderWidth * 2 - 2) + 'px', paddingBottom: (borderWidth * 2 - 2) + 'px' }; } this.addDisposable(this.field.events.on('htmlValueChanged', (args) => { this._updateContainerStyle(); }), this.field.events.on('readOnlyChanged', (args) => { this._updateContainerStyle(); }), this.field.events.on('_editorValueChanged', (args) => { this.data.value = this.field._editorValue; })); this._updateContainerStyle(); } onPropertyChanged(args) { if (args.propertyName === 'active') this._updateContainerStyle(); } createViewModel() { return createViewModelGenerator(super.createViewModel()) .generateProperty('borderStyle', this.borderStyle) .generateProperty('breakOffsetStyle', this.breakOffsetStyle) .generateProperty('wordWrap', this.wordWrap) .generateProperty('editorTemplate', this.editorTemplate) .generateProperty('data', this.data) .getViewModel(); } activateEditor(viewModel, e) { if (this.field.readOnly || this.active) { return; } const data = viewModel.data; if (data && data.options && data.options.onPreRender) { data.options.onPreRender(this.data, this.field); } this.active = true; let elementFocused = false; const options = viewModel['options']; if (options?.onEditorShown) { elementFocused = options.onEditorShown(this.data, e?.currentTarget); } super.activateEditor(viewModel, e, elementFocused); } } export function focusTextElement(target) { const element = $dx(target).find('input:visible').element || $dx(target).find('textarea:visible').element; if (!element) return; element?.focus(); if (element['setSelectionRange']) { element['setSelectionRange'](element['value'].length, element['value'].length); } }