810 lines
22 KiB
JavaScript
810 lines
22 KiB
JavaScript
/*
|
||
* (c) Copyright Ascensio System SIA 2010-2025
|
||
*
|
||
* 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()
|
||
{
|
||
/**
|
||
* Class for managing document sections and their header/footer content.
|
||
*
|
||
* @param {AscWord.Document} logicDocument - The parent document object
|
||
* @constructor
|
||
*/
|
||
function DocumentSections(logicDocument)
|
||
{
|
||
this.logicDocument = logicDocument;
|
||
this.Elements = [];
|
||
|
||
this.needUpdate = true;
|
||
|
||
this.paragraphToCheck = {};
|
||
|
||
this.paraToSection = {};
|
||
}
|
||
DocumentSections.prototype.GetFirstSectPr = function()
|
||
{
|
||
this.Update();
|
||
|
||
if (!this.Elements.length)
|
||
return this.logicDocument.GetFinalSectPr();
|
||
|
||
return this.Elements[0].SectPr;
|
||
};
|
||
/**
|
||
* @returns {AscWord.SectPr}
|
||
*/
|
||
DocumentSections.prototype.GetNextSectPr = function(sectPr)
|
||
{
|
||
this.Update();
|
||
|
||
let index = this.Find(sectPr);
|
||
if (-1 === index || index >= this.Elements.length - 1)
|
||
return sectPr;
|
||
|
||
return this.Elements[index + 1].SectPr;
|
||
};
|
||
DocumentSections.prototype.GetSectionsCount = function()
|
||
{
|
||
this.Update();
|
||
return this.Elements.length;
|
||
};
|
||
DocumentSections.prototype.Find_ByHdrFtr = function(HdrFtr)
|
||
{
|
||
if (!HdrFtr)
|
||
return -1;
|
||
|
||
this.Update();
|
||
|
||
var Count = this.Elements.length;
|
||
for (var Index = 0; Index < Count; Index++)
|
||
{
|
||
var SectPr = this.Elements[Index].SectPr;
|
||
|
||
if (HdrFtr === SectPr.Get_Header_First()
|
||
|| HdrFtr === SectPr.Get_Header_Default()
|
||
|| HdrFtr === SectPr.Get_Header_Even()
|
||
|| HdrFtr === SectPr.Get_Footer_First()
|
||
|| HdrFtr === SectPr.Get_Footer_Default()
|
||
|| HdrFtr === SectPr.Get_Footer_Even())
|
||
return Index;
|
||
}
|
||
|
||
return -1;
|
||
};
|
||
DocumentSections.prototype.Reset_HdrFtrRecalculateCache = function()
|
||
{
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.Reset_RecalculateCache();
|
||
});
|
||
};
|
||
DocumentSections.prototype.GetAllParagraphs = function(props, paragraphs)
|
||
{
|
||
if (!paragraphs)
|
||
paragraphs = [];
|
||
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.GetAllParagraphs(props, paragraphs);
|
||
});
|
||
|
||
return paragraphs;
|
||
};
|
||
DocumentSections.prototype.GetAllTables = function(props, tables)
|
||
{
|
||
if (!tables)
|
||
tables = [];
|
||
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.GetAllTables(props, tables);
|
||
});
|
||
|
||
return tables;
|
||
};
|
||
DocumentSections.prototype.GetAllDrawingObjects = function(drawings)
|
||
{
|
||
if (!drawings)
|
||
drawings = [];
|
||
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.GetAllDrawingObjects(drawings);
|
||
});
|
||
|
||
return drawings;
|
||
};
|
||
DocumentSections.prototype.UpdateBookmarks = function(bookmarkManager)
|
||
{
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.UpdateBookmarks(bookmarkManager);
|
||
});
|
||
};
|
||
DocumentSections.prototype.Document_CreateFontMap = function(fontMap)
|
||
{
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.Document_CreateFontMap(fontMap);
|
||
});
|
||
};
|
||
DocumentSections.prototype.Document_CreateFontCharMap = function(fontCharMap)
|
||
{
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.Document_CreateFontCharMap(fontCharMap);
|
||
});
|
||
};
|
||
DocumentSections.prototype.Document_Get_AllFontNames = function(allFonts)
|
||
{
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.Document_Get_AllFontNames(allFonts);
|
||
});
|
||
};
|
||
DocumentSections.prototype.GetSectPrByElement = function(element)
|
||
{
|
||
this.Update();
|
||
|
||
let finalSectPr = this.logicDocument.GetFinalSectPr();
|
||
if (!element)
|
||
return finalSectPr;
|
||
|
||
let docPos = element.GetDocumentPositionFromObject();
|
||
if (!docPos || !docPos.length)
|
||
return finalSectPr;
|
||
|
||
let topClass = docPos[0].Class;
|
||
if (topClass !== this.logicDocument)
|
||
{
|
||
let sectPr = topClass.Get_SectPr();
|
||
return sectPr ? sectPr : finalSectPr;
|
||
}
|
||
|
||
let b = 0;
|
||
let e = this.Elements.length - 1;
|
||
|
||
while (b < e)
|
||
{
|
||
let m = (b + e) >> 1;
|
||
let _docPos = this.Elements[m].Paragraph.GetDocumentPositionFromObject();
|
||
if (AscWord.CompareDocumentPositions(docPos, _docPos) <= 0)
|
||
e = m;
|
||
else
|
||
b = m + 1;
|
||
}
|
||
|
||
return this.Elements[b].SectPr;
|
||
};
|
||
DocumentSections.prototype.GetFirstParagraph = function(sectionIndex)
|
||
{
|
||
if (0 === sectionIndex)
|
||
return this.logicDocument.GetFirstParagraph();
|
||
|
||
let prevParagraph = this.Elements[sectionIndex - 1].Paragraph;
|
||
return prevParagraph.GetNextParagraph();
|
||
};
|
||
DocumentSections.prototype.GetSectPrByIndex = function(index)
|
||
{
|
||
return this.Elements[index].SectPr;
|
||
};
|
||
DocumentSections.prototype.Find = function(sectPr)
|
||
{
|
||
if (!sectPr)
|
||
return -1;
|
||
|
||
this.Update();
|
||
|
||
for (let i = 0, count = this.Elements.length; i < count; ++i)
|
||
{
|
||
if (this.Elements[i].SectPr === sectPr)
|
||
return i;
|
||
}
|
||
|
||
return -1;
|
||
};
|
||
DocumentSections.prototype.Update = function()
|
||
{
|
||
if (!this.CheckNeedUpdate())
|
||
return;
|
||
|
||
this._clear();
|
||
|
||
let paragraphs = this.logicDocument.GetAllSectPrParagraphs();
|
||
for (let i = 0; i < paragraphs.length; ++i)
|
||
{
|
||
this._addSection(paragraphs[i].Get_SectionPr(), paragraphs[i]);
|
||
}
|
||
this._addSection(this.logicDocument.GetFinalSectPr(), this.logicDocument);
|
||
|
||
// Когда полностью обновляются секции надо пересчитывать с самого начала
|
||
this.logicDocument.RecalcInfo.Set_NeedRecalculateFromStart(true);
|
||
|
||
this.needUpdate = false;
|
||
};
|
||
DocumentSections.prototype.CheckNeedUpdate = function()
|
||
{
|
||
for (let paraId in this.paragraphToCheck)
|
||
{
|
||
let para = this.paragraphToCheck[paraId];
|
||
if (!para.Get_SectionPr() || para.CanAddSectionPr())
|
||
{
|
||
this.needUpdate = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return this.needUpdate;
|
||
};
|
||
DocumentSections.prototype.CheckParagraph = function(paragraph)
|
||
{
|
||
if (paragraph && paragraph.Get_SectionPr())
|
||
this.paragraphToCheck[paragraph.GetId()] = paragraph;
|
||
};
|
||
DocumentSections.prototype.UpdateOnAdd = function(items)
|
||
{
|
||
this.Update();
|
||
|
||
for (let i = 0, count = items.length; i < count; ++i)
|
||
{
|
||
let paragraphs = items[i].GetAllSectPrParagraphs();
|
||
for (let paraIndex = 0, paraCount = paragraphs.length; paraIndex < paraCount; ++paraIndex)
|
||
{
|
||
let paragraph = paragraphs[paraIndex];
|
||
|
||
let paraId = paragraph.GetId();
|
||
let sectPr = paragraph.Get_SectionPr();
|
||
if (!sectPr || this.paraToSection[paraId])
|
||
continue;
|
||
|
||
let sectionPos = this.GetIndexByElement(paragraph);
|
||
if (-1 === sectionPos)
|
||
continue;
|
||
|
||
this._insertSection(sectionPos, sectPr, paragraph);
|
||
}
|
||
}
|
||
};
|
||
DocumentSections.prototype.UpdateOnRemove = function(items, checkHdrFtr)
|
||
{
|
||
this.Update();
|
||
|
||
let paragraphs = [];
|
||
for (let i = 0, count = items.length; i < count; ++i)
|
||
{
|
||
items[i].GetAllSectPrParagraphs(paragraphs);
|
||
}
|
||
|
||
// По логике удаляемые секции должны идти последовательно, но будем проверять каждую отдельно
|
||
for (let i = 0, count = paragraphs.length; i < count; ++i)
|
||
{
|
||
let sectionPos = this.GetIndexByElement(paragraphs[i]);
|
||
if (-1 === sectionPos)
|
||
continue;
|
||
|
||
if (checkHdrFtr && sectionPos < this.Elements.length - 1)
|
||
{
|
||
let currSectPr = this.Elements[sectionPos].SectPr;
|
||
let nextSectPr = this.Elements[sectionPos + 1].SectPr;
|
||
if (nextSectPr.IsAllHdrFtrNull() && !currSectPr.IsAllHdrFtrNull())
|
||
{
|
||
nextSectPr.Set_Header_First(currSectPr.Get_Header_First());
|
||
nextSectPr.Set_Header_Even(currSectPr.Get_Header_Even());
|
||
nextSectPr.Set_Header_Default(currSectPr.Get_Header_Default());
|
||
nextSectPr.Set_Footer_First(currSectPr.Get_Footer_First());
|
||
nextSectPr.Set_Footer_Even(currSectPr.Get_Footer_Even());
|
||
nextSectPr.Set_Footer_Default(currSectPr.Get_Footer_Default());
|
||
}
|
||
}
|
||
|
||
this._removeSection(sectionPos);
|
||
}
|
||
};
|
||
DocumentSections.prototype.GetCount = function()
|
||
{
|
||
this.Update();
|
||
return this.Elements.length;
|
||
};
|
||
/**
|
||
* Получаем секцию по заданному номеру
|
||
* @param {number} nIndex
|
||
* @returns {DocumentSection}
|
||
*/
|
||
DocumentSections.prototype.Get = function(nIndex)
|
||
{
|
||
this.Update();
|
||
return this.Elements[nIndex];
|
||
};
|
||
/**
|
||
* Получаем номер секции, в которой лежит заданный элемент
|
||
* @param element
|
||
* @returns {number}
|
||
*/
|
||
DocumentSections.prototype.GetIndexByElement = function(element)
|
||
{
|
||
this.Update();
|
||
|
||
let b = 0;
|
||
let e = this.Elements.length - 1;
|
||
|
||
if (!element)
|
||
return -1;
|
||
|
||
let docPos = element.GetDocumentPositionFromObject();
|
||
if (!docPos || !docPos.length)
|
||
return -1;
|
||
|
||
let topClass = docPos[0].Class;
|
||
if (topClass !== this.logicDocument)
|
||
{
|
||
let sectPr = topClass.Get_SectPr();
|
||
return this.Find(sectPr);
|
||
}
|
||
|
||
while (b < e)
|
||
{
|
||
let m = (b + e) >> 1;
|
||
let _docPos = this.Elements[m].Paragraph.GetDocumentPositionFromObject();
|
||
if (AscWord.CompareDocumentPositions(docPos, _docPos) <= 0)
|
||
e = m;
|
||
else
|
||
b = m + 1;
|
||
}
|
||
|
||
return b;
|
||
};
|
||
/**
|
||
* Получаем массив всех колонтитулов, используемых в данном документе
|
||
* @returns {Array.CHeaderFooter}
|
||
*/
|
||
DocumentSections.prototype.GetAllHdrFtrs = function()
|
||
{
|
||
let result = [];
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
result.push(hdrFtr);
|
||
});
|
||
return result;
|
||
};
|
||
DocumentSections.prototype.GetAllContentControls = function(contentControls)
|
||
{
|
||
this.forEachHdrFtr(function(hdrFtr){
|
||
hdrFtr.GetAllContentControls(contentControls);
|
||
});
|
||
};
|
||
/**
|
||
* Обновляем заданную секцию
|
||
* @param paragraph {AscWord.Paragraph} - Параграф, в котором обновляется секция
|
||
* @param prevSectPr {AscWord.SectPr} - Предыдущая секция в заданном параграфе (если она была)
|
||
* @param checkHdrFtr {boolean} - Нужно ли проверять колонтитулы при удалении секции
|
||
* @returns {boolean} Если не смогли обновить, возвращаем false
|
||
*/
|
||
DocumentSections.prototype.UpdateSection = function(paragraph, prevSectPr, checkHdrFtr)
|
||
{
|
||
this.Update();
|
||
|
||
let newSectPr = paragraph.Get_SectionPr();
|
||
if (prevSectPr)
|
||
{
|
||
let sectionPos = this.Find(prevSectPr);
|
||
if (-1 === sectionPos || this.paraToSection[paragraph.GetId()] !== this.Elements[sectionPos])
|
||
return;
|
||
|
||
if (newSectPr)
|
||
{
|
||
this.Elements[sectionPos].SectPr = newSectPr;
|
||
}
|
||
else
|
||
{
|
||
if (checkHdrFtr && sectionPos < this.Elements.length - 1)
|
||
{
|
||
let currSectPr = this.Elements[sectionPos].SectPr;
|
||
let nextSectPr = this.Elements[sectionPos + 1].SectPr;
|
||
if (nextSectPr.IsAllHdrFtrNull() && !currSectPr.IsAllHdrFtrNull())
|
||
{
|
||
nextSectPr.Set_Header_First(currSectPr.Get_Header_First());
|
||
nextSectPr.Set_Header_Even(currSectPr.Get_Header_Even());
|
||
nextSectPr.Set_Header_Default(currSectPr.Get_Header_Default());
|
||
nextSectPr.Set_Footer_First(currSectPr.Get_Footer_First());
|
||
nextSectPr.Set_Footer_Even(currSectPr.Get_Footer_Even());
|
||
nextSectPr.Set_Footer_Default(currSectPr.Get_Footer_Default());
|
||
}
|
||
}
|
||
this._removeSection(sectionPos);
|
||
}
|
||
}
|
||
else if (newSectPr)
|
||
{
|
||
if (this.paraToSection[paragraph.GetId()])
|
||
{
|
||
this.paraToSection[paragraph.GetId()].SectPr = newSectPr;
|
||
}
|
||
else
|
||
{
|
||
let sectionPos = this.GetIndexByElement(paragraph);
|
||
if (-1 === sectionPos)
|
||
return;
|
||
|
||
this._insertSection(sectionPos, newSectPr, paragraph)
|
||
}
|
||
}
|
||
};
|
||
DocumentSections.prototype.private_GetHdrFtrsArray = function(oCurHdrFtr)
|
||
{
|
||
var isEvenOdd = EvenAndOddHeaders;
|
||
|
||
var nCurPos = -1;
|
||
var arrHdrFtrs = [];
|
||
for (var nIndex = 0, nCount = this.Elements.length; nIndex < nCount; ++nIndex)
|
||
{
|
||
var oSectPr = this.Elements[nIndex].SectPr;
|
||
var isFirst = oSectPr.Get_TitlePage();
|
||
|
||
var oHeaderFirst = oSectPr.Get_Header_First();
|
||
var oHeaderEven = oSectPr.Get_Header_Even();
|
||
var oHeaderDefault = oSectPr.Get_Header_Default();
|
||
var oFooterFirst = oSectPr.Get_Footer_First();
|
||
var oFooterEven = oSectPr.Get_Footer_Even();
|
||
var oFooterDefault = oSectPr.Get_Footer_Default();
|
||
|
||
if (oHeaderFirst && isFirst)
|
||
arrHdrFtrs.push(oHeaderFirst);
|
||
|
||
if (oHeaderEven && isEvenOdd)
|
||
arrHdrFtrs.push(oHeaderEven);
|
||
|
||
if (oHeaderDefault)
|
||
arrHdrFtrs.push(oHeaderDefault);
|
||
|
||
if (oFooterFirst && isFirst)
|
||
arrHdrFtrs.push(oFooterFirst);
|
||
|
||
if (oFooterEven && isEvenOdd)
|
||
arrHdrFtrs.push(oFooterEven);
|
||
|
||
if (oFooterDefault)
|
||
arrHdrFtrs.push(oFooterDefault);
|
||
}
|
||
|
||
if (oCurHdrFtr)
|
||
{
|
||
for (var nIndex = 0, nCount = arrHdrFtrs.length; nIndex < nCount; ++nIndex)
|
||
{
|
||
if (oCurHdrFtr === arrHdrFtrs[nIndex])
|
||
{
|
||
nCurPos = nIndex;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
HdrFtrs : arrHdrFtrs,
|
||
CurPos : nCurPos
|
||
};
|
||
};
|
||
DocumentSections.prototype.FindNextFillingForm = function(isNext, oCurHdrFtr)
|
||
{
|
||
var oInfo = this.private_GetHdrFtrsArray(oCurHdrFtr);
|
||
|
||
var arrHdrFtrs = oInfo.HdrFtrs;
|
||
var nCurPos = oInfo.CurPos;
|
||
|
||
var nCount = arrHdrFtrs.length;
|
||
|
||
var isCurrent = true;
|
||
if (-1 === nCurPos)
|
||
{
|
||
isCurrent = false;
|
||
nCurPos = isNext ? 0 : arrHdrFtrs.length - 1;
|
||
if (arrHdrFtrs[nCurPos])
|
||
oCurHdrFtr = arrHdrFtrs[nCurPos];
|
||
}
|
||
|
||
if (nCurPos >= 0 && nCurPos <= nCount - 1)
|
||
{
|
||
var oRes = oCurHdrFtr.GetContent().FindNextFillingForm(isNext, isCurrent, isCurrent);
|
||
if (oRes)
|
||
return oRes;
|
||
|
||
if (isNext)
|
||
{
|
||
for (var nIndex = nCurPos + 1; nIndex < nCount; ++nIndex)
|
||
{
|
||
oRes = arrHdrFtrs[nIndex].GetContent().FindNextFillingForm(isNext, false);
|
||
|
||
if (oRes)
|
||
return oRes;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (var nIndex = nCurPos - 1; nIndex >= 0; --nIndex)
|
||
{
|
||
oRes = arrHdrFtrs[nIndex].GetContent().FindNextFillingForm(isNext, false);
|
||
|
||
if (oRes)
|
||
return oRes;
|
||
}
|
||
}
|
||
}
|
||
|
||
return null;
|
||
};
|
||
DocumentSections.prototype.RestartSpellCheck = function()
|
||
{
|
||
var bEvenOdd = EvenAndOddHeaders;
|
||
for (let nIndex = 0, nCount = this.Elements.length; nIndex < nCount; ++nIndex)
|
||
{
|
||
var SectPr = this.Elements[nIndex].SectPr;
|
||
var bFirst = SectPr.Get_TitlePage();
|
||
|
||
if (null != SectPr.HeaderFirst && true === bFirst)
|
||
SectPr.HeaderFirst.RestartSpellCheck();
|
||
|
||
if (null != SectPr.HeaderEven && true === bEvenOdd)
|
||
SectPr.HeaderEven.RestartSpellCheck();
|
||
|
||
if (null != SectPr.HeaderDefault)
|
||
SectPr.HeaderDefault.RestartSpellCheck();
|
||
|
||
if (null != SectPr.FooterFirst && true === bFirst)
|
||
SectPr.FooterFirst.RestartSpellCheck();
|
||
|
||
if (null != SectPr.FooterEven && true === bEvenOdd)
|
||
SectPr.FooterEven.RestartSpellCheck();
|
||
|
||
if (null != SectPr.FooterDefault)
|
||
SectPr.FooterDefault.RestartSpellCheck();
|
||
}
|
||
};
|
||
DocumentSections.prototype.RemoveEmptyHdrFtrs = function()
|
||
{
|
||
for (let nIndex = 0, nCount = this.Elements.length; nIndex < nCount; ++nIndex)
|
||
{
|
||
let oSectPr = this.Elements[nIndex].SectPr;
|
||
oSectPr.RemoveEmptyHdrFtrs();
|
||
}
|
||
};
|
||
DocumentSections.prototype.CheckRunContent = function(fCheck)
|
||
{
|
||
let headers = this.GetAllHdrFtrs();
|
||
for (let index = 0, count = headers.length; index < count; ++index)
|
||
{
|
||
headers[index].GetContent().CheckRunContent(fCheck);
|
||
}
|
||
};
|
||
//------------------------------------------------------------------------------------------------------------------
|
||
// Search
|
||
//------------------------------------------------------------------------------------------------------------------
|
||
DocumentSections.prototype.Search = function(oSearchEngine)
|
||
{
|
||
var bEvenOdd = EvenAndOddHeaders;
|
||
for (var nIndex = 0, nCount = this.Elements.length; nIndex < nCount; ++nIndex)
|
||
{
|
||
var oSectPr = this.Elements[nIndex].SectPr;
|
||
var bFirst = oSectPr.Get_TitlePage();
|
||
|
||
if (oSectPr.HeaderFirst && true === bFirst)
|
||
oSectPr.HeaderFirst.Search(oSearchEngine, search_Header);
|
||
|
||
if (oSectPr.HeaderEven && true === bEvenOdd)
|
||
oSectPr.HeaderEven.Search(oSearchEngine, search_Header);
|
||
|
||
if (oSectPr.HeaderDefault)
|
||
oSectPr.HeaderDefault.Search(oSearchEngine, search_Header);
|
||
|
||
if (oSectPr.FooterFirst && true === bFirst)
|
||
oSectPr.FooterFirst.Search(oSearchEngine, search_Footer);
|
||
|
||
if (oSectPr.FooterEven && true === bEvenOdd)
|
||
oSectPr.FooterEven.Search(oSearchEngine, search_Footer);
|
||
|
||
if (oSectPr.FooterDefault)
|
||
oSectPr.FooterDefault.Search(oSearchEngine, search_Footer);
|
||
}
|
||
};
|
||
DocumentSections.prototype.GetSearchElementId = function(bNext, CurHdrFtr)
|
||
{
|
||
var HdrFtrs = [];
|
||
var CurPos = -1;
|
||
|
||
var bEvenOdd = EvenAndOddHeaders;
|
||
var Count = this.Elements.length;
|
||
for (var Index = 0; Index < Count; Index++)
|
||
{
|
||
var SectPr = this.Elements[Index].SectPr;
|
||
var bFirst = SectPr.Get_TitlePage();
|
||
|
||
if (null != SectPr.HeaderFirst && true === bFirst)
|
||
{
|
||
HdrFtrs.push(SectPr.HeaderFirst);
|
||
|
||
if (CurHdrFtr === SectPr.HeaderFirst)
|
||
CurPos = HdrFtrs.length - 1;
|
||
}
|
||
|
||
if (null != SectPr.HeaderEven && true === bEvenOdd)
|
||
{
|
||
HdrFtrs.push(SectPr.HeaderEven);
|
||
|
||
if (CurHdrFtr === SectPr.HeaderEven)
|
||
CurPos = HdrFtrs.length - 1;
|
||
}
|
||
|
||
if (null != SectPr.HeaderDefault)
|
||
{
|
||
HdrFtrs.push(SectPr.HeaderDefault);
|
||
|
||
if (CurHdrFtr === SectPr.HeaderDefault)
|
||
CurPos = HdrFtrs.length - 1;
|
||
}
|
||
|
||
if (null != SectPr.FooterFirst && true === bFirst)
|
||
{
|
||
HdrFtrs.push(SectPr.FooterFirst);
|
||
|
||
if (CurHdrFtr === SectPr.FooterFirst)
|
||
CurPos = HdrFtrs.length - 1;
|
||
}
|
||
|
||
if (null != SectPr.FooterEven && true === bEvenOdd)
|
||
{
|
||
HdrFtrs.push(SectPr.FooterEven);
|
||
|
||
if (CurHdrFtr === SectPr.FooterEven)
|
||
CurPos = HdrFtrs.length - 1;
|
||
}
|
||
|
||
if (null != SectPr.FooterDefault)
|
||
{
|
||
HdrFtrs.push(SectPr.FooterDefault);
|
||
|
||
if (CurHdrFtr === SectPr.FooterDefault)
|
||
CurPos = HdrFtrs.length - 1;
|
||
}
|
||
}
|
||
|
||
var Count = HdrFtrs.length;
|
||
|
||
var isCurrent = true;
|
||
if (-1 === CurPos)
|
||
{
|
||
isCurrent = false;
|
||
CurPos = bNext ? 0 : HdrFtrs.length - 1;
|
||
if (HdrFtrs[CurPos])
|
||
CurHdrFtr = HdrFtrs[CurPos];
|
||
}
|
||
|
||
if (CurPos >= 0 && CurPos <= HdrFtrs.length - 1)
|
||
{
|
||
var Id = CurHdrFtr.GetSearchElementId(bNext, isCurrent);
|
||
if (null != Id)
|
||
return Id;
|
||
|
||
if (true === bNext)
|
||
{
|
||
for (var Index = CurPos + 1; Index < Count; Index++)
|
||
{
|
||
Id = HdrFtrs[Index].GetSearchElementId(bNext, false);
|
||
|
||
if (null != Id)
|
||
return Id;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (var Index = CurPos - 1; Index >= 0; Index--)
|
||
{
|
||
Id = HdrFtrs[Index].GetSearchElementId(bNext, false);
|
||
|
||
if (null != Id)
|
||
return Id;
|
||
}
|
||
}
|
||
}
|
||
|
||
return null;
|
||
};
|
||
//------------------------------------------------------------------------------------------------------------------
|
||
// Private area
|
||
//------------------------------------------------------------------------------------------------------------------
|
||
/**
|
||
* Iterates through all sections and executes a callback function for each header and footer.
|
||
* @param {Function} callback
|
||
*/
|
||
DocumentSections.prototype.forEachHdrFtr = function(callback)
|
||
{
|
||
this.Update();
|
||
|
||
for (let i = 0, count = this.Elements.length; i < count; ++i)
|
||
{
|
||
let sectPr = this.Elements[i].SectPr;
|
||
|
||
if (null != sectPr.HeaderFirst)
|
||
callback.call(this, sectPr.HeaderFirst);
|
||
|
||
if (null != sectPr.HeaderDefault)
|
||
callback.call(this, sectPr.HeaderDefault);
|
||
|
||
if (null != sectPr.HeaderEven)
|
||
callback.call(this, sectPr.HeaderEven);
|
||
|
||
if (null != sectPr.FooterFirst)
|
||
callback.call(this, sectPr.FooterFirst);
|
||
|
||
if (null != sectPr.FooterDefault)
|
||
callback.call(this, sectPr.FooterDefault);
|
||
|
||
if (null != sectPr.FooterEven)
|
||
callback.call(this, sectPr.FooterEven);
|
||
}
|
||
};
|
||
DocumentSections.prototype._clear = function()
|
||
{
|
||
//console.log(`Clear all sections`);
|
||
this.Elements.length = 0;
|
||
this.paraToSection = {};
|
||
};
|
||
DocumentSections.prototype._insertSection = function(pos, sectPr, paragraph)
|
||
{
|
||
//console.log(`Insert sections at pos ${pos} paraId=${paragraph.GetId()}`);
|
||
let documentSection = new DocumentSection(sectPr, paragraph);
|
||
this.paraToSection[paragraph.GetId()] = documentSection;
|
||
this.Elements.splice(pos, 0, documentSection);
|
||
};
|
||
DocumentSections.prototype._addSection = function(sectPr, paragraph)
|
||
{
|
||
let documentSection = new DocumentSection(sectPr, paragraph);
|
||
this.paraToSection[paragraph.GetId()] = documentSection;
|
||
this.Elements.push(documentSection);
|
||
//console.log(`Add section at the end. Current count=${this.Elements.length} paraId=${paragraph.GetId()}`);
|
||
};
|
||
DocumentSections.prototype._removeSection = function(pos)
|
||
{
|
||
let docSection = this.Elements[pos];
|
||
//console.log(`Remove section at pos ${pos} paraId=${docSection.Paragraph.GetId()}`);
|
||
delete this.paraToSection[docSection.Paragraph.GetId()];
|
||
this.Elements.splice(pos, 1);
|
||
};
|
||
//------------------------------------------------------------------------------------------------------------------
|
||
|
||
/**
|
||
* Represents a document section associated with a specific paragraph.
|
||
*
|
||
* @param {AscWord.SectPr} sectPr - Section properties object containing formatting settings
|
||
* @param {AscWord.Paragraph} paragraph - The paragraph object that ends this section
|
||
* @constructor
|
||
*/
|
||
function DocumentSection(sectPr, paragraph)
|
||
{
|
||
this.SectPr = sectPr;
|
||
this.Paragraph = paragraph;
|
||
}
|
||
|
||
//--------------------------------------------------------export----------------------------------------------------
|
||
AscWord.DocumentSections = DocumentSections;
|
||
AscWord.DocumentSection = DocumentSection;
|
||
})();
|