Merge pull request #2876 from Jwaegebaert/collapsibleHeadingsIssue

Solve collapsible heading issues with naming and order
This commit is contained in:
Hugo Bernier 2022-07-27 20:49:09 -07:00 committed by GitHub
commit 26bd57d378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 58 deletions

View File

@ -28,7 +28,7 @@ Version|Date|Comments
1.2|May, 2022|SPFx Upgraded to 1.14.0
1.3|June 9, 2022|Updated React package from `^16.14.0` to `16.13.1`
1.4|June 29, 2022|Adds the capability to find collapsible section headers and insert them into the navigation
1.5|July 2, 2022|Fixes heading links containing a lot of spaces between words and caps heading length at 128 charsgu
1.5|July 19, 2022|Bug fixes
## Minimal Path to Awesome

View File

@ -9,7 +9,7 @@
"This web part fetches all the automatically added Header anchor tags in a SharePoint page and displays them in a Navigation component."
],
"creationDateTime": "2019-09-05",
"updateDateTime": "2022-07-02",
"updateDateTime": "2022-07-19",
"products": [
"SharePoint"
],

View File

@ -37,13 +37,38 @@ export class SPService {
return anchorUrl;
}
/**
* Nests a new nav link within the nav links tree
* @param currentLinks current nav links
* @param newLink the new nav link to be added to the structure
* @param order place order of the new link
* @param depth sequence depth
* @returns navLinks
*/
public static navLinkBuilder(currentLinks: INavLink[], newLink: INavLink, order: number, depth: number = 0): INavLink[] {
const lastIndex = currentLinks.length - 1;
if (currentLinks[lastIndex].links.length === 0 || order === depth) {
if (depth === 0) {
currentLinks.push(newLink);
} else {
currentLinks[lastIndex].links.push(newLink);
}
} else {
depth++;
currentLinks[lastIndex].links.concat(this.navLinkBuilder(currentLinks[lastIndex].links, newLink, order, depth));
}
return currentLinks;
}
/**
* Returns the Anchor Links for Nav element
* @param context Web part context
* @returns anchorLinks
*/
public static async GetAnchorLinks(context: WebPartContext) {
const anchorLinks: INavLink[] = [];
let anchorLinks: INavLink[] = [];
try {
/* Page ID on which the web part is added */
@ -55,82 +80,51 @@ export class SPService {
const canvasContent1 = jsonData.CanvasContent1;
const canvasContent1JSON: any[] = JSON.parse(canvasContent1);
/* Initialize variables to be used for sorting and adding the Navigation links */
let headingIndex = 0;
let subHeadingIndex = -1;
let prevHeadingOrder = 0;
this.allUrls = [];
/* Traverse through all the Text web parts in the page */
canvasContent1JSON.map((webPart) => {
if (webPart.zoneGroupMetadata) {
const headingValue = webPart.zoneGroupMetadata.displayName;
const anchorUrl = this.GetAnchorUrl(headingValue);
if (webPart.zoneGroupMetadata && webPart.zoneGroupMetadata.type === 1) {
const headingIsEmpty: boolean = webPart.zoneGroupMetadata.displayName === '';
const headingValue: string = headingIsEmpty ? 'Empty Heading' : webPart.zoneGroupMetadata.displayName ;
const anchorUrl: string = this.GetAnchorUrl(headingValue);
this.allUrls.push(anchorUrl);
/* Add link to Nav element */
anchorLinks.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: webPart.zoneGroupMetadata.isExpanded });
// Limitation! This will break with headings containing the same name
if (anchorLinks.filter(x => x.name === headingValue).length === 0) {
// Add link to nav element
anchorLinks.push({ name: headingValue, key: anchorUrl, url: !headingIsEmpty && anchorUrl, links: [], isExpanded: webPart.zoneGroupMetadata.isExpanded });
}
}
if (webPart.innerHTML) {
const HTMLString: string = webPart.innerHTML;
const hasCollapsableHeader: boolean = webPart.zoneGroupMetadata &&
webPart.zoneGroupMetadata.type === 1 &&
( anchorLinks.filter(x => x.name === webPart.zoneGroupMetadata.displayName).length === 1 ||
webPart.zoneGroupMetadata.displayName === '' );
const htmlObject = document.createElement('div');
const htmlObject: HTMLDivElement = document.createElement('div');
htmlObject.innerHTML = HTMLString;
const headers = htmlObject.querySelectorAll('h1, h2, h3, h4');
const headers: NodeListOf<Element> = htmlObject.querySelectorAll('h1, h2, h3, h4');
headers.forEach(header => {
const headingValue = header.textContent;
let headingOrder = parseInt(header.tagName.substring(1));
const headingValue: string = header.textContent;
let headingOrder: number = parseInt(header.tagName.substring(1));
// -2 because the text webpart heading 1 uses a h2 element
headingOrder -= 2;
if (webPart.zoneGroupMetadata) {
if (hasCollapsableHeader) {
headingOrder++;
}
const anchorUrl = this.GetAnchorUrl(headingValue);
const anchorUrl: string = this.GetAnchorUrl(headingValue);
this.allUrls.push(anchorUrl);
/* Add links to Nav element */
if (anchorLinks.length === 0) {
anchorLinks.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
} else {
if (headingOrder <= prevHeadingOrder) {
/* Adding or Promoting links */
switch (headingOrder) {
case 2:
anchorLinks.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
headingIndex++;
subHeadingIndex = -1;
break;
case 4:
if (subHeadingIndex > -1) {
anchorLinks[headingIndex].links[subHeadingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
} else {
anchorLinks[headingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
}
break;
default:
anchorLinks[headingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
subHeadingIndex = anchorLinks[headingIndex].links.length - 1;
break;
}
} else {
/* Making sub links */
if (headingOrder === 3) {
anchorLinks[headingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
subHeadingIndex = anchorLinks[headingIndex].links.length - 1;
} else {
if (subHeadingIndex > -1) {
anchorLinks[headingIndex].links[subHeadingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
} else {
anchorLinks[headingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
}
}
}
}
prevHeadingOrder = headingOrder;
// Add link to nav element
const newNavLink: INavLink = { name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true };
anchorLinks = this.navLinkBuilder(anchorLinks, newNavLink, headingOrder, hasCollapsableHeader ? 1 : 0);
});
}
});