diff --git a/common/Drawings/Metafile.js b/common/Drawings/Metafile.js index 845a2d1ad7..e3bfb0a7b2 100644 --- a/common/Drawings/Metafile.js +++ b/common/Drawings/Metafile.js @@ -837,6 +837,17 @@ this.data[this.pos++] = (c >>> 8) & 0xFF; } } + this.WriteCustomStringA = function(text) + { + var encoder = new TextEncoder('utf-8'); + var encodedText = encoder.encode(text); + + this.WriteULong(encodedText.length); + + for (let i = 0; i < encodedText.length; i++) { + this.data[this.pos++] = encodedText[i]; + } + } this.WriteStringA = function(text) { var count = text.length; diff --git a/common/HistoryCommon.js b/common/HistoryCommon.js index ea25d141bb..36d35e0e58 100644 --- a/common/HistoryCommon.js +++ b/common/HistoryCommon.js @@ -2346,7 +2346,8 @@ window['AscDFH'].historyitem_SdtPr_FormPr = window['AscDFH'].historyitem_type_SdtPr | 22; window['AscDFH'].historyitem_SdtPr_PictureFormPr = window['AscDFH'].historyitem_type_SdtPr | 23; window['AscDFH'].historyitem_SdtPr_ComplexFormPr = window['AscDFH'].historyitem_type_SdtPr | 24; - window['AscDFH'].historyitem_SdtPr_OForm = window['AscDFH'].historyitem_type_SdtPr | 24; + window['AscDFH'].historyitem_SdtPr_OForm = window['AscDFH'].historyitem_type_SdtPr | 25; + window['AscDFH'].historyitem_SdtPr_DataBinding = window['AscDFH'].historyitem_type_SdtPr | 26; //------------------------------------------------------------------------------------------------------------------ // Типы изменений в классе CSdtPr //------------------------------------------------------------------------------------------------------------------ diff --git a/configs/word.json b/configs/word.json index ef0dfee08a..33505129e6 100644 --- a/configs/word.json +++ b/configs/word.json @@ -33,6 +33,7 @@ "word/api.js", "word/api_plugins.js", "common/spell/spell.js", + "common/zlib/zlib.js", "word/Editor/Table/TableLook.js", "cell/utils/utils.js", "pdf/src/defines.js", @@ -76,7 +77,7 @@ "common/Drawings/Metafile.js", "common/libfont/textmeasurer.js", "common/Drawings/WorkEvents.js", - + "word/Editor/History.js", "common/Shapes/EditorSettings.js", @@ -150,13 +151,17 @@ "cell/model/Workbook.js", "cell/model/Serialize.js", "cell/model/CellInfo.js", - + + "word/Editor/custom-xml/custom-xml.js", + "word/Editor/custom-xml/custom-xml-manager.js", + "word/Editor/custom-xml/data-binding.js", + "word/Math/mathTypes.js", "word/Editor/Styles.js", "word/Math/math-settings.js", "word/Editor/StructuredDocumentTags/sdt-settings.js", "word/Editor/DocumentSettings.js", - + "word/Editor/Paragraph/Run/FontClassification.js", "word/Editor/Paragraph/Run/FontCalculator.js", "word/Editor/Paragraph/Run/run-composite-input.js", @@ -393,7 +398,7 @@ "word/Math/accent.js", "word/Math/borderBox.js", "word/Math/mathTrackHandler.js", - + "word/Editor/Styles/style-cache.js", "word/Editor/Styles/FixedFormDefaults.js", "word/Editor/Styles/default-styles.js", diff --git a/tests/word/customXML/customXML.html b/tests/word/customXML/customXML.html new file mode 100644 index 0000000000..3db4d28ddd --- /dev/null +++ b/tests/word/customXML/customXML.html @@ -0,0 +1,35 @@ + + + + + + Document calculation tests + + + + + + + + + + + + + + + + + +

Test forms

+

+
+

+
    +
    test markup, will be hidden
    + + diff --git a/tests/word/customXML/customXML.js b/tests/word/customXML/customXML.js new file mode 100644 index 0000000000..a48c82fa78 --- /dev/null +++ b/tests/word/customXML/customXML.js @@ -0,0 +1,795 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +$(function () { + + function MockZLibEngine () + { + this.files = []; + + this.open = function (buf) { + //console.log("ZLibFake: Open archive..."); + + if (Array.isArray(buf)) { + this.files = []; + this.data = {}; + buf.forEach(item => { + if (item.path && item.data) { + this.files.push(item.path); + this.data[item.path] = item.data; + } + }); + return this.files; + } + } + this.create = function () { + //console.log("ZLibFake: Creating new archive..."); + + this.files = []; + this.data = {}; + return true; + } + this.save = function () { + //console.log("ZLibFake: Saving archive..."); + + return this.files.map(path => ({ + path: path, + data: this.data[path] + })); + } + this.getFile = function (path) { + //console.log(`ZLibFake: Getting file: ${path}`); + + const file = this.data[path] || null; + return file ? file : null; + } + this.addFile = function (path, data) { + //console.log(`ZLibFake: Add file: ${path}`); + + if (this.files.indexOf(path) === -1) { + this.files.push(path); + } + this.data[path] = data; + return true; + } + this.removeFile = function (path) { + //console.log(`ZLibFake: Removing file: ${path}`); + + const index = this.files.indexOf(path); + if (index > -1) { + this.files.splice(index, 1); + delete this.data[path]; + return true; + } + return false; + } + this.close = function() { + //console.log("ZLibFake: Closing archive..."); + + this.files = []; + this.data = {}; + } + this.getImageBlob = function (path) { + // console.log(`ZLibFake: Getting image blob: ${path}`); + + // return new Blob(); + } + this.getPaths = function () { + console.log("ZLibFake: Getting all file paths..."); + + return this.files; + } + } + + function MockZLib () { + this.engine = new MockZLibEngine(); + this.files = []; + + this.open = function (buf) { + this.files = this.engine.open(buf); + return this.files.length > 0; + } + this.create = function () { + return this.engine.create(); + } + this.save = function () { + return this.engine.save(); + } + this.getFile = function (path) { + return this.engine.getFile(path); + } + this.addFile = function (path, data) { + this.files.push(path); + return this.engine.addFile(path, data); + } + this.removeFile = function (path) { + const index = this.files.indexOf(path); + if (index > -1) { + this.files.splice(index, 1); // Удаляем имя файла + } + + return this.engine.removeFile(path); + } + this.close = function () { + return this.engine.close(); + } + this.getImageBlob = function (path) { + return this.engine.getImageBlob(path); + } + this.getPaths = function () { + return this.engine.getPaths(); + } + } + + AscCommon.ZLib = MockZLib; + let logicDocument = AscTest.CreateLogicDocument(); + let oXMLManager = logicDocument.getCustomXmlManager(); + const oCustomXMLData = { + 'date': "2000-01-01", + 'checkboxTrue': true, + 'checkboxFalse': false, + 'checkbox0': 0, + 'checkbox1': 1, + 'checkboxMess': "hello", + 'linearXML': '<?xml version="1.0" standalone="yes"?><?mso-application progid="Word.Document"?><pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"><pkg:part pkg:name="/_rels/.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="512"><pkg:xmlData><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships></pkg:xmlData></pkg:part><pkg:part pkg:name="/word/document.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"><pkg:xmlData><w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh wp14"><w:body><w:p w:rsidR="00000000" w:rsidRDefault="001D1115"><w:r><w:rPr><w:lang w:val="en-US"/></w:rPr><w:t>12345+2</w:t></w:r></w:p><w:sectPr w:rsidR="00000000"><w:pgSz w:w="12240" w:h="15840"/><w:pgMar w:top="1134" w:right="850" w:bottom="1134" w:left="1701" w:header="720" w:footer="720" w:gutter="0"/><w:cols w:space="720"/></w:sectPr></w:body></w:document></pkg:xmlData></pkg:part><pkg:part pkg:name="/word/_rels/document.xml.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="256"><pkg:xmlData><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/></Relationships></pkg:xmlData></pkg:part><pkg:part pkg:name="/word/styles.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"><pkg:xmlData><w:styles xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh"><w:docDefaults><w:rPrDefault><w:rPr><w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorHAnsi" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi"/><w:sz w:val="22"/><w:szCs w:val="22"/><w:lang w:val="ru-RU" w:eastAsia="en-US" w:bidi="ar-SA"/></w:rPr></w:rPrDefault><w:pPrDefault><w:pPr><w:spacing w:after="160" w:line="259" w:lineRule="auto"/></w:pPr></w:pPrDefault></w:docDefaults><w:style w:type="paragraph" w:default="1" w:styleId="a"><w:name w:val="Normal"/><w:qFormat/><w:pPr><w:spacing w:after="200" w:line="276" w:lineRule="auto"/></w:pPr></w:style><w:style w:type="character" w:default="1" w:styleId="a0"><w:name w:val="Default Paragraph Font"/><w:uiPriority w:val="1"/><w:semiHidden/><w:unhideWhenUsed/></w:style><w:style w:type="table" w:default="1" w:styleId="a1"><w:name w:val="Normal Table"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/><w:tblPr><w:tblInd w:w="0" w:type="dxa"/><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPr></w:style><w:style w:type="numbering" w:default="1" w:styleId="a2"><w:name w:val="No List"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/></w:style></w:styles></pkg:xmlData></pkg:part></pkg:package>', + 'onePicture' : '/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAEsASwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9/KKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo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', + 'twoPicture' : '/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAEsASwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9/KKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo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y3t/W79T6m/4Ix/8Em/FP/BWn9q+z8J2K3mmeBNAaK+8Za/EoA0uyLHEUbMCv2mba6RKQeQzkFY3r+xb4IfBPwr+zf8ACTw/4F8E6LZ+HvCnhezSw0zT7VcR28S+55ZiSWZ2JZmZmYkkk/mX/wAE2v8Agpz/AME6f+CY37LGifDHwN8ctBkW1H2rWNWk0LU1utev2UCW6mxbHlsAKmSERUQEhcn3z/iJJ/Yj/wCi9aF/4J9U/wDkau6vVioqjS+Fat9339Fry36Xdk20cNGnKUvbVN3suy009Xa7+7W139xUV8O/8RJP7Ef/AEXrQv8AwT6p/wDI1H/EST+xH/0XrQv/AAT6p/8AI1ch1H3FRXw7/wARJP7Ef/RetC/8E+qf/I1H/EST+xH/ANF60L/wT6p/8jUAfcVFfDv/ABEk/sR/9F60L/wT6p/8jUf8RJP7Ef8A0XrQv/BPqn/yNQB9xUV8O/8AEST+xH/0XrQv/BPqn/yNX2J8LfidoXxq+GugeMPC+oJq3hvxRp8Gq6XepG8a3drPGskUgVwGAZGU4YA88gVXK7c1tP6/yJ5lfl6m9RRRUlBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFfx8/8ABzn/AMpvPjZ/120v/wBNVnX9g1fHv7Tv/BA/9k39sn43638R/iR8KP8AhJPGfiIxNqOo/wDCT6zZ/aDFEkKfure7jiXEcaD5UGcZOSSa550ZOvGotkmvvt/kdFOso0pwe8rfgz+MWiv6/f8AiFx/YT/6Ib/5efiD/wCTqP8AiFx/YT/6Ib/5efiD/wCTq6DnP5AqK/r9/wCIXH9hP/ohv/l5+IP/AJOo/wCIXH9hP/ohv/l5+IP/AJOoA/kCor+v3/iFx/YT/wCiG/8Al5+IP/k6j/iFx/YT/wCiG/8Al5+IP/k6gD+QKiv6/f8AiFx/YT/6Ib/5efiD/wCTqP8AiFx/YT/6Ib/5efiD/wCTqAP5AqK/r9/4hcf2E/8Aohv/AJefiD/5Oo/4hcf2E/8Aohv/AJefiD/5OoA/kY8AeC774k+O9F8O6XD9o1PX7+DTbSLOPMmmkWNFz7swFf3kfCzwLbfC/wCGPhzwzZqqWfh3S7bTIFAwFjhiWNR+Sivjv4Y/8G3P7Fvwc+JHh/xd4c+C66f4g8L6jb6tply3izXLhbe5gkWWJzHJetG+11U7XVlOMEEZFfcVdPto/V1SW/M2/uSj915ff93P7Juv7V7JWXzd3+UbfMKKKK5joCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA/9k=', + } + const oCustomXMLs = { + "withoutContent" : "\n\n\n\"", + "date" : "\n\n" + oCustomXMLData.date + "\n\"", + 'checkboxTrue': "\n\n" + oCustomXMLData.checkboxTrue + "\n\"", + 'checkboxFalse': "\n\n" + oCustomXMLData.checkboxFalse + "\n\"", + 'checkbox0': "\n\n" + oCustomXMLData.checkbox0 + "\n\"", + 'checkbox1': "\n\n" + oCustomXMLData.checkbox1 + "\n\"", + 'checkboxMess': "\n\n" + oCustomXMLData.checkboxMess + "\n\"", + 'picture': "\n\n" + oCustomXMLData.onePicture + "\n\"", + 'notValidData': oCustomXMLData.onePicture, + 'checkboxTrueAnotherXML': "\n " + oCustomXMLData.checkboxTrue + "", + } + + function CreateContentControl(isInline, nPos) + { + let para = AscTest.CreateParagraph(); + + logicDocument.AddToContent(nPos, para); + para.SetThisElementCurrent(); + return logicDocument.AddContentControl(isInline ? c_oAscSdtLevelType.Inline : c_oAscSdtLevelType.Block); + } + function CreateDataBindingForCC(contentControl, prefix, itemId, xpath, checkSum) + { + let oDataBinding = new AscWord.DataBinding( + prefix === undefined ? "xmlns:ns0='http://example.com/picture' " : prefix, + itemId === undefined ? "{694325A8-B1C9-407B-A2C2-E2DD1740AA5E}" : itemId, + xpath === undefined ? "/ns0:documentData[1]/ns0:simpleText[1]" : xpath, + checkSum === undefined ? "Gt6wYg==" : checkSum, + ); + + contentControl.Pr.DataBinding = oDataBinding; + contentControl.checkDataBinding(); + } + function CreateCustomXMLForDocument(strContent, ItemId, Uri) + { + let oXML = new AscWord.CustomXml(); + + oXML.addContentByXMLString( + strContent !== undefined + ? strContent + : oCustomXMLs.withoutContent + ); + + oXML.itemId = ItemId === undefined + ? "{694325A8-B1C9-407B-A2C2-E2DD1740AA5E}" + : ItemId; + + oXML.uri = Uri === undefined + ? ['http://example.com/picture'] + : Uri; + + oXMLManager.add(oXML); + } + function SetPictureToContentControl (oCC, strBase64) + { + oXMLManager.setContentByDataBinding(oCC.Pr.DataBinding, strBase64); + } + function MoveCursorToCC(oCC, isToStart) + { + let paragraph = oCC.GetLastParagraph(); + if (!paragraph || !(paragraph instanceof AscWord.Paragraph)) + return; + + paragraph.SetThisElementCurrent(); + + if (false === isToStart) + paragraph.MoveCursorToEndPos(); + else + paragraph.MoveCursorToStartPos(); + + return paragraph; + } + + function CreateDateCC(nPos, isInline) + { + let cc = CreateFilledContentControl(nPos, isInline); + let dateTimePr = new AscWord.CSdtDatePickerPr(); + cc.ApplyDatePickerPr(dateTimePr, true); + return cc; + } + function CreateCheckBoxCC(nPos, isInline) + { + let cc = CreateFilledContentControl(nPos, isInline) + let checkboxPr = new AscWord.CSdtCheckBoxPr(); + cc.ApplyCheckBoxPr(checkboxPr); + return cc; + } + // поле со списком + function CreateComboBox(nPos, isInline) + { + let cc = CreateFilledContentControl(nPos, isInline); + let comboBoxPr = new AscWord.CSdtComboBoxPr(); + cc.ApplyComboBoxPr(comboBoxPr, true); + return cc; + } + // раскрывающийся список + function CreateDropDown(nPos, isInline) + { + let cc = CreateFilledContentControl(nPos, isInline); + let comboBoxPr = new AscWord.CSdtComboBoxPr(); + cc.ApplyDropDownListPr(comboBoxPr, true); + return cc; + } + function CreatePicture(nPos, isInline) + { + let cc = CreateFilledContentControl(nPos, isInline); + let picturePr = new AscWord.CSdtPictureFormPr(); + cc.ApplyPicturePr(picturePr); + return cc; + } + function CreateText(nPos, isInline) + { + let cc = CreateFilledContentControl(nPos, isInline); + cc.SetContentControlText(true) + return cc; + } + + function CreateFilledContentControl(nPos, isInline) + { + return CreateContentControl(isInline, nPos) + } + function CheckContentParagraph(assert, oContentArr, arrSample) + { + for (let i = 0; i < arrSample.length; i++) + { + let oCurStr = arrSample[i]; + let oCurContent = oContentArr[i].GetText(); + assert.strictEqual(oCurStr, oCurContent, oCurContent); + } + } + + function getCheck(strContent) + { + return '\n' + + '\n' + + '\t'+ strContent +'\n' + + ''; + } + function Reset() + { + AscTest.ClearDocument(); + oXMLManager.xml = [] + } + + QUnit.testStart( function() { Reset() } ); + + QUnit.module("Block content control"); + + QUnit.test("Date and CheckBox content control's load/save from/to different CustomXML's", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.date); + CreateCustomXMLForDocument(oCustomXMLs.checkboxTrueAnotherXML, "{694325A8-B1C9-407B-A2C2-E2DD1740AA55}", ["/weather[1]"]); + + let c1 = CreateDateCC(0); + CreateDataBindingForCC(c1); + + let oDatePr = c1.GetDatePickerPr(); + let strDate = oDatePr.GetFullDate(); + let oDate = new Date(strDate).toDateString(); + let oStartDate = new Date(oCustomXMLData.date).toDateString(); + + assert.strictEqual(oDate, oStartDate, "Date loaded from CustomXml"); + + let c2 = CreateCheckBoxCC(1); + CreateDataBindingForCC(c2, '', "{694325A8-B1C9-407B-A2C2-E2DD1740AA55}", '/weather[1]', ''); + let oCHeckBoxPr = c2.GetCheckBoxPr(); + + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxTrue, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkboxTrue + "\" is true" + ); + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\t01/01/2000\n', + "Check saved CustomXML" + ); + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(1)), + "\n" + oCustomXMLData.checkboxTrue + "", + "Check saved CustomXML" + ); + }); + + QUnit.test("Date content control load/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.date); + + let c1 = CreateDateCC(0); + CreateDataBindingForCC(c1); + + let oDatePr = c1.GetDatePickerPr(); + let strDate = oDatePr.GetFullDate(); + let oDate = new Date(strDate).toDateString(); + let oStartDate = new Date(oCustomXMLData.date).toDateString(); + + assert.strictEqual(oDate, oStartDate, "Date loaded from CustomXml"); + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\t01/01/2000\n', + "Check saved CustomXML" + ); + }); + + QUnit.test("Checkbox content control load/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.checkboxTrue); + let c1 = CreateCheckBoxCC(0); + CreateDataBindingForCC(c1); + let oCHeckBoxPr = c1.GetCheckBoxPr(); + + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxTrue, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkboxTrue + "\" is true" + ); + Reset(); + + CreateCustomXMLForDocument(oCustomXMLs.checkboxFalse); + c1 = CreateCheckBoxCC(0); + CreateDataBindingForCC(c1); + oCHeckBoxPr = c1.GetCheckBoxPr(); + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxFalse, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkboxFalse + "\" is false" + ); + Reset(); + + CreateCustomXMLForDocument(oCustomXMLs.checkbox0); + c1 = CreateCheckBoxCC(0); + CreateDataBindingForCC(c1); + oCHeckBoxPr = c1.GetCheckBoxPr(); + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxFalse, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkbox0 + "\" is false" + ); + Reset(); + + CreateCustomXMLForDocument(oCustomXMLs.checkbox1); + c1 = CreateCheckBoxCC(0); + CreateDataBindingForCC(c1); + oCHeckBoxPr = c1.GetCheckBoxPr(); + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxTrue, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkbox1 + "\" is true" + ); + Reset(); + + CreateCustomXMLForDocument(oCustomXMLs.checkboxMess); + c1 = CreateCheckBoxCC(0); + CreateDataBindingForCC(c1); + oCHeckBoxPr = c1.GetCheckBoxPr(); + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxFalse, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkboxMess + "\" is false" + ); + + c1.SetCheckBoxChecked(true); + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + getCheck('true'), + "Check saved CustomXML" + ); + + c1.SetCheckBoxChecked(false); + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + getCheck('false'), + "Check saved CustomXML" + ); + }); + + QUnit.test("ComboBox content control load from/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.checkboxMess); + + let c1 = CreateComboBox(0); + CreateDataBindingForCC(c1); + + let oValue = c1.GetCurrentParagraph().GetText(); + + assert.strictEqual(oValue, "hello ", "Date loaded from CustomXml"); + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\thello\n', + "Check saved CustomXML" + ); + + let oPar = c1.GetCurrentParagraph(); + + oPar.MoveCursorToEndPos() + AscTest.AddTextToParagraph(oPar,'123') + oValue = c1.GetCurrentParagraph().GetText(); + + assert.strictEqual(oValue, "hello123 ", "Date loaded from CustomXml"); + }); + + QUnit.test("DropDown content control load from/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.checkboxMess); + + let c1 = CreateDropDown(0); + CreateDataBindingForCC(c1); + + let oValue = c1.GetCurrentParagraph().GetText(); + + assert.strictEqual(oValue, "hello ", "Date loaded from CustomXml"); + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\thello\n', + "Check saved CustomXML" + ); + + let oPar = c1.GetCurrentParagraph(); + + oPar.MoveCursorToEndPos() + AscTest.AddTextToParagraph(oPar,'123') + oValue = c1.GetCurrentParagraph().GetText(); + + assert.strictEqual(oValue, "hello123 ", "Date saved from CustomXml"); + }); + + QUnit.test("Picture content control load from/save CustomXML", async function (assert) + { + let editor = logicDocument.GetApi(); + editor.ImageLoader = AscCommon.g_image_loader; + + CreateCustomXMLForDocument(oCustomXMLs.picture); + let c1 = CreatePicture(0); + CreateDataBindingForCC(c1); + + let strCheckDefaultPicture = '\n\n\t/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAEsASwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9/KKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo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\n' + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + strCheckDefaultPicture, + "Check load CustomXML" + ); + + SetPictureToContentControl(c1, oCustomXMLData.twoPicture); + + let strCheckAfterPicture = '\n\n\t/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAEsASwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9/KKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo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y3t/W79T6m/4Ix/8Em/FP/BWn9q+z8J2K3mmeBNAaK+8Za/EoA0uyLHEUbMCv2mba6RKQeQzkFY3r+xb4IfBPwr+zf8ACTw/4F8E6LZ+HvCnhezSw0zT7VcR28S+55ZiSWZ2JZmZmYkkk/mX/wAE2v8Agpz/AME6f+CY37LGifDHwN8ctBkW1H2rWNWk0LU1utev2UCW6mxbHlsAKmSERUQEhcn3z/iJJ/Yj/wCi9aF/4J9U/wDkau6vVioqjS+Fat9339Fry36Xdk20cNGnKUvbVN3suy009Xa7+7W139xUV8O/8RJP7Ef/AEXrQv8AwT6p/wDI1H/EST+xH/0XrQv/AAT6p/8AI1ch1H3FRXw7/wARJP7Ef/RetC/8E+qf/I1H/EST+xH/ANF60L/wT6p/8jUAfcVFfDv/ABEk/sR/9F60L/wT6p/8jUf8RJP7Ef8A0XrQv/BPqn/yNQB9xUV8O/8AEST+xH/0XrQv/BPqn/yNX2J8LfidoXxq+GugeMPC+oJq3hvxRp8Gq6XepG8a3drPGskUgVwGAZGU4YA88gVXK7c1tP6/yJ5lfl6m9RRRUlBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFfx8/8ABzn/AMpvPjZ/120v/wBNVnX9g1fHv7Tv/BA/9k39sn43638R/iR8KP8AhJPGfiIxNqOo/wDCT6zZ/aDFEkKfure7jiXEcaD5UGcZOSSa550ZOvGotkmvvt/kdFOso0pwe8rfgz+MWiv6/f8AiFx/YT/6Ib/5efiD/wCTqP8AiFx/YT/6Ib/5efiD/wCTq6DnP5AqK/r9/wCIXH9hP/ohv/l5+IP/AJOo/wCIXH9hP/ohv/l5+IP/AJOoA/kCor+v3/iFx/YT/wCiG/8Al5+IP/k6j/iFx/YT/wCiG/8Al5+IP/k6gD+QKiv6/f8AiFx/YT/6Ib/5efiD/wCTqP8AiFx/YT/6Ib/5efiD/wCTqAP5AqK/r9/4hcf2E/8Aohv/AJefiD/5Oo/4hcf2E/8Aohv/AJefiD/5OoA/kY8AeC774k+O9F8O6XD9o1PX7+DTbSLOPMmmkWNFz7swFf3kfCzwLbfC/wCGPhzwzZqqWfh3S7bTIFAwFjhiWNR+Sivjv4Y/8G3P7Fvwc+JHh/xd4c+C66f4g8L6jb6tply3izXLhbe5gkWWJzHJetG+11U7XVlOMEEZFfcVdPto/V1SW/M2/uSj915ff93P7Juv7V7JWXzd3+UbfMKKKK5joCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA/9k=\n' + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + strCheckAfterPicture, + "Check saved CustomXML" + ); + }); + + QUnit.test("Simple text content control load from/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.checkboxMess); + let c1 = CreateText(0); + CreateDataBindingForCC(c1); + + let p = c1.GetFirstParagraph(); + let str = p.GetText(); + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\thello\n', + "Check load CustomXML" + ); + }); + + QUnit.test("Rich text content control load from/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(getCheck(oCustomXMLData.linearXML)); + + let c1 = CreateFilledContentControl(0); + CreateDataBindingForCC(c1); + + let p = c1.GetFirstParagraph(); + let strContentInParagraph = p.GetText(); + assert.strictEqual( + strContentInParagraph, + '12345+2 ', + "Content in Paragraph after load CustomXML" + ); + + let p1 = MoveCursorToCC(c1); + AscTest.AddTextToParagraph(p1, "990") + let str = oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)); + + assert.strictEqual( + str, + ` + +\t<?xml version="1.0" standalone="yes"?><?mso-application progid="Word.Document"?><pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage"><pkg:part pkg:name="/_rels/.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="512"><pkg:xmlData><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships></pkg:xmlData></pkg:part><pkg:part pkg:name="/word/document.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"><pkg:xmlData><w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh wp14"><w:body><w:p w:rsidR="00000000" w:rsidRDefault="001D1115"><w:r><w:rPr><w:lang w:val="en-US"/></w:rPr><w:t>12345+2</w:t></w:r></w:p><w:sectPr w:rsidR="00000000"><w:pgSz w:w="12240" w:h="15840"/><w:pgMar w:top="1134" w:right="850" w:bottom="1134" w:left="1701" w:header="720" w:footer="720" w:gutter="0"/><w:cols w:space="720"/></w:sectPr></w:body></w:document></pkg:xmlData></pkg:part><pkg:part pkg:name="/word/_rels/document.xml.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="256"><pkg:xmlData><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/></Relationships></pkg:xmlData></pkg:part><pkg:part pkg:name="/word/styles.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"><pkg:xmlData><w:styles xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh"><w:docDefaults><w:rPrDefault><w:rPr><w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorHAnsi" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi"/><w:sz w:val="22"/><w:szCs w:val="22"/><w:lang w:val="ru-RU" w:eastAsia="en-US" w:bidi="ar-SA"/></w:rPr></w:rPrDefault><w:pPrDefault><w:pPr><w:spacing w:after="160" w:line="259" w:lineRule="auto"/></w:pPr></w:pPrDefault></w:docDefaults><w:style w:type="paragraph" w:default="1" w:styleId="a"><w:name w:val="Normal"/><w:qFormat/><w:pPr><w:spacing w:after="200" w:line="276" w:lineRule="auto"/></w:pPr></w:style><w:style w:type="character" w:default="1" w:styleId="a0"><w:name w:val="Default Paragraph Font"/><w:uiPriority w:val="1"/><w:semiHidden/><w:unhideWhenUsed/></w:style><w:style w:type="table" w:default="1" w:styleId="a1"><w:name w:val="Normal Table"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/><w:tblPr><w:tblInd w:w="0" w:type="dxa"/><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPr></w:style><w:style w:type="numbering" w:default="1" w:styleId="a2"><w:name w:val="No List"/><w:uiPriority w:val="99"/><w:semiHidden/><w:unhideWhenUsed/></w:style></w:styles></pkg:xmlData></pkg:part></pkg:package> +`, + "Check load CustomXML" + ); + }); + + QUnit.module("Inline content control"); + + QUnit.test("Date and CheckBox inline content control's load/save from/to different CustomXML's", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.date); + CreateCustomXMLForDocument(oCustomXMLs.checkboxTrueAnotherXML, "{694325A8-B1C9-407B-A2C2-E2DD1740AA55}", ["/weather[1]"]); + + let c1 = CreateDateCC(0, true); + CreateDataBindingForCC(c1); + + let oDatePr = c1.GetDatePickerPr(); + let strDate = oDatePr.GetFullDate(); + let oDate = new Date(strDate).toDateString(); + let oStartDate = new Date(oCustomXMLData.date).toDateString(); + + assert.strictEqual(oDate, oStartDate, "Date loaded from CustomXml"); + + let c2 = CreateCheckBoxCC(1, true); + CreateDataBindingForCC(c2, '', "{694325A8-B1C9-407B-A2C2-E2DD1740AA55}", '/weather[1]', ''); + let oCHeckBoxPr = c2.GetCheckBoxPr(); + + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxTrue, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkboxTrue + "\" is true" + ); + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\t01/01/2000\n', + "Check saved CustomXML" + ); + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(1)), + "\n" + oCustomXMLData.checkboxTrue + "", + "Check saved CustomXML" + ); + }); + + QUnit.test("Date content control load/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.date); + + let c1 = CreateDateCC(0, true); + CreateDataBindingForCC(c1); + + let oDatePr = c1.GetDatePickerPr(); + let strDate = oDatePr.GetFullDate(); + let oDate = new Date(strDate).toDateString(); + let oStartDate = new Date(oCustomXMLData.date).toDateString(); + + assert.strictEqual(oDate, oStartDate, "Date loaded from CustomXml"); + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\t01/01/2000\n', + "Check saved CustomXML" + ); + }); + + QUnit.test("Checkbox content control load/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.checkboxTrue); + let c1 = CreateCheckBoxCC(0, true); + CreateDataBindingForCC(c1); + let oCHeckBoxPr = c1.GetCheckBoxPr(); + + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxTrue, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkboxTrue + "\" is true" + ); + Reset(); + + CreateCustomXMLForDocument(oCustomXMLs.checkboxFalse); + c1 = CreateCheckBoxCC(0, true); + CreateDataBindingForCC(c1); + oCHeckBoxPr = c1.GetCheckBoxPr(); + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxFalse, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkboxFalse + "\" is false" + ); + Reset(); + + CreateCustomXMLForDocument(oCustomXMLs.checkbox0); + c1 = CreateCheckBoxCC(0, true); + CreateDataBindingForCC(c1); + oCHeckBoxPr = c1.GetCheckBoxPr(); + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxFalse, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkbox0 + "\" is false" + ); + Reset(); + + CreateCustomXMLForDocument(oCustomXMLs.checkbox1); + c1 = CreateCheckBoxCC(0, true); + CreateDataBindingForCC(c1); + oCHeckBoxPr = c1.GetCheckBoxPr(); + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxTrue, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkbox1 + "\" is true" + ); + Reset(); + + CreateCustomXMLForDocument(oCustomXMLs.checkboxMess); + c1 = CreateCheckBoxCC(0, true); + CreateDataBindingForCC(c1); + oCHeckBoxPr = c1.GetCheckBoxPr(); + assert.strictEqual( + oCHeckBoxPr.Checked, + oCustomXMLData.checkboxFalse, + "Check load checkbox content from CustomXML with text \"" + oCustomXMLData.checkboxMess + "\" is false" + ); + + c1.SetCheckBoxChecked(true); + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + getCheck('true'), + "Check saved CustomXML" + ); + + c1.SetCheckBoxChecked(false); + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + getCheck('false'), + "Check saved CustomXML" + ); + }); + + QUnit.test("ComboBox content control load from/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.checkboxMess); + + let c1 = CreateComboBox(0, true); + + CreateDataBindingForCC(c1); + + let oValue = c1.GetInnerText(); + + assert.strictEqual(oValue, "hello", "Date loaded from CustomXml"); + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\thello\n', + "Check saved CustomXML" + ); + + c1.SelectContentControl(); + AscTest.EnterText('123') + oValue = c1.GetInnerText(); + + assert.strictEqual(oValue, "123", "Date loaded from CustomXml"); + }); + + QUnit.test("DropDown content control load from/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.checkboxMess); + + let c1 = CreateDropDown(0, true); + CreateDataBindingForCC(c1); + + c1.Pr.DropDown.AddItem('123', '123', 1); + c1.Pr.DropDown.AddItem('456', '456', 2); + + let oValue = c1.GetInnerText(); + + assert.strictEqual(oValue, "hello", "Date loaded from CustomXml"); + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\thello\n', + "Check saved CustomXML" + ); + + c1.SelectContentControl(); + c1.SelectListItem('123') + oValue = c1.GetInnerText(); + + assert.strictEqual(oValue, "123", "Date saved from CustomXml"); + }); + + QUnit.test("Picture content control load from/save CustomXML", async function (assert) + { + let editor = logicDocument.GetApi(); + editor.ImageLoader = AscCommon.g_image_loader; + + CreateCustomXMLForDocument(oCustomXMLs.picture); + let c1 = CreatePicture(0, true); + CreateDataBindingForCC(c1); + + let strCheckDefaultPicture = '\n\n\t/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAEsASwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9/KKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo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\n' + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + strCheckDefaultPicture, + "Check load CustomXML" + ); + + SetPictureToContentControl(c1, oCustomXMLData.twoPicture); + + let strCheckAfterPicture = '\n\n\t/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAEsASwDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9/KKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo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y3t/W79T6m/4Ix/8Em/FP/BWn9q+z8J2K3mmeBNAaK+8Za/EoA0uyLHEUbMCv2mba6RKQeQzkFY3r+xb4IfBPwr+zf8ACTw/4F8E6LZ+HvCnhezSw0zT7VcR28S+55ZiSWZ2JZmZmYkkk/mX/wAE2v8Agpz/AME6f+CY37LGifDHwN8ctBkW1H2rWNWk0LU1utev2UCW6mxbHlsAKmSERUQEhcn3z/iJJ/Yj/wCi9aF/4J9U/wDkau6vVioqjS+Fat9339Fry36Xdk20cNGnKUvbVN3suy009Xa7+7W139xUV8O/8RJP7Ef/AEXrQv8AwT6p/wDI1H/EST+xH/0XrQv/AAT6p/8AI1ch1H3FRXw7/wARJP7Ef/RetC/8E+qf/I1H/EST+xH/ANF60L/wT6p/8jUAfcVFfDv/ABEk/sR/9F60L/wT6p/8jUf8RJP7Ef8A0XrQv/BPqn/yNQB9xUV8O/8AEST+xH/0XrQv/BPqn/yNX2J8LfidoXxq+GugeMPC+oJq3hvxRp8Gq6XepG8a3drPGskUgVwGAZGU4YA88gVXK7c1tP6/yJ5lfl6m9RRRUlBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFfx8/8ABzn/AMpvPjZ/120v/wBNVnX9g1fHv7Tv/BA/9k39sn43638R/iR8KP8AhJPGfiIxNqOo/wDCT6zZ/aDFEkKfure7jiXEcaD5UGcZOSSa550ZOvGotkmvvt/kdFOso0pwe8rfgz+MWiv6/f8AiFx/YT/6Ib/5efiD/wCTqP8AiFx/YT/6Ib/5efiD/wCTq6DnP5AqK/r9/wCIXH9hP/ohv/l5+IP/AJOo/wCIXH9hP/ohv/l5+IP/AJOoA/kCor+v3/iFx/YT/wCiG/8Al5+IP/k6j/iFx/YT/wCiG/8Al5+IP/k6gD+QKiv6/f8AiFx/YT/6Ib/5efiD/wCTqP8AiFx/YT/6Ib/5efiD/wCTqAP5AqK/r9/4hcf2E/8Aohv/AJefiD/5Oo/4hcf2E/8Aohv/AJefiD/5OoA/kY8AeC774k+O9F8O6XD9o1PX7+DTbSLOPMmmkWNFz7swFf3kfCzwLbfC/wCGPhzwzZqqWfh3S7bTIFAwFjhiWNR+Sivjv4Y/8G3P7Fvwc+JHh/xd4c+C66f4g8L6jb6tply3izXLhbe5gkWWJzHJetG+11U7XVlOMEEZFfcVdPto/V1SW/M2/uSj915ff93P7Juv7V7JWXzd3+UbfMKKKK5joCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA/9k=\n' + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + strCheckAfterPicture, + "Check saved CustomXML" + ); + }); + + QUnit.test("Simple text content control load from/save CustomXML", async function (assert) + { + CreateCustomXMLForDocument(oCustomXMLs.checkboxMess); + let c1 = CreateText(0, true); + CreateDataBindingForCC(c1); + + + + assert.strictEqual( + oXMLManager.getCustomXMLString(oXMLManager.getCustomXml(0)), + '\n\n\thello\n', + "Check load CustomXML" + ); + }); + +}); diff --git a/word/Editor/Document.js b/word/Editor/Document.js index 39cc89ccea..e064537c58 100644 --- a/word/Editor/Document.js +++ b/word/Editor/Document.js @@ -411,7 +411,7 @@ function CDocumentRecalculateState() this.UseRecursion = true; this.Continue = false; // параметр сигнализирующий, о том что нужно продолжить пересчет (для нерекурсивного метода) - + this.ScrollToTarget = true; } @@ -1865,9 +1865,9 @@ function CDocument(DrawingDocument, isMainLogicDocument) this.Content[0] = new AscWord.Paragraph(this); this.Content[0].Set_DocumentNext(null); this.Content[0].Set_DocumentPrev(null); - + this.Background = new AscWord.DocumentBackground(); - + this.CurPos = { X : 0, @@ -2175,6 +2175,8 @@ function CDocument(DrawingDocument, isMainLogicDocument) this.AutoCorrectSettings = new AscCommon.CAutoCorrectSettings(); + this.customXml = new AscWord.CustomXmlManager(this); + // Контролируем изменения интерфейса this.ChangedStyles = []; // Объект с Id стилями, которые были изменены/удалены/добавлены this.TurnOffPanelStyles = 0; // == 0 - можно обновлять панельку со стилями, != 0 - нельзя обновлять @@ -2309,7 +2311,7 @@ CDocument.prototype.sendEvent = function() { if (!this.MainDocument || !this.Api) return; - + this.Api.sendEvent.apply(this.Api, arguments); }; CDocument.prototype.UpdateDefaultsDependingOnCompatibility = function() @@ -2606,7 +2608,7 @@ CDocument.prototype.StartAction = function(nDescription, oSelectionState, flags) this.Action.Redraw.Start = undefined; this.Action.Redraw.End = undefined; this.Action.Additional = {}; - + if (undefined !== flags && null !== flags) { this.Action.Recalculate = !!(flags & ACTION_FLAGS.RECALCULATE); @@ -2780,11 +2782,11 @@ CDocument.prototype.FinalizeAction = function(checkEmptyAction) this.Action.Depth--; return true; } - + this.private_CheckAdditionalOnFinalize(); this.private_CheckEmptyPointsInAction(checkEmptyAction); this.private_CheckActionLock(); - + let actionCompleted = true; if (this.Action.CancelAction) { @@ -2793,13 +2795,13 @@ CDocument.prototype.FinalizeAction = function(checkEmptyAction) { arrChanges = arrChanges.concat(this.History.Undo()); } - + if (arrChanges.length) this.RecalculateByChanges(arrChanges); - + actionCompleted = false; } - + if (this.Action.PointsCount) { if (this.Action.Recalculate) @@ -2891,7 +2893,7 @@ CDocument.prototype.CheckActionLock = function() { if (!this.IsActionStarted()) return; - + this.Action.CheckLock = true; }; CDocument.prototype.StartUndoRedoAction = function() @@ -2958,12 +2960,12 @@ CDocument.prototype.private_CheckEmptyPointsInAction = function(checkEmptyAction { if (false === checkEmptyAction) return; - + for (let pointIndex = 0, pointCount = this.Action.PointsCount; pointIndex < pointCount; ++pointIndex) { if (!this.History.Is_LastPointEmpty()) break; - + this.History.Remove_LastPoint(); --this.Action.PointsCount; } @@ -2972,18 +2974,18 @@ CDocument.prototype.private_CheckActionLock = function() { if (!this.Action.CheckLock || !this.Action.PointsCount || this.Action.CancelAction) return; - + if (!this.StartSelectionLockCheck()) { this.Action.CancelAction = true; return; } - + this.History.checkLock(this.Action.PointsCount); - + if (this.EndSelectionLockCheck()) this.Action.CancelAction = true; - + // TODO: Если сервер нам запрещает делать действие, то мы делаем Undo из совместки. Но там делается отмена // только для одной точки, а в действии их может быть несколько. Надо доработать этот момент (но в текущий // момент данная проверка не вызывается для случаев, где в действии более одной точки) @@ -3299,7 +3301,7 @@ CDocument.prototype.private_Recalculate = function(_RecalcData, isForceStrictRec var RecalcData = History.Get_RecalcData(_RecalcData); History.Reset_RecalcIndex(); - + if (RecalcData.ResetCache) this.Reset_RecalculateCache(); @@ -4572,7 +4574,7 @@ CDocument.prototype.Recalculate_PageColumn = function() else this.CurPage = PageIndex; // TODO: переделать } - + if (docpostype_Content === this.GetDocPosType() && ((true !== this.Selection.Use && Index === this.CurPos.ContentPos + 1) || (true === this.Selection.Use && Index === (Math.max(this.Selection.EndPos, this.Selection.StartPos) + 1)))) this.UpdateCursorOnRecalculate(); } @@ -5264,7 +5266,7 @@ CDocument.prototype.private_RecalculateFlowParagraph = function(RecalcIn var TempElement = this.Content[TempIndex]; TempElement.Reset(TempElement.X, TempElement.Y, TempElement.XLimit, TempElement.YLimit, PageIndex, ColumnIndex, ColumnsCount); } - + Index += FlowCount - 1; RecalcResult = recalcresult_NextElement; } @@ -5512,7 +5514,7 @@ CDocument.prototype.CheckViewPosition = function() } this.FullRecalc.ScrollToTarget = false; - + let anchorPos = this.ViewPosition.AnchorPos; let alignTop = this.ViewPosition.AlignTop; let distance = this.ViewPosition.Distance; @@ -5644,9 +5646,9 @@ CDocument.prototype.Draw = function(nPageInd // Определим секцию var Page_StartPos = this.Pages[nPageIndex].Pos; var SectPr = this.SectionsInfo.Get_SectPr(Page_StartPos).SectPr; - + this.Background.draw(pGraphics, SectPr, this.GetTheme(), this.GetColorMap()); - + // Рисуем границы вокруг страницы (если границы надо рисовать под текстом) if (section_borders_ZOrderBack === SectPr.Get_Borders_ZOrder()) this.DrawPageBorders(pGraphics, SectPr, nPageIndex); @@ -5661,7 +5663,7 @@ CDocument.prototype.Draw = function(nPageInd else if (!this.IsViewMode()) pGraphics.End_GlobalAlpha(); } - + this.DrawingObjects.drawBehindDoc(nPageIndex, pGraphics); this.Footnotes.Draw(nPageIndex, pGraphics); @@ -5936,7 +5938,7 @@ CDocument.prototype.setBackgroundColor = function(color, unifill) { let oldValue = this.Background.copy(); let newValue = new AscWord.DocumentBackground(color, unifill, null); - + AscCommon.History.Add(new CChangesDocumentPageColor(this, oldValue, newValue)); this.Background = newValue; }; @@ -6433,7 +6435,7 @@ CDocument.prototype.AddToParagraph = function(oParaItem, bRecalculate) this.RemoveSelectedNumberingOnTextAdd(); this.Controller.AddToParagraph(oParaItem, bRecalculate); - + if (para_TextPr === oParaItem.Type) this.setMergeFormatComplexFieldOnApplyTextPr(); }; @@ -6473,7 +6475,7 @@ CDocument.prototype.RemoveSelectedNumberingOnTextAdd = function() CDocument.prototype.setMergeFormatComplexFieldOnApplyTextPr = function() { let complexField = this.GetCurrentComplexField(); - + // Word doesn't add MERGEFORMAT for all field types (for example PAGE) // So we add it to some specific types if (!complexField @@ -6483,7 +6485,7 @@ CDocument.prototype.setMergeFormatComplexFieldOnApplyTextPr = function() || !complexField.CheckType(AscWord.fieldtype_REF) || !this.Action.Start) return; - + // We don't check selection lock, because this method should be called when other action was started let state = this.SaveDocumentState(); this.StartAction(AscDFH.historydescription_Document_ComplexField_MergeFormat); @@ -8328,7 +8330,7 @@ CDocument.prototype.OnEndTextDrag = function(NearPos, bCopy) arrParagraphs[0].AddTrackMoveMark(true, true, this.TrackMoveId); } } - + if (!bCopy) { // TODO: Проверить, зачем тут посылается isOnAddText=true. Когда выделены ячейки таблицы точно нужно посылать false @@ -8812,7 +8814,7 @@ CDocument.prototype.OnKeyDown = function(e) { if (this.Api.isTargetHandMode() && !this.IsInFormField()) this.Api.asc_setViewerTargetType("select"); - + this.SelectAll(); bUpdateSelection = false; bRetValue = keydownresult_PreventAll; @@ -10162,7 +10164,7 @@ CDocument.prototype.CorrectEnterText = function(oldValue, newValue) let state = this.SaveDocumentState(false); let startPos = paragraph.getCurrentPos(); let endPos = startPos; - + let paraSearchPos = new CParagraphSearchPos(); let maxShifts = oldCodePoints.length; @@ -10172,12 +10174,12 @@ CDocument.prototype.CorrectEnterText = function(oldValue, newValue) { paraSearchPos.Reset(); paragraph.Get_LeftPos(paraSearchPos, endPos); - + if (!paraSearchPos.IsFound()) break; - + endPos = paraSearchPos.GetPos().Copy(); - + paragraph.SetSelectionContentPos(startPos, endPos, false); selectedText = paragraph.GetSelectedText(true); @@ -10192,7 +10194,7 @@ CDocument.prototype.CorrectEnterText = function(oldValue, newValue) this.LoadDocumentState(state); return false; } - + this.StartAction(AscDFH.historydescription_Document_CorrectEnterText); @@ -11523,16 +11525,16 @@ CDocument.prototype.SetSectionPageNumFormat = function(format) let curHdrFtr = this.HdrFtr.CurHdrFtr; if (!curHdrFtr) return; - + let curPage = curHdrFtr.RecalcInfo.CurPage; if (-1 === curPage) return; - + let startIndex = this.Pages[curPage].Pos; let sectPr = this.SectionsInfo.Get_SectPr(startIndex).SectPr; - + sectPr.SetPageNumFormat(format); - + this.Recalculate(); this.UpdateSelection(); this.UpdateInterface(); @@ -11545,7 +11547,7 @@ CDocument.prototype.isHeaderEditing = function() { if (docpostype_HdrFtr !== this.GetDocPosType()) return false; - + let hdrFtr = this.HdrFtr.Get_CurHdrFtr(); return hdrFtr && AscCommon.hdrftr_Header === hdrFtr.Type; }; @@ -11553,7 +11555,7 @@ CDocument.prototype.isFooterEditing = function() { if (docpostype_HdrFtr !== this.GetDocPosType()) return false; - + let hdrFtr = this.HdrFtr.Get_CurHdrFtr(); return hdrFtr && AscCommon.hdrftr_Footer === hdrFtr.Type; }; @@ -12434,7 +12436,7 @@ CDocument.prototype.Document_UpdateCopyCutState = function() // Во время работы селекта не обновляем состояние if (true === this.Selection.Start) return; - + let canCopy = this.Can_CopyCut(); let canCut = canCopy; if (this.IsFillingFormMode() && canCut) @@ -12503,7 +12505,7 @@ CDocument.prototype.GetWatermark = function() let header = this.Get_SectionHdrFtr(this.CurPage, pageInfo.bFirst, pageInfo.bFirst.bEven).Header; if (header) return header.FindWatermark(); - + return null; } else @@ -12513,21 +12515,21 @@ CDocument.prototype.GetWatermark = function() let header = sectPr.Get_Header_Default(); if (header) return header.FindWatermark(); - + return null; } }; CDocument.prototype.GetWatermarkProps = function() { let watermark = this.GetWatermark(); - + let props = new Asc.CAscWatermarkProperties(); props.put_Api(this.Api); if (watermark) props = watermark.GetWatermarkProps(); else props.put_Type(Asc.c_oAscWatermarkType.None); - + return props; }; CDocument.prototype.GetHeaderForWatermark = function() @@ -12538,7 +12540,7 @@ CDocument.prototype.GetHeaderForWatermark = function() let header = this.Get_SectionHdrFtr(this.CurPage, pageInfo.bFirst, pageInfo.bFirst.bEven).Header; if (header) return header; - + return this.Create_SectionHdrFtr(hdrftr_Header, this.CurPage); } else @@ -12548,7 +12550,7 @@ CDocument.prototype.GetHeaderForWatermark = function() let header = sectPr.Get_Header_Default(); if (header) return header; - + header = new CHeaderFooter(this.HdrFtr, this, this.DrawingDocument, hdrftr_Header); sectPr.Set_Header_Default(header); return header; @@ -12577,10 +12579,10 @@ CDocument.prototype.SetWatermarkPropsAction = function(oProps) this.RemoveSelection(true); watermark.Remove_FromDocument(false); } - + if (Asc.c_oAscWatermarkType.None === oProps.get_Type()) return; - + let oWatermark = this.DrawingObjects.createWatermark(oProps); if (oWatermark) { @@ -13746,7 +13748,7 @@ CDocument.prototype.HideCurrentComment = function() { if (!this.Comments.Is_Use() || !this.Comments.Get_CurrentId()) return; - + this.SelectComment(null, false); this.Api.sync_HideComment(); }; @@ -14443,12 +14445,12 @@ CDocument.prototype.UpdateCursorOnRecalculate = function() let isLockScroll = false; if ((this.FullRecalc.Id && !this.FullRecalc.ScrollToTarget) || this.ViewPosition) isLockScroll = true; - + if (isLockScroll) this.Api.asc_LockScrollToTarget(true); - + this.private_UpdateCursorXY(true, true); - + if (isLockScroll) this.Api.asc_LockScrollToTarget(false); }; @@ -16097,7 +16099,7 @@ CDocument.prototype.private_GetElementPageIndexByXY = function(ElementPos, X, Y, StartColumn = 0; EndColumn = Math.min(ElementPagesCount - ElementStartColumn + (PageIndex - ElementStartPage) * ColumnsCount, ColumnsCount - 1); } - + if (!PageSection.Columns[EndColumn]) return 0; @@ -16644,12 +16646,12 @@ CDocument.prototype.SetDocumentReadMode = function(nW, nH, nScale) { oRun.Recalc_CompiledPr(true); }); - + this.GetAllParagraphs().forEach(function(paragraph) { paragraph.RecalcCompiledPr(); }); - + this.GetAllTables().forEach(function(table) { table.Recalc_CompiledPr(); @@ -16665,12 +16667,12 @@ CDocument.prototype.SetDocumentPrintMode = function() { oRun.Recalc_CompiledPr(true); }); - + this.GetAllParagraphs().forEach(function(paragraph) { paragraph.RecalcCompiledPr(); }); - + this.GetAllTables().forEach(function(table) { table.Recalc_CompiledPr(); @@ -17331,7 +17333,7 @@ CDocument.prototype.Get_MailMergedDocument = function(_nStartIndex, _nEndIndex) LogicDocument.theme = this.theme.createDuplicate(); LogicDocument.clrSchemeMap = this.clrSchemeMap.createDuplicate(); - + LogicDocument.Background = this.Background.copy(); var FieldsManager = this.FieldsManager; @@ -18220,7 +18222,7 @@ CDocument.prototype.AddFootnote = function(sText) if (this.IsSelectionLocked(changestype_Paragraph_Content)) return null - + this.StartAction(AscDFH.historydescription_Document_AddFootnote); let footnote = this._addFootnote(sText); this.Recalculate(); @@ -18240,12 +18242,12 @@ CDocument.prototype._addFootnote = function(text) this.MoveCursorRight(false, false, false); this.RemoveSelection(); } - + if (text) this.AddToParagraph(new AscWord.CRunFootnoteReference(oFootnote, text)); else this.AddToParagraph(new AscWord.CRunFootnoteReference(oFootnote)); - + this.SetDocPosType(docpostype_Footnotes); this.Footnotes.Set_CurrentElement(true, 0, oFootnote); } @@ -18459,7 +18461,7 @@ CDocument.prototype.AddEndnote = function(sText) if (this.IsSelectionLocked(changestype_Paragraph_Content)) return null; - + this.StartAction(AscDFH.historydescription_Document_AddEndnote); let endnote = this._addEndnote(sText); this.Recalculate(); @@ -18474,18 +18476,18 @@ CDocument.prototype._addEndnote = function(text) { oEndnote = this.Endnotes.CreateEndnote(); oEndnote.AddDefaultEndnoteContent(text); - + if (true === this.IsSelectionUse()) { this.MoveCursorRight(false, false, false); this.RemoveSelection(); } - + if (text) this.AddToParagraph(new AscWord.CRunEndnoteReference(oEndnote, text)); else this.AddToParagraph(new AscWord.CRunEndnoteReference(oEndnote)); - + this.SetDocPosType(docpostype_Endnotes); this.Endnotes.Set_CurrentElement(true, 0, oEndnote); } @@ -18809,7 +18811,7 @@ CDocument.prototype.controller_AddNewParagraph = function(bRecalculate, bForceAd var ItemReviewType = Item.GetReviewType(); // Создаем новый параграф var NewParagraph = new AscWord.Paragraph(); - + let firstPara, secondPara; if (Item.IsCursorAtBegin()) { @@ -18822,7 +18824,7 @@ CDocument.prototype.controller_AddNewParagraph = function(bRecalculate, bForceAd var nContentPos = this.CurPos.ContentPos; this.AddToContent(nContentPos, NewParagraph); this.CurPos.ContentPos = nContentPos + 1; - + firstPara = NewParagraph; secondPara = Item; } @@ -18885,11 +18887,11 @@ CDocument.prototype.controller_AddNewParagraph = function(bRecalculate, bForceAd var nContentPos = this.CurPos.ContentPos + 1; this.AddToContent(nContentPos, NewParagraph); this.CurPos.ContentPos = nContentPos; - + firstPara = Item; secondPara = NewParagraph; } - + if (this.IsTrackRevisions()) { firstPara.RemovePrChange(); @@ -18919,19 +18921,19 @@ CDocument.prototype.controller_AddNewParagraph = function(bRecalculate, bForceAd { // Если мы находимся в начале первого параграфа первой ячейки, и // данная таблица - первый элемент, тогда добавляем параграф до таблицы. - + let newPos = -1; if (Item.IsCursorAtBegin(true) && (0 === this.CurPos.ContentPos || !this.Content[this.CurPos.ContentPos - 1].IsParagraph())) newPos = this.CurPos.ContentPos; else if (Item.IsCursorAtEnd() && (this.Content.length - 1 === this.CurPos.ContentPos || !this.Content[this.CurPos.ContentPos + 1].IsParagraph())) newPos = this.CurPos.ContentPos + 1; - + if (-1 !== newPos) { let newParagraph = new AscWord.Paragraph(); this.Internal_Content_Add(newPos, newParagraph); this.CurPos.ContentPos = newPos; - + if (this.IsTrackRevisions()) { newParagraph.RemovePrChange(); @@ -21712,7 +21714,7 @@ CDocument.prototype.controller_UpdateSelectionState = function() this.private_CheckCurPage(); this.RecalculateCurPos(); } - + this.private_UpdateTracks(true, false); this.DrawingDocument.TargetEnd(); @@ -22141,7 +22143,7 @@ CDocument.prototype.IsFillingOFormMode = function() { if (!this.IsFillingFormMode()) return false; - + let api = this.GetApi(); return !!(api.DocInfo && api.DocInfo.isFormatWithForms()); }; @@ -22169,7 +22171,7 @@ CDocument.prototype.IsInFormField = function(isAllowComplexForm, isCheckCurrentU if (oInlineSdt && oInlineSdt.IsContentControlEquation()) return false; - + if (isCheckCurrentUser && oInlineSdt && (!oInlineSdt.IsComplexForm() || isAllowComplexForm)) @@ -22417,7 +22419,7 @@ CDocument.prototype.RemoveContentControlWrapper = function(Id) let contentControl = this.TableId.Get_ById(Id); if (!contentControl) return; - + if (contentControl.IsForm()) contentControl.RemoveFormPr(); @@ -22708,7 +22710,7 @@ CDocument.prototype.AddFieldWithInstruction = function(instructionLine, textPr) var oParagraph = this.GetCurrentParagraph(false, false, {ReplacePlaceHolder : true}); if (!oParagraph) return null; - + return this.addFieldWithInstructionToParagraph(oParagraph, instructionLine, textPr); }; CDocument.prototype.addFieldWithInstructionToParagraph = function(paragraph, instructionLine, textPr, forceUpdate) @@ -22716,18 +22718,18 @@ CDocument.prototype.addFieldWithInstructionToParagraph = function(paragraph, ins let beginChar = new ParaFieldChar(fldchartype_Begin, this); let separateChar = new ParaFieldChar(fldchartype_Separate, this); let endChar = new ParaFieldChar(fldchartype_End, this); - + var run = new AscWord.Run(); run.AddToContent(-1, beginChar); run.AddInstrText(instructionLine); run.AddToContent(-1, separateChar); run.AddToContent(-1, endChar); paragraph.Add(run); - + beginChar.SetRun(run); separateChar.SetRun(run); endChar.SetRun(run); - + let complexField = beginChar.GetComplexField(); complexField.SetBeginChar(beginChar); complexField.SetInstructionLine(instructionLine); @@ -22740,10 +22742,10 @@ CDocument.prototype.addFieldWithInstructionToParagraph = function(paragraph, ins let pos = run.GetElementPosition(endChar); run.AddText(value, pos); } - + if (textPr) run.SetPr(textPr); - + return complexField; }; CDocument.prototype.AddDateTime = function(oPr) @@ -22823,7 +22825,7 @@ CDocument.prototype.AddRefToParagraph = function(oParagraph, nType, bHyperlink, let bookmarkName = oParagraph.AddBookmarkForRef(); if (bookmarkName) this.private_AddRefToBookmark(bookmarkName, nType, bHyperlink, bAboveBelow, sSeparator); - + this.UpdateInterface(); this.UpdateSelection(); this.FinalizeAction(); @@ -23200,7 +23202,7 @@ CDocument.prototype.GetAllFields = function(isUseSelection) this.RemoveSelection(); arrFields = this.GetCurrentComplexFields(); this.LoadDocumentState(state); - + this.Controller.GetAllFields(isUseSelection, arrFields); } else @@ -23263,7 +23265,7 @@ CDocument.prototype.AddAddinField = function(data) this.RemoveSelection(); let textPr = this.GetDirectTextPr(); - + let field = this.AddFieldWithInstruction(" ADDIN " + instruction + " ", textPr); if (field) { @@ -24769,14 +24771,14 @@ CDocument.prototype.AddCaption = function(oPr) let targetElement = this.GetCurrentTable(); if (!targetElement) targetElement = this.GetCurrentParagraph(); - + let docContent = targetElement ? targetElement.GetParent() : null; if (docContent) { let targetPos = targetElement.GetIndex(); if (!oPr.get_Before() || -1 === targetPos) ++targetPos; - + NewParagraph = new AscWord.Paragraph(); this.RemoveSelection(); docContent.AddToContent(targetPos, NewParagraph); @@ -24787,7 +24789,7 @@ CDocument.prototype.AddCaption = function(oPr) let captionStyleId = this.Styles.GetStyleIdByName("Caption", true); if (captionStyleId) NewParagraph.SetParagraphStyleById(captionStyleId); - + var NewRun; var nCurPos = 0; var oComplexField; @@ -27335,6 +27337,13 @@ CDocument.prototype.isPreventedPreDelete = function() { return this.PreventPreDelete; }; +/** + * @returns {AscWord.CustomXmlManager} + */ +CDocument.prototype.getCustomXmlManager = function() +{ + return this.customXml; +}; function CDocumentSelectionState() { diff --git a/word/Editor/Serialize2.js b/word/Editor/Serialize2.js index 85a075532e..98dee2e930 100644 --- a/word/Editor/Serialize2.js +++ b/word/Editor/Serialize2.js @@ -1130,6 +1130,8 @@ var c_oSerSdt = { TextFormPrFormatVal : 81, TextFormPrFormatSymbols : 82, + StoreItemCheckSum : 85, + ComplexFormPr : 90, ComplexFormPrType : 91, OformMaster : 92 @@ -1880,8 +1882,10 @@ function BinaryFileWriter(doc, bMailMergeDocx, bMailMergeHtml, isCompatible, opt pptx_content_writer.BinaryFileWriter.ImportFromMemory(old); }}); } - if (this.Document.CustomXmls.length > 0) { - this.WriteTable(c_oSerTableTypes.Customs, new BinaryCustomsTableWriter(this.memory, this.Document, this.Document.CustomXmls)); + + let customXmlManager = this.Document.getCustomXmlManager(); + if (customXmlManager.getCount() > 0) { + this.WriteTable(c_oSerTableTypes.Customs, new BinaryCustomsTableWriter(this.memory, this.Document, customXmlManager)); } //Write Settings this.WriteTable(c_oSerTableTypes.Settings, new BinarySettingsTableWriter(this.memory, this.Document, this.saveParams)); @@ -6530,12 +6534,18 @@ function BinaryDocumentTableWriter(memory, doc, oMapCommentId, oNumIdMap, copyPa // if (oSdt.EndPr) { // this.bs.WriteItem(c_oSerSdt.EndPr, function(){oThis.brPrs.Write_rPr(oSdt.EndPr, null, null);}); // } - if (0 === type) { + + if (0 === type) + { var oInnerDocument = new BinaryDocumentTableWriter(this.memory, this.Document, this.oMapCommentId, this.oNumIdMap, this.copyParams, this.saveParams, this.oBinaryHeaderFooterTableWriter); this.bs.WriteItem(c_oSerSdt.Content, function(){oInnerDocument.WriteDocumentContent(oSdt.Content);}); - } else if (1 === type) { + } + else if (1 === type) + { this.bs.WriteItem(c_oSerSdt.Content, function(){oThis.WriteParagraphContent(oSdt, false, false);}); } + + }; this.WriteSdtPr = function (val, oSdt) { @@ -6553,9 +6563,9 @@ function BinaryDocumentTableWriter(memory, doc, oMapCommentId, oNumIdMap, copyPa rPr.Color = val.Color; oThis.bs.WriteItem(c_oSerSdt.Color, function (){oThis.brPrs.Write_rPr(rPr, null, null);}); } - // if (null != val.DataBinding) { - // oThis.bs.WriteItem(c_oSerSdt.DataBinding, function (){oThis.WriteSdtPrDataBinding(val.DataBinding);}); - // } + if (null != val.DataBinding) { + oThis.bs.WriteItem(c_oSerSdt.DataBinding, function (){oThis.WriteSdtPrDataBinding(val.DataBinding);}); + } // if (null != val.DocPartList) { // oThis.bs.WriteItem(c_oSerSdt.DocPartList, function (){oThis.WriteDocPartList(val.DocPartList);}); // } @@ -6691,17 +6701,25 @@ function BinaryDocumentTableWriter(memory, doc, oMapCommentId, oNumIdMap, copyPa this.WriteSdtPrDataBinding = function (val) { var oThis = this; - if (null != val.PrefixMappings) { + if (null != val.prefixMappings) { this.memory.WriteByte(c_oSerSdt.PrefixMappings); - this.memory.WriteString2(val.PrefixMappings); + this.memory.WriteString2(val.prefixMappings); } - if (null != val.StoreItemID) { + if (null != val.storeItemID) { this.memory.WriteByte(c_oSerSdt.StoreItemID); - this.memory.WriteString2(val.StoreItemID); + this.memory.WriteString2(val.storeItemID); } - if (null != val.XPath) { + if (null != val.xpath) { this.memory.WriteByte(c_oSerSdt.XPath); - this.memory.WriteString2(val.XPath); + this.memory.WriteString2(val.xpath); + } + if (null !== val.storeItemCheckSum) + { + //let strCustomXmlContent = this.Document.customXml.getContentByDataBinding(val); + //val.recalculateCheckSum(strCustomXmlContent); + + this.memory.WriteByte(c_oSerSdt.StoreItemCheckSum); + this.memory.WriteString2(val.storeItemCheckSum); } }; this.WriteSdtPrDate = function (val) @@ -7566,12 +7584,14 @@ function BinaryNotesTableWriter(memory, doc, oNumIdMap, oMapCommentId, copyParam this.bs.WriteItem(c_oSerNotes.NoteContent, function(){dtw.WriteDocumentContent(note);}); }; }; -function BinaryCustomsTableWriter(memory, doc, CustomXmls) + +function BinaryCustomsTableWriter(memory, doc, customXmlManager) { this.memory = memory; this.Document = doc; this.bs = new BinaryCommonWriter(this.memory); - this.CustomXmls = CustomXmls; + this.customXmlManager = customXmlManager; + this.Write = function() { var oThis = this; @@ -7580,25 +7600,26 @@ function BinaryCustomsTableWriter(memory, doc, CustomXmls) this.WriteCustomXmls = function() { var oThis = this; - for (var i = 0; i < this.CustomXmls.length; ++i) { - this.bs.WriteItem(c_oSerCustoms.Custom, function() {oThis.WriteCustomXml(oThis.CustomXmls[i]);}); + for (var i = 0, count = this.customXmlManager.getCount(); i < count; ++i) { + this.bs.WriteItem(c_oSerCustoms.Custom, function() {oThis.WriteCustomXml(oThis.customXmlManager.getCustomXml(i));}); } }; this.WriteCustomXml = function(customXml) { var oThis = this; - for(var i = 0; i < customXml.Uri.length; ++i){ + for(var i = 0; i < customXml.uri.length; ++i){ this.bs.WriteItem(c_oSerCustoms.Uri, function () { - oThis.memory.WriteString3(customXml.Uri[i]); + oThis.memory.WriteString3(customXml.uri[i]); }); } - if (null !== customXml.ItemId) { + if (null !== customXml.itemId) { this.bs.WriteItem(c_oSerCustoms.ItemId, function() { - oThis.memory.WriteString3(customXml.ItemId); + oThis.memory.WriteString3(customXml.itemId); }); } - if (null !== customXml.Content) { + if (null !== customXml.content) { this.bs.WriteItem(c_oSerCustoms.ContentA, function() { - oThis.memory.WriteBuffer(customXml.Content, 0, customXml.Content.length) + let str = customXmlManager.getCustomXMLString(customXml); + oThis.memory.WriteCustomStringA(str); }); } }; @@ -7892,7 +7913,7 @@ function BinaryFileReader(doc, openParams) break; case c_oSerTableTypes.Customs: this.stream.Seek2(mtiOffBits); - res = (new Binary_CustomsTableReader(this.Document, this.oReadResult, this.stream, this.Document.CustomXmls)).Read(); + res = (new Binary_CustomsTableReader(this.Document, this.oReadResult, this.stream)).Read(); break; case c_oSerTableTypes.Glossary: if(!this.oReadResult.bCopyPaste || this.oReadResult.isDocumentPasting()) { @@ -11230,6 +11251,7 @@ function Binary_DocumentTableReader(doc, oReadResult, openParams, stream, curNot res = this.bcr.Read1(length, function(t, l){ return oThis.ReadSdt(t,l, oSdt, 0); }); + oSdt.checkDataBinding(); Content.push(oSdt); } else if ( c_oSerParType.Background === type ) { res = this.bcr.Read2(length, function(t, l){ @@ -11572,6 +11594,7 @@ function Binary_DocumentTableReader(doc, oReadResult, openParams, stream, curNot res = this.bcr.Read1(length, function(t, l){ return oThis.ReadSdt(t,l, oSdt, 1, oSdt); }); + oSdt.checkDataBinding(); if (oSdt.IsEmpty()) oSdt.ReplaceContentWithPlaceHolder(); paragraphContent.AddToContentToEnd(oSdt); @@ -12881,20 +12904,25 @@ function Binary_DocumentTableReader(doc, oReadResult, openParams, stream, curNot if (oSdtContent.length > 0) { oSdt.Content.ReplaceContent(oSdtContent); } - } else if (1 === typeContainer) { + } + else if (1 === typeContainer) { res = this.bcr.Read1(length, function(t, l) { return oThis.ReadParagraphContent(t, l, container); }); - } else if (2 === typeContainer) { + } + else if (2 === typeContainer) { res = this.bcr.Read1(length, function(t, l) { return oThis.Read_TableContent(t, l, container); }); - } else if (3 === typeContainer) { + } + else if (3 === typeContainer) { res = this.bcr.Read1(length, function(t, l) { return oThis.ReadRowContent(t, l, container); }); } - } else { + } + else + { res = c_oSerConstants.ReadUnknown; } return res; @@ -12930,12 +12958,14 @@ function Binary_DocumentTableReader(doc, oReadResult, openParams, stream, curNot if(textPr.Color){ oSdtPr.Color = textPr.Color; } - // } else if (c_oSerSdt.DataBinding === type) { - // oSdtPr.DataBinding = {}; - // res = this.bcr.Read1(length, function(t, l) { - // return oThis.ReadSdtPrDataBinding(t, l, oSdtPr.DataBinding); - // }); - } else if (c_oSerSdt.PrDate === type) { + } + else if (c_oSerSdt.DataBinding === type) { + oSdtPr.DataBinding = new AscWord.DataBinding(); + res = this.bcr.Read1(length, function(t, l) { + return oThis.ReadSdtPrDataBinding(t, l, oSdtPr.DataBinding); + }); + } + else if (c_oSerSdt.PrDate === type) { var datePicker = new AscWord.CSdtDatePickerPr(); res = this.bcr.Read1(length, function(t, l) { return oThis.ReadSdtPrDate(t, l, datePicker); @@ -13064,13 +13094,14 @@ function Binary_DocumentTableReader(doc, oReadResult, openParams, stream, curNot }; this.ReadSdtPrDataBinding = function(type, length, val) { var res = c_oSerConstants.ReadOk; - var oThis = this; if (c_oSerSdt.PrefixMappings === type) { - val.PrefixMappings = this.stream.GetString2LE(length); + val.prefixMappings = this.stream.GetString2LE(length); } else if (c_oSerSdt.StoreItemID === type) { - val.StoreItemID = this.stream.GetString2LE(length); + val.storeItemID = this.stream.GetString2LE(length); } else if (c_oSerSdt.XPath === type) { - val.XPath = this.stream.GetString2LE(length); + val.xpath = this.stream.GetString2LE(length); + } else if (c_oSerSdt.StoreItemCheckSum === type) { + val.storeItemCheckSum = this.stream.GetString2LE(length) } else { res = c_oSerConstants.ReadUnknown; } @@ -16027,11 +16058,12 @@ function Binary_OtherTableReader(doc, oReadResult, stream) return res; }; }; -function Binary_CustomsTableReader(doc, oReadResult, stream, CustomXmls) { + +function Binary_CustomsTableReader(doc, oReadResult, stream) { this.Document = doc; this.oReadResult = oReadResult; this.stream = stream; - this.CustomXmls = CustomXmls; + this.customXmlManager = doc.getCustomXmlManager(); this.bcr = new Binary_CommonReader(this.stream); this.Read = function() { var oThis = this; @@ -16043,11 +16075,14 @@ function Binary_CustomsTableReader(doc, oReadResult, stream, CustomXmls) { var res = c_oSerConstants.ReadOk; var oThis = this; if (c_oSerCustoms.Custom === type) { - var custom = {Uri: [], ItemId: null, Content: null}; + + var custom = new AscWord.CustomXml(); + res = this.bcr.Read1(length, function(t, l) { return oThis.ReadCustomContent(t, l, custom); }); - this.CustomXmls.push(custom); + + this.customXmlManager.add(custom); } else res = c_oSerConstants.ReadUnknown; @@ -16056,11 +16091,11 @@ function Binary_CustomsTableReader(doc, oReadResult, stream, CustomXmls) { this.ReadCustomContent = function(type, length, custom) { var res = c_oSerConstants.ReadOk; if (c_oSerCustoms.Uri === type) { - custom.Uri.push(this.stream.GetString2LE(length)); + custom.uri.push(this.stream.GetString2LE(length)); } else if (c_oSerCustoms.ItemId === type) { - custom.ItemId = this.stream.GetString2LE(length); + custom.itemId = this.stream.GetString2LE(length); } else if (c_oSerCustoms.ContentA === type) { - custom.Content = this.stream.GetBuffer(length); + custom.addContent(this.stream.GetBuffer(length)) } else res = c_oSerConstants.ReadUnknown; return res; diff --git a/word/Editor/StructuredDocumentTags/BlockLevel.js b/word/Editor/StructuredDocumentTags/BlockLevel.js index d690eb6bd5..24c8726033 100644 --- a/word/Editor/StructuredDocumentTags/BlockLevel.js +++ b/word/Editor/StructuredDocumentTags/BlockLevel.js @@ -562,6 +562,8 @@ CBlockLevelSdt.prototype.Remove = function(nCount, isRemoveWholeElement, bRemove return true; } + this.SetContentByDataBinding(this); + return bResult; }; CBlockLevelSdt.prototype.Is_Empty = function() @@ -594,6 +596,17 @@ CBlockLevelSdt.prototype.Add = function(oParaItem) this.Content.AddToParagraph(oParaItem); } + if (this.Pr.DataBinding) + { + var nContentPos = this.Content.CurPos.ContentPos; + var Item = this.Content.Content[nContentPos]; + + if (this.Pr.Text) + this.SetContentByDataBinding(Item.GetText()); + else + this.SetContentByDataBinding(this) + } + if (isRemoveWrapper) this.RemoveContentControlWrapper(); }; @@ -1462,6 +1475,9 @@ CBlockLevelSdt.prototype.SetPr = function(oPr) if (undefined !== oPr.Color) this.SetColor(oPr.Color); + + if (undefined !== oPr.DataBinding) + this.setDataBinding(oPr.DataBinding); }; /** * Выставляем настройки текста по умолчанию для данного контрола @@ -1559,6 +1575,60 @@ CBlockLevelSdt.prototype.SetColor = function(oColor) this.Pr.Color = oColor; } }; +CBlockLevelSdt.prototype.fillContentWithDataBinding = function(content) +{ + let logicDocument = this.GetLogicDocument(); + + if (this.IsCheckBox()) + { + let checkBoxPr = new AscWord.CSdtCheckBoxPr(); + + if (content === "true" || content === "1") + checkBoxPr.SetChecked(true); + else if (content === "false" || content === "0") + checkBoxPr.SetChecked(false); + + this.SetCheckBoxPr(checkBoxPr) + } + else if (this.IsDatePicker()) + { + let datePr = new AscWord.CSdtDatePickerPr(); + datePr.SetFullDate(content); + this.SetDatePickerPr(datePr); + this.private_UpdateDatePickerContent(); + } + else if (this.IsDropDownList() || this.IsComboBox() || this.Pr.Text === true) + { + let oRun = new ParaRun(); + oRun.AddText(content); + + // now style reset todo + this.Content.Remove_FromContent(0, this.Content.Content.length); + this.AddNewParagraph(); + this.Content.AddText(content); + } + else + { + let oParent = this.Parent; + if (oParent instanceof CDocumentContent) + oParent = oParent.Parent + + // if parent element is rich text content control - skip + if (oParent instanceof CBlockLevelSdt && oParent.GetSpecificType() === Asc.c_oAscContentControlSpecificType.None) + return; + + let customXmlManager = logicDocument.getCustomXmlManager(); + let arrContent = customXmlManager.proceedLinearXMl(content); + + this.Content.RemoveFromContent(0, this.Content.Content.length); + this.Content.AddContent(arrContent); + this.Content.Recalculate(true); + } +}; +CBlockLevelSdt.prototype.GetDataBinding = function () +{ + return this.Pr.DataBinding; +}; CBlockLevelSdt.prototype.GetColor = function() { return this.Pr.Color; @@ -2011,6 +2081,8 @@ CBlockLevelSdt.prototype.private_UpdateCheckBoxContent = function() oRun.SetRFontsCS({Index : -1, Name : this.Pr.CheckBox.UncheckedFont}); oRun.SetRFontsEastAsia({Index : -1, Name : this.Pr.CheckBox.UncheckedFont}); } + + this.SetContentByDataBinding(isChecked ? "true" : "false"); }; /** * Проверяем, является ли данный класс специальным контейнером для картинки @@ -2276,6 +2348,8 @@ CBlockLevelSdt.prototype.SelectListItem = function(sValue) oRun.AddText(sText); } } + + this.SetContentByDataBinding(sText); }; CBlockLevelSdt.prototype.private_UpdateListContent = function() { @@ -2420,6 +2494,16 @@ CBlockLevelSdt.prototype.private_UpdateDatePickerContent = function() if (oRun) oRun.AddText(sText); + + this.SetContentByDataBinding(sText); +}; +CBlockLevelSdt.prototype.SetContentByDataBinding = function (inputData) +{ + if (this.Pr.DataBinding) + { + let CustomManager = this.LogicDocument.getCustomXmlManager(); + CustomManager.setContentByDataBinding(this.Pr.DataBinding, inputData); + } }; CBlockLevelSdt.prototype.Document_Is_SelectionLocked = function(CheckType, bCheckInner) { diff --git a/word/Editor/StructuredDocumentTags/InlineLevel.js b/word/Editor/StructuredDocumentTags/InlineLevel.js index 97b5e198a7..13617b6eec 100644 --- a/word/Editor/StructuredDocumentTags/InlineLevel.js +++ b/word/Editor/StructuredDocumentTags/InlineLevel.js @@ -150,6 +150,8 @@ CInlineLevelSdt.prototype.Add = function(Item) oNextForm.SetThisElementCurrentInParagraph(); oNextForm.MoveCursorToStartPos(); } + + this.SetContentByDataBinding(this.Pr.Text ? this.Content[0].GetText() : this); if (!this.IsForm() && this.IsContentControlTemporary()) this.RemoveContentControlWrapper(); @@ -908,6 +910,8 @@ CInlineLevelSdt.prototype.Remove = function(nDirection, bOnAddText) result = true; } + this.SetContentByDataBinding(this.Content[0].GetText()); + return result; }; CInlineLevelSdt.prototype.Shift_Range = function(Dx, Dy, _CurLine, _CurRange, _CurPage) @@ -1648,6 +1652,9 @@ CInlineLevelSdt.prototype.SetPr = function(oPr) if(undefined !== oPr.OForm) this.SetOForm(oPr.OForm); + + if (undefined !== oPr.DataBinding) + this.setDataBinding(oPr.DataBinding); }; /** * Выставляем настройки текста по умолчанию для данного контрола @@ -1990,6 +1997,7 @@ CInlineLevelSdt.prototype.ToggleCheckBox = function(isChecked) return; this.SetCheckBoxChecked(!this.Pr.CheckBox.Checked); + this.SetContentByDataBinding(this.Pr.CheckBox.Checked ? "true" : "false"); }; CInlineLevelSdt.prototype.SetCheckBoxChecked = function(isChecked) { @@ -2088,6 +2096,8 @@ CInlineLevelSdt.prototype.private_UpdateCheckBoxContent = function() oRun.SetRFontsCS({Index : -1, Name : this.Pr.CheckBox.UncheckedFont}); oRun.SetRFontsEastAsia({Index : -1, Name : this.Pr.CheckBox.UncheckedFont}); } + + this.SetContentByDataBinding(isChecked ? "true" : "false"); }; /** * Проверяем, является ли данный класс специальным контейнером для картинки @@ -2371,6 +2381,8 @@ CInlineLevelSdt.prototype.SelectListItem = function(sValue) oRun.AddText(sText); } } + + this.SetContentByDataBinding(sText); }; CInlineLevelSdt.prototype.private_UpdateListContent = function() { @@ -2488,13 +2500,27 @@ CInlineLevelSdt.prototype.private_UpdateDatePickerContent = function() if (oRun) oRun.AddText(sText); - + + this.SetContentByDataBinding(sText); + if (isTemporary) { this.Pr.Temporary = true; this.RemoveContentControlWrapper(); } }; +CInlineLevelSdt.prototype.SetContentByDataBinding = function (inputData) +{ + if (this.Pr.DataBinding) + { + let oLogicDocument = this.GetParagraph().GetLogicDocument(); + if (oLogicDocument) + { + let CustomManager = oLogicDocument.getCustomXmlManager(); + CustomManager.setContentByDataBinding(this.Pr.DataBinding, inputData); + } + } +}; /** * Является ли данный контейнер специальной текстовой формой * @returns {boolean} @@ -3763,6 +3789,48 @@ CInlineLevelSdt.prototype.CorrectSingleLineFormContent = function() } } }; +CInlineLevelSdt.prototype.fillContentWithDataBinding = function(content) +{ + let logicDocument = this.GetLogicDocument(); + + if (this.IsCheckBox()) + { + let checkBoxPr = new AscWord.CSdtCheckBoxPr(); + + if (content === "true" || content === "1") + checkBoxPr.SetChecked(true); + else if (content === "false" || content === "0") + checkBoxPr.SetChecked(false); + + this.SetCheckBoxPr(checkBoxPr) + } + else if (this.IsDatePicker()) + { + let datePr = new AscWord.CSdtDatePickerPr(); + datePr.SetFullDate(content); + this.SetDatePickerPr(datePr); + this.private_UpdateDatePickerContent(); + } + else if (this.IsDropDownList() || this.IsComboBox()) + { + this.ReplacePlaceHolderWithContent(); + let oRun = this.private_UpdateListContent(); + if (oRun) + oRun.AddText(content); + } + else if (this.Pr.Text === true) + { + return + } + else + { + let customXmlManager = logicDocument.getCustomXmlManager(); + let arrContent = customXmlManager.proceedLinearXMl(content); + + this.SetParagraph(arrContent[0]); + } +}; + //--------------------------------------------------------export-------------------------------------------------------- window['AscCommonWord'] = window['AscCommonWord'] || {}; diff --git a/word/Editor/StructuredDocumentTags/SdtBase.js b/word/Editor/StructuredDocumentTags/SdtBase.js index 685ba535b5..9ab98f9202 100644 --- a/word/Editor/StructuredDocumentTags/SdtBase.js +++ b/word/Editor/StructuredDocumentTags/SdtBase.js @@ -1124,4 +1124,52 @@ CSdtBase.prototype.IsHideContentControlTrack = function() return Asc.c_oAscSdtAppearance.Hidden === this.GetAppearance(); }; +CSdtBase.prototype.setDataBinding = function(dataBinding) +{ + AscCommon.History.Add(new CChangesSdtPrDataBinding(this, this.Pr.DataBinding, dataBinding)); + this.Pr.DataBinding = dataBinding; +}; +CSdtBase.prototype.getDataBinding = function() +{ + return this.Pr.DataBinding; +}; +/** + * Проверяем, есть ли привязанные данные, и если есть заполняем ими содержимое контрола + */ +CSdtBase.prototype.checkDataBinding = function() +{ + let logicDocument = this.GetLogicDocument(); + if (!logicDocument || !this.Pr.DataBinding) + return; + + let content = logicDocument.getCustomXmlManager().getContentByDataBinding(this.Pr.DataBinding, this); + if (!content) + return; + + if (this.IsPicture()) + { + let allDrawings = this.GetAllDrawingObjects(); + if (!allDrawings.length) + return; + + let drawing = allDrawings[0]; + let imageData = "data:image/jpeg;base64," + content; + let editor = logicDocument.GetApi(); + editor.ImageLoader.LoadImagesWithCallback([imageData], function(){}, 0, true); + + let w = drawing.getXfrmExtX(); + let h = drawing.getXfrmExtY(); + + let imageShape = logicDocument.DrawingObjects.createImage(imageData, 0, 0, w, h); + imageShape.setParent(drawing); + drawing.Set_GraphicObject(imageShape); + } + else + { + this.fillContentWithDataBinding(content); + } +}; +CSdtBase.prototype.fillContentWithDataBinding = function(content) +{ +}; diff --git a/word/Editor/StructuredDocumentTags/SdtPr.js b/word/Editor/StructuredDocumentTags/SdtPr.js index 0adbc4b9ca..5401e4ac53 100644 --- a/word/Editor/StructuredDocumentTags/SdtPr.js +++ b/word/Editor/StructuredDocumentTags/SdtPr.js @@ -39,6 +39,8 @@ function CSdtPr() this.Tag = undefined; this.Label = undefined; this.Lock = undefined; + + this.DataBinding = undefined; this.DocPartObj = { Gallery : undefined, @@ -84,6 +86,9 @@ CSdtPr.prototype.Copy = function() oPr.Appearance = this.Appearance; oPr.Color = (this.Color ? this.Color.Copy() : undefined); + if (this.DataBinding) + oPr.DataBinding = this.DataBinding.copy(); + if (this.CheckBox) oPr.CheckBox = this.CheckBox.Copy(); @@ -263,6 +268,12 @@ CSdtPr.prototype.Write_ToBinary = function(Writer) this.ComplexFormPr.WriteToBinary(Writer); Flags |= (1 << 22); } + + if (this.DataBinding) + { + this.DataBinding.toBinary(Writer); + Flags |= (1 << 23); + } var EndPos = Writer.GetCurPosition(); Writer.Seek(StartPos); @@ -368,6 +379,9 @@ CSdtPr.prototype.Read_FromBinary = function(Reader) this.ComplexFormPr = new AscWord.CSdtComplexFormPr(); this.ComplexFormPr.ReadFromBinary(Reader); } + + if (Flags & (1 << 23)) + this.DataBinding = AscWord.DataBinding.fromBinary(Reader); }; CSdtPr.prototype.IsBuiltInDocPart = function() { diff --git a/word/Editor/StructuredDocumentTags/SdtPrChanges.js b/word/Editor/StructuredDocumentTags/SdtPrChanges.js index e2e237ad40..1e80f77d28 100644 --- a/word/Editor/StructuredDocumentTags/SdtPrChanges.js +++ b/word/Editor/StructuredDocumentTags/SdtPrChanges.js @@ -56,6 +56,8 @@ AscDFH.changesFactory[AscDFH.historyitem_SdtPr_TextForm] = CChangesSdtPr AscDFH.changesFactory[AscDFH.historyitem_SdtPr_FormPr] = CChangesSdtPrFormPr; AscDFH.changesFactory[AscDFH.historyitem_SdtPr_PictureFormPr] = CChangesSdtPrPictureFormPr; AscDFH.changesFactory[AscDFH.historyitem_SdtPr_ComplexFormPr] = CChangesSdtPrComplexFormPr; +AscDFH.changesFactory[AscDFH.historyitem_SdtPr_OForm] = CChangesSdtPrOForm; +AscDFH.changesFactory[AscDFH.historyitem_SdtPr_DataBinding] = CChangesSdtPrDataBinding; //---------------------------------------------------------------------------------------------------------------------- // Карта зависимости изменений //---------------------------------------------------------------------------------------------------------------------- @@ -83,6 +85,9 @@ AscDFH.changesRelationMap[AscDFH.historyitem_SdtPr_Appearance] = [ AscDFH.changesRelationMap[AscDFH.historyitem_SdtPr_Color] = [ AscDFH.historyitem_SdtPr_Color ]; +AscDFH.changesRelationMap[AscDFH.historyitem_SdtPr_DataBinding] = [ + AscDFH.historyitem_SdtPr_DataBinding +]; AscDFH.changesRelationMap[AscDFH.historyitem_SdtPr_CheckBox] = [ AscDFH.historyitem_SdtPr_CheckBox, AscDFH.historyitem_SdtPr_CheckBox_Checked @@ -138,7 +143,7 @@ function private_SdtPrChangesCheckLock(lockData) { if (lockData && lockData.isFillingForm()) lockData.setLock(true); - + if (this instanceof AscWord.CInlineLevelSdt) private_ParagraphContentChangesCheckLock.apply(this, arguments); } @@ -427,6 +432,30 @@ CChangesSdtPrColor.prototype.IsNeedRecalculate = function() return false; }; CChangesSdtPrColor.prototype.CheckLock = private_SdtPrChangesCheckLock; +/** + * @constructor + * @extends {AscDFH.CChangesBaseObjectProperty} + */ +function CChangesSdtPrDataBinding(Class, Old, New) +{ + AscDFH.CChangesBaseObjectProperty.call(this, Class, Old, New); +} +CChangesSdtPrDataBinding.prototype = Object.create(AscDFH.CChangesBaseObjectProperty.prototype); +CChangesSdtPrDataBinding.prototype.constructor = CChangesSdtPrDataBinding; +CChangesSdtPrDataBinding.prototype.Type = AscDFH.historyitem_SdtPr_DataBinding; +CChangesSdtPrDataBinding.prototype.private_SetValue = function(Value) +{ + this.Class.Pr.DataBinding = Value; +}; +CChangesSdtPrDataBinding.prototype.private_CreateObject = function() +{ + return new AscWord.DataBinding(); +}; +CChangesSdtPrDataBinding.prototype.IsNeedRecalculate = function() +{ + return true; +}; + /** * @constructor * @extends {AscDFH.CChangesBaseObjectProperty} diff --git a/word/Editor/custom-xml/custom-xml-manager.js b/word/Editor/custom-xml/custom-xml-manager.js new file mode 100644 index 0000000000..f0ffbfee2a --- /dev/null +++ b/word/Editor/custom-xml/custom-xml-manager.js @@ -0,0 +1,413 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +"use strict"; + +(function(window) +{ + /** + * Класс представляющий менеджер CustomXMLs + * @param {AscWord.CDocument} document + * @constructor + */ + function CustomXmlManager(document) + { + this.document = document; + this.xml = []; + this.saveCCs = []; + } + CustomXmlManager.prototype.add = function(customXml) + { + // TODO: Надо будет сделать этот метод с сохранением в историю, когда + // будем реализовывать возможность добавления таких xml во время работы + this.xml.push(customXml); + }; + CustomXmlManager.prototype.getCount = function() + { + return this.xml.length; + }; + CustomXmlManager.prototype.getCustomXml = function(index) + { + return this.xml[index]; + }; + + /** + * Find element/attribute of CustomXMl by xpath string + * @param root {CustomXMLContent} + * @param xpath {string} + * @return {{attribute: string, content: CustomXMLContent}} + */ + CustomXmlManager.prototype.findElementByXPath = function (root, xpath) + { + let arrParts = xpath.split('/'); + let currentElement = root; + + arrParts.shift(); // Убираем пустой первый элемент + + for (let i = 0; i < arrParts.length; i++) + { + let namespaceAndTag, + index, + tagName, + part = arrParts[i]; + + if (part.includes("@")) + { + let strAttributeName = part.slice(1); + return { + content: currentElement, + attribute: strAttributeName, + }; + } + else if (part.includes("[")) + { + namespaceAndTag = part.split('[')[0]; + let partBeforeCloseBracket = part.split(']')[0]; + index = partBeforeCloseBracket.slice(-1) - 1; + } + else + { + namespaceAndTag = part; + index = 0; + } + + tagName = namespaceAndTag.includes(":") + ? namespaceAndTag.split(':')[1] + : namespaceAndTag; + + let matchingChildren = currentElement.content.filter(function (child) { + let arr = child.name.split(":"); + + if (arr.length > 1) + return arr[1] === tagName; + else + return arr[0] === tagName; + }); + + if (matchingChildren.length <= index) + break; // Элемент не найден + + currentElement = matchingChildren[index]; + } + + return { + content: currentElement, + attribute: undefined, + }; + }; + /** + * Get custom xml data of content control by data binding property + * @param dataBinding {window.AscWord.DataBinding} + * @param oContentLink {CBlockLevelSdt | CInlineLevelSdt} + * @return {string | undefined} + */ + CustomXmlManager.prototype.getContentByDataBinding = function(dataBinding, oContentLink) + { + for (let i = 0; i < this.xml.length; ++i) + { + let customXml = this.xml[i]; + customXml.oContentLink = oContentLink; + + if (dataBinding.storeItemID === customXml.itemId || customXml.checkUrl(dataBinding.prefixMappings)) + { + let xPath = dataBinding.xpath; + let oFindEl = this.findElementByXPath(customXml.content, xPath); + let content = oFindEl.content; + let strAttribute = oFindEl.attribute; + + return (undefined !== strAttribute) + ? content.attribute[strAttribute] + : content.textContent; + } + } + }; + /** + * Set custom xml data of content control by data binding property + * @param {window.AscWord.DataBinding} dataBinding + * @param data {string | CBlockLevelSdt} + */ + CustomXmlManager.prototype.setContentByDataBinding = function (dataBinding, data) + { + for (let i = 0; i < this.xml.length; ++i) + { + let customXml = this.xml[i]; + + if (dataBinding.storeItemID === customXml.itemId) + { + let xPath = dataBinding.xpath; + let oFindEl = this.findElementByXPath(customXml.content, xPath); + let oContent = oFindEl.content; + let strAttribute = oFindEl.attribute; + + if (data instanceof AscCommonWord.CBlockLevelSdt) + { + // recording changes every time a control with formatted text changes is not efficient + // save which control needs to be processed, and update CustomXML field for rich text when save document + if (!this.saveCCs.includes(data)) + this.saveCCs.push(data); + + return; + } + + if (strAttribute) + oContent.setAttribute(strAttribute, data); + else + oContent.setTextContent(data); + } + } + }; + /** + * Write linear xml data of content control in CustomXML + * @param oCC {CBlockLevelSdt} + */ + CustomXmlManager.prototype.updateRichTextCustomXML = function (oCC) + { + function replaceSubstring(originalString, startPoint, endPoint, insertionString) + { + if (startPoint < 0 || endPoint >= originalString.length || startPoint > endPoint) + return originalString; + + const prefix = originalString.substring(0, startPoint); + const suffix = originalString.substring(endPoint + 1); + + return prefix + insertionString + suffix; + } + + AscFormat.ExecuteNoHistory(function() { + let doc = new AscWord.CDocument(null, false); + let oSdtContent = oCC.GetContent().Copy(); + let jsZlib = new AscCommon.ZLib(); + + doc.ReplaceContent(oSdtContent.Content); + jsZlib.create(); + doc.toZip(jsZlib, new AscCommon.XmlWriterContext(AscCommon.c_oEditorId.Word)); + + let openDoc = new AscCommon.openXml.OpenXmlPackage(jsZlib, null); + let outputUString = ""; + let arrPath = jsZlib.getPaths(); + + arrPath.forEach(function(path) + { + if ((path === "_rels/.rels" || path === "word/document.xml" || path === "word/_rels/document.xml.rels") && !path.includes("glossary")) + { + let ctfBytes = jsZlib.getFile(path); + let ctfText = AscCommon.UTF8ArrayToString(ctfBytes, 0, ctfBytes.length); + let type = openDoc.getContentType(path); + + if (path === "word/_rels/document.xml.rels") + { + let text = ''; + let arrRelationships = openDoc.getRelationships(); + + for (let i = 0; i < arrRelationships.length; i++) + { + let relation = arrRelationships[i]; + let relId = relation.relationshipId; + let relType = relation.relationshipType; + let relTarget = relation.target; + + if (i === 0) + { + relType = relType.replace("relationships\/officeDocument", "relationships\/styles"); + relTarget = relTarget.replace("word/document.xml", "styles.xml"); + } + + text += "" + } + + let nStart = ctfText.indexOf("", 0) + "".length; + let nEnd = ctfText.indexOf("", nStart) - 1; + ctfText = replaceSubstring(ctfText, nStart, nEnd, text); + } + + outputUString += " " + + "" + ctfText.replace("", "").replace("\n", "") + "" + } + }); + + outputUString = outputUString.replace("pkg:contentType=\"application/xml\"", "pkg:contentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml\""); + outputUString += ""; + outputUString = outputUString.replaceAll("<", "<"); + outputUString = outputUString.replaceAll(">", ">"); + this.setContentByDataBinding(oCC.Pr.DataBinding, outputUString); + }, this, []); + }; + /** + * Proceed linear xml from CustomXMl attribute or element for fill content control + * @param strLinearXML {string} + * @return {[]} Return array of CC content + */ + CustomXmlManager.prototype.proceedLinearXMl = function (strLinearXML) + { + strLinearXML = strLinearXML.replaceAll("<", "<"); + strLinearXML = strLinearXML.replaceAll(">", ">"); + strLinearXML = strLinearXML.replaceAll("", ""); + strLinearXML = strLinearXML.replaceAll("", ""); + + // при записи в атрибут больше проблем, изменить подход если в будущем еще будут проблемы c html entry + strLinearXML = strLinearXML.replaceAll(" ", ""); + strLinearXML = strLinearXML.replaceAll("&", "&"); + strLinearXML = strLinearXML.replaceAll(""", "\""); + strLinearXML = strLinearXML.replaceAll("'", "'"); + + let zLib = new AscCommon.ZLib; + zLib.create(); + zLib.addFile('[Content_Types].xml', new TextEncoder("utf-8").encode('' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '')); + + let nPos = 0; + while (true) + { + let nStartPos = nPos = strLinearXML.indexOf('', nStartPos); + let strText = strLinearXML.substring(nStartPos, nEndPos); + + let nPosStartName = strText.indexOf('name="', 0) + 'name="'.length; + let nPosEndName = strText.indexOf('"', nPosStartName); + let name = strText.substring(nPosStartName, nPosEndName); + + let nDataStartPos = strText.indexOf('', 0); + let nDataEndPos; + + if (nDataStartPos !== -1) + { + nDataStartPos = nDataStartPos + ''.length; + nDataEndPos = strText.indexOf('', nDataStartPos); + } + else + { + nDataStartPos = strText.indexOf('', 0); + if (nDataStartPos !== -1) + nDataStartPos += ''.length; + nDataEndPos = strText.indexOf('', nDataStartPos); + } + + if (nStartPos === -1 || nEndPos === -1) + continue; + + let data = strText.substring(nDataStartPos, nDataEndPos).trim(); + + if (name[0] === "/") + name = name.substring(1, name.length); + + zLib.addFile(name, new TextEncoder("utf-8").encode(data)); + } + + let arr = zLib.save(); + let draw = this.document.DrawingDocument; + let Doc = new CDocument(draw, false); + let xmlParserContext = new AscCommon.XmlParserContext(); + let jsZlib = new AscCommon.ZLib(); + + xmlParserContext.DrawingDocument = draw; + + if (!jsZlib.open(arr)) + return []; + + let oBinaryFileReader = new AscCommonWord.BinaryFileReader(Doc, {}); + oBinaryFileReader.PreLoadPrepare(); + + Doc.fromZip(jsZlib, xmlParserContext, oBinaryFileReader.oReadResult); + + oBinaryFileReader.PostLoadPrepare(xmlParserContext); + jsZlib.close(); + + return Doc.Content; + }; + /** + * Get CustomXML text + * @param oCustomXMl {AscWord.CustomXml} + * @return {string} + */ + CustomXmlManager.prototype.getCustomXMLString = function(oCustomXMl) + { + this.updateCustomXMlFromRichTextCCs(); + return oCustomXMl.getText(); + }; + /** + * Go through all edited rich text content controls and save it's content in CustomXML + */ + CustomXmlManager.prototype.updateCustomXMlFromRichTextCCs = function () + { + for (let i = 0; i < this.saveCCs.length; i++) + { + this.updateRichTextCustomXML(this.saveCCs[i]); + } + }; + + //--------------------------------------------------------export---------------------------------------------------- + window['AscWord'] = window['AscWord'] || {}; + window['AscWord'].CustomXmlManager = CustomXmlManager; + +})(window); diff --git a/word/Editor/custom-xml/custom-xml.js b/word/Editor/custom-xml/custom-xml.js new file mode 100644 index 0000000000..98ed20c2be --- /dev/null +++ b/word/Editor/custom-xml/custom-xml.js @@ -0,0 +1,231 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +"use strict"; + +(function(window) +{ + /** + * @param {array} [uri] + * @param {string} [itemId] + * @param {CustomXMLContent} [content] + * @param [oContentLink] + * + * Класс представляющий CustomXML + * @constructor + */ + function CustomXml(uri, itemId, content, oContentLink) + { + this.uri = uri ? uri : []; + this.itemId = itemId ? itemId : ""; + this.content = content ? content : null; + this.oContentLink = oContentLink ? oContentLink : null; + } + + /** + * Get CustomXML data by string + * @return {string} + */ + CustomXml.prototype.getText = function () + { + return this.content.getStringFromBuffer(); + }; + /** + * Find url in uri array + * @return {boolean} + */ + CustomXml.prototype.checkUrl = function (str) + { + if (!str) + return false; + + for (let i = 0; i < this.uri.length; i++) + { + if (str.includes(this.uri[i])) + return true; + } + return false; + } + /** + * Add content of CustomXML + * @param arrData {array} + */ + CustomXml.prototype.addContent = function (arrData) + { + let strContent = "".fromUtf8(arrData), + strCustomXml = strContent.slice(strContent.indexOf("<"), strContent.length); // Skip "L" + + this.addContentByXMLString(strCustomXml); + }; + CustomXml.prototype.addContentByXMLString = function (strCustomXml) + { + let oStax = new StaxParser(strCustomXml), + rootContent = new CustomXMLContent(null); + + while (oStax.Read()) + { + switch (oStax.GetEventType()) { + case EasySAXEvent.CHARACTERS: + rootContent.addTextContent(oStax.text); + break; + case EasySAXEvent.END_ELEMENT: + rootContent = rootContent.getParent(); + break; + case EasySAXEvent.START_ELEMENT: + let name = oStax.GetName(); + let childElement = rootContent.addContent(name); + + while (oStax.MoveToNextAttribute()) + { + let attributeName = oStax.GetName(); + let attributeValue = oStax.GetValue(); + childElement.addAttribute(attributeName, attributeValue); + } + + rootContent = childElement; + break; + } + } + + this.content = rootContent; + } + + function CustomXMLContent(parent, name) + { + this.parent = parent; + this.name = name ? name : ""; + this.content = []; + this.attribute = {}; + this.textContent = ""; + + this.addAttribute = function (name, value) + { + this.attribute[name] = value; + }; + this.addContent = function (name) + { + let newItem = new CustomXMLContent(this, name); + + this.content.push(newItem); + return newItem; + }; + this.getParent = function () + { + if (this.parent) + return this.parent; + + return null; + }; + this.addTextContent = function (text) + { + if (text !== "") + this.textContent += text; + }; + this.setTextContent = function (str) + { + this.textContent = str; + }; + this.setAttribute = function (attribute, value) + { + this.attribute[attribute] = value; + }; + this.getBuffer = function () + { + let writer = new AscCommon.CMemory(); + let nTab = 0; + + function Write(content) + { + let current = null; + + if (!content.name) + { + writer.WriteXmlString("\x00\n"); + current = content.content[0]; + } + else + { + current = content; + } + + for (let i = 0; i < nTab; i++) + { + writer.WriteXmlString(" "); + } + + writer.WriteXmlNodeStart(current.name); + + let atr = Object.keys(current.attribute) + + for (let i = 0; i < atr.length; i++) + { + let cur = atr[i]; + writer.WriteXmlAttributeStringEncode(cur, current.attribute[cur]); + } + + writer.WriteXmlAttributesEnd(); + + for (let i = 0; i < current.content.length; i++) + { + nTab++; + if (i === 0) + writer.WriteXmlString("\n"); + let curContent = current.content[i]; + Write(curContent); + nTab--; + writer.WriteXmlString("\n"); + } + + if (current.textContent) + writer.WriteXmlString(current.textContent.toString().trim()); + + writer.WriteXmlNodeEnd(current.name); + } + + Write(this); + return writer; + }; + this.getStringFromBuffer = function () + { + let buffer = this.getBuffer(); + let str = AscCommon.UTF8ArrayToString(buffer.data, 1); + str = str.replaceAll(""", "\""); + str = str.replaceAll("&", "&"); + return str; + }; + } + + //--------------------------------------------------------export---------------------------------------------------- + window['AscWord'] = window['AscWord'] || {}; + window['AscWord'].CustomXml = CustomXml; + +})(window); diff --git a/word/Editor/custom-xml/data-binding.js b/word/Editor/custom-xml/data-binding.js new file mode 100644 index 0000000000..fbb4e2df41 --- /dev/null +++ b/word/Editor/custom-xml/data-binding.js @@ -0,0 +1,108 @@ +/* + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * + */ + +"use strict"; + +(function(window) +{ + /** + * @constructor + */ + function DataBinding(prefix, itemID, xpath, checkSum) + { + this.prefixMappings = prefix ? prefix : undefined; + this.storeItemID = itemID ? itemID : undefined; + this.xpath = xpath ? xpath : undefined; + this.storeItemCheckSum = checkSum ? checkSum : undefined; + } + DataBinding.prototype.copy = function() + { + return new DataBinding(this.prefixMappings, this.storeItemID, this.xpath, this.storeItemCheckSum); + }; + DataBinding.prototype.recalculateCheckSum = function (stringOfCustomXMlContent) + { + }; + DataBinding.prototype.toBinary = function(writer) + { + return this.Write_ToBinary(writer); + }; + DataBinding.fromBinary = function(reader) + { + let data = new DataBinding(); + data.Read_FromBinary(reader); + return data; + }; + DataBinding.prototype.Write_ToBinary = function(writer) + { + let startPos = writer.GetCurPosition(); + writer.Skip(4); + let flags = 0; + + if (undefined !== this.prefixMappings) + { + writer.WriteString2(this.prefixMappings); + flags |= 1; + } + + if (undefined !== this.storeItemID) + { + writer.WriteLong(this.storeItemID); + flags |= 2; + } + + if (undefined !== this.xpath) + { + writer.WriteString2(this.xpath); + flags |= 4; + } + + let endPos = startPos.GetCurPosition(); + writer.Seek(startPos); + writer.WriteLong(flags); + writer.Seek(endPos); + }; + DataBinding.prototype.Read_FromBinary = function(reader) + { + let flags = reader.GetLong(); + if (flags & 1) + this.prefixMappings = reader.GetString2(); + if (flags & 2) + this.storeItemID = reader.GetString2(); + if (flags & 4) + this.xpath = reader.GetString2(); + }; + + //--------------------------------------------------------export---------------------------------------------------- + window['AscWord'] = window['AscWord'] || {}; + window['AscWord'].DataBinding = DataBinding; + +})(window); diff --git a/word/api.js b/word/api.js index b42913d1d7..7771edfac8 100644 --- a/word/api.js +++ b/word/api.js @@ -10749,6 +10749,12 @@ background-repeat: no-repeat;\ oApi.WordControl.m_oLogicDocument.SetImageProps(oImagePr); oCC.SetShowingPlcHdr(false); + if (oCC.Pr.DataBinding) + { + let CustomManager = oApi.WordControl.m_oLogicDocument.getCustomXmlManager(); + CustomManager.setContentByDataBinding(oCC.Pr.DataBinding, oDrawingObjects.selectedObjects[0].getPictureBase64Data().ImageUrl.replace("data:image/png;base64,", "")); + } + if (oCC.IsPictureForm()) { oCC.UpdatePictureFormLayout();