UNPKG

devexpress-reporting

Version:

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

269 lines (268 loc) 13.4 kB
/** * DevExpress HTML/JS Reporting (designer\controls\utils\_bindings.js) * Version: 25.1.3 * Build date: Jun 26, 2025 * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED * License: https://www.devexpress.com/Support/EULAs/universal.xml */ import * as ko from 'knockout'; import { XRCheckBoxSurface } from '../xrCheckbox'; import { controlsFactory } from '../../utils/settings'; import { ImageSource } from '../../../common/imageSource'; import { findSurface, extend, NotifyAboutWarning, formatUnicorn, getLocalization, base64DecodeUnicode } from '@devexpress/analytics-core/analytics-internal'; import { BandViewModel } from '../../bands/xrBand'; const svgAttrs = ko.bindingHandlers['svgAttrs']; ko.bindingHandlers['svgAttrs'] = { update: function (element, valueAccessor, allBindingsAccessor, viewModel) { svgAttrs.update(element, valueAccessor, allBindingsAccessor, viewModel); if (viewModel instanceof XRCheckBoxSurface) { element.setAttribute('preserveAspectRatio', 'none'); } } }; const checkControlsUnderDropPoint = (event, domElement, controls) => { let result = false; const dropX = event.clientX; const dropY = event.clientY; const elementRect = domElement.getBoundingClientRect(); for (const control of controls) { const x = elementRect.x + control.location.x(); const y = elementRect.y + control.location.y(); const width = control.size.width(); const height = control.size.height(); if (dropX >= x && dropX <= x + width && dropY >= y && dropY <= y + height) { result = true; } } return result; }; const checkIfControlSupportFile = (controlType) => { const notifyControlNotSupportFile = (control, fileTypes) => { NotifyAboutWarning(formatUnicorn(getLocalization('{0} does not support this file type. You can upload files with the following types: {1}.', 'ASPxReportsStringId.ReportDesigner_DropFileWarning_ControlNotSupportFile'), control, fileTypes), true); }; switch (controlType) { case 'XRPictureBox': { notifyControlNotSupportFile(getLocalization('Picture Box', 'DevExpress.XtraReports.UI.XRPictureBox'), 'PNG, JPG, JPEG'); return true; } case 'XRPdfContent': { notifyControlNotSupportFile(getLocalization('PDF Content', 'DevExpress.XtraReports.UI.XRPdfContent'), 'PDF'); return true; } case 'XRRichText': { notifyControlNotSupportFile(getLocalization('Rich Text', 'DevExpress.XtraReports.UI.XRRichText'), 'DOCX, RTF, HTML, TXT'); return true; } case 'XRLabel': { notifyControlNotSupportFile(getLocalization('Label', 'DevExpress.XtraReports.UI.XRLabel'), 'TXT'); return true; } default: return false; } }; const mapTypeToRichFormat = { 'application/msword': 'rtf', 'text/html': 'html', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx', 'text/plain': 'txt', }; const createControl = (type) => { const infoObject = extend({ '@ControlType': type }, controlsFactory().controlsMap[type].defaultVal); return controlsFactory().createControl(infoObject, null); }; const getDropTargetSurface = (control, bandToDrop) => { const parent = control.getNearestParent(bandToDrop); return findSurface(parent); }; const dropedFileHandler = (files, dropTarget, dragDropHandler) => { const isFit = dropTarget.root?.surface?.isFit; const file = files[0]; const reader = new FileReader(); if (!dropTarget) { return; } reader.onload = (loadEvent) => { try { const fileContent = loadEvent.target?.result; const formatted = (fileContent).replace(/(^data:[^,]+,)|(^data:)/, ''); switch (true) { case file.type.startsWith('image/'): { if (dropTarget.controlType !== 'XRPictureBox' && checkIfControlSupportFile(dropTarget.controlType)) { break; } if (dropTarget.controlType === 'XRPictureBox') { dropTarget.imageSource(new ImageSource('img', formatted)); break; } if (dropTarget instanceof BandViewModel) { const pictureBox = createControl('XRPictureBox'); pictureBox.imageSource(new ImageSource('img', formatted)); const dropTargetSurface = getDropTargetSurface(pictureBox, dropTarget); if (isFit && isFit(dropTargetSurface)) { dragDropHandler.addControl(pictureBox, dropTargetSurface, pictureBox.size); } break; } break; } case file.type === 'application/pdf': { if (dropTarget.controlType !== 'XRPdfContent' && checkIfControlSupportFile(dropTarget.controlType)) { break; } if (dropTarget.controlType === 'XRPdfContent') { dropTarget.source(formatted); break; } const pdfContent = createControl('XRPdfContent'); pdfContent.source(formatted); if (dropTarget instanceof BandViewModel) { if (dropTarget.controlType === 'TopMarginBand' || dropTarget.controlType === 'BottomMarginBand') { const topMarginString = getLocalization('Top Margin', 'DevExpress.XtraReports.UI.TopMarginBand'); const bottomMarginString = getLocalization('Bottom Margin', 'DevExpress.XtraReports.UI.BottomMarginBand'); const pdfContentString = getLocalization('PDF Content', 'DevExpress.XtraReports.UI.XRPdfContent'); const localizedFormatedMessage = formatUnicorn(getLocalization('{0} control could not be created in the following bands: {1}.', 'ASPxReportsStringId.ReportDesigner_DropFileWarning_BandNotSupportControl'), pdfContentString, `${topMarginString}, ${bottomMarginString}`); NotifyAboutWarning(localizedFormatedMessage, true); break; } const dropTargetSurface = getDropTargetSurface(pdfContent, dropTarget); if (isFit && isFit(dropTargetSurface)) { dragDropHandler.addControl(pdfContent, dropTargetSurface, pdfContent.size); } break; } break; } case !!mapTypeToRichFormat[file.type]: { if (dropTarget.controlType === 'XRLabel' && file.type === 'text/plain') { const content = base64DecodeUnicode(formatted); dropTarget.text(content); break; } if (dropTarget.controlType !== 'XRRichText' && checkIfControlSupportFile(dropTarget.controlType)) { break; } const format = mapTypeToRichFormat[file.type]; if (dropTarget.controlType === 'XRRichText') { dropTarget._newDocumentData({ format, content: formatted, contentType: 'base64' }); break; } const richTextContentRtf = createControl('XRRichText'); richTextContentRtf._newDocumentData({ format, content: formatted, contentType: 'base64' }); if (dropTarget instanceof BandViewModel && file.type !== 'text/plain') { const dropTargetSurface = getDropTargetSurface(richTextContentRtf, dropTarget); if (isFit && isFit(dropTargetSurface)) { dragDropHandler.addControl(richTextContentRtf, dropTargetSurface, richTextContentRtf.size); } break; } } case file.type === 'text/plain': { if (dropTarget.controlType !== 'XRLabel' && checkIfControlSupportFile(dropTarget.controlType)) { break; } const textControl = createControl('XRLabel'); const content = base64DecodeUnicode(formatted); textControl.text(content); if (dropTarget instanceof BandViewModel) { const dropTargetSurface = getDropTargetSurface(textControl, dropTarget); if (isFit && isFit(dropTargetSurface)) { dragDropHandler.addControl(textControl, dropTargetSurface, textControl.size); } break; } break; } default: NotifyAboutWarning(formatUnicorn(getLocalization('File type not supported. You can upload files in the following formats: {0}.', 'ASPxReportsStringId.ReportDesigner_DropFileWarning_WrongFormat'), 'PNG, JPG, JPEG, PDF, TXT, DOCX, RTF, HTML'), true); break; } } catch (error) { console.error(error); } }; reader.readAsDataURL(file); }; ko.bindingHandlers['dragDropFileToControl'] = { init: (element, valueAccessor, allBindings, viewModel, bindingContext) => { const { dragDropFileEnabled } = valueAccessor(); if (!ko.unwrap(dragDropFileEnabled)) { return; } let counter = 0; element.addEventListener('dragenter', event => { event.stopPropagation(); counter++; viewModel.showDropBorders && viewModel.showDropBorders(true); }); element.addEventListener('dragleave', event => { event.stopPropagation(); counter--; if (counter === 0) { viewModel.showDropBorders && viewModel.showDropBorders(false); } }); element.addEventListener('dragover', event => { event.preventDefault(); }); element.addEventListener('drop', event => { event.preventDefault(); event.stopPropagation(); viewModel.showDropBorders && viewModel.showDropBorders(false); counter = 0; const { dragDropHandler } = valueAccessor(); const files = event.dataTransfer.files; const dropTarget = viewModel.getControlModel && viewModel.getControlModel(); if (dropTarget instanceof BandViewModel) { if (checkControlsUnderDropPoint(event, element, dropTarget.controls())) { NotifyAboutWarning(getLocalization('This control does not support file uploads.', 'ASPxReportsStringId.ReportDesigner_DropFileWarning_ControlNotSupportUpload'), true); return; } } dragDropHandler.snapToGridOnCreateControl = dragDropHandler.snapHelper.getSnappingMode() === 'SnapToGrid' && event.altKey !== true; files.length > 0 && dropedFileHandler(files, dropTarget, dragDropHandler); }); }, }; ko.bindingHandlers['dragDropJsonToDataSource'] = { init: (element, valueAccessor, allBindings, viewModel, bindingContext) => { const jsonStringEditor = viewModel; element.addEventListener('dragenter', event => { event.stopPropagation(); viewModel.showDropBorders && viewModel.showDropBorders(true); }); element.addEventListener('dragleave', event => { event.stopPropagation(); viewModel.showDropBorders && viewModel.showDropBorders(false); }); element.addEventListener('dragover', event => { event.preventDefault(); }); element.addEventListener('drop', event => { event.preventDefault(); const files = event.dataTransfer.files; if (files.length > 0) { const file = files[0]; const format = file.name.split('.').pop(); if (format !== 'json') { return; } const reader = new FileReader(); reader.onload = (e) => { const fileContent = e.target?.result; jsonStringEditor.value(fileContent); }; reader.readAsText(file); } }); } };