UNPKG

gd-sprest-bs

Version:

SharePoint JavaScript, TypeScript and Web Components designed using the Bootstrap framework.

291 lines (248 loc) • 11 kB
import { Components } from "gd-bs"; import { WebPart } from "../base"; import { IWebPartInfo } from "../base/types"; import { IWPTabs, IWPTabsProps } from "./types"; /** * Web Part Tab Types */ export enum WPTabTypes { Pillars = 1, Tabs = 2 } /** * Web Part Tabs */ export const WPTabs = (props: IWPTabsProps): IWPTabs => { let _elWebPart: HTMLDivElement = null; let _isContentZone: boolean = false; let _nav: Components.INav = null; // Method to get the webparts let getWebParts = (wpInfo: IWebPartInfo) => { let wps = []; // Get the webpart element and zone let elWebPart = document.querySelector("div[webpartid='" + wpInfo.cfg.WebPartId + "']") as HTMLDivElement; let elWebPartZone: HTMLElement = elWebPart ? getWebPartZone(elWebPart) : null; if (elWebPart && elWebPartZone) { // Add a class name to the webpart zone elWebPartZone.className += " wp-tabs" // Remove the empty elements removeEmptyElements(elWebPartZone); // Parse the webparts in this zone let webparts = elWebPartZone.querySelectorAll(".ms-webpartzone-cell[id^='MSOZoneCell_WebPart']"); for (let i = 0; i < webparts.length; i++) { let webpart = webparts[i] as HTMLDivElement; // See if it's this webpart if (webpart.querySelector("div[webpartid='" + wpInfo.cfg.WebPartId + "']")) { // Save a reference _elWebPart = webpart; // Set the class _elWebPart.className += " wp-tab"; // Skip this webpart continue; } // Skip hidden webparts let wpTitle: string = ((webpart.querySelector(".ms-webpart-titleText") || {}) as HTMLDivElement).innerText || ""; let isHidden = webpart.firstElementChild && webpart.firstElementChild.classList.contains("ms-hide"); isHidden = isHidden || /^\(Hidden\)/.test(wpTitle); if (isHidden) { continue; } // See if this is within a content zone if (_isContentZone) { // Get the parent webpart box while (webpart.parentNode) { // See if this is the webpart box element if (webpart.classList.contains("ms-rte-wpbox")) { // Find the div containing the webpart id let wpElement = webpart.querySelector("div[webpartid*='-']"); if (wpElement) { // Set the webpart id attribute webpart.setAttribute("wpid", wpElement.getAttribute("webpartid")); } // Add this webpart and break from the loop wps.push(webpart); break; } // Check the parent element webpart = webpart.parentNode as HTMLDivElement; } } else { // Add the webpart wps.push(webpart); } } } // Return the webparts return wps; } // Method to get the webpart zone let getWebPartZone = (el: HTMLDivElement) => { // Ensure the element exists if (el && el.classList) { // See if this is the webpart zone element if (el.classList.contains("ms-webpart-zone")) { // Return it return el; } // See if this is the inner page zone if (el.classList.contains("ms-rte-layoutszone-inner") || el.classList.contains("ms-rtestate-field")) { // Set the flag _isContentZone = true; // Return it return el; } // Check the parent element return getWebPartZone(el.parentNode as HTMLDivElement); } // Return nothing return null; } // Method to remove empty paragraph or new lines for webparts w/in content zones let removeEmptyElements = (elWebPartZone: HTMLElement) => { let elChildren: Array<HTMLElement> = []; // See if this webpart is within a layout zone or rich html field if (elWebPartZone.className.indexOf("ms-rte-layoutszone-inner") >= 0 || elWebPartZone.className.indexOf("ms-rtestate-field") >= 0) { // Set the children elements elChildren = elWebPartZone.children as any; } // Parse the children elements for (let i = 0; i < elChildren.length; i++) { let elChild = elWebPartZone.children[i]; // See if the last element is a new line let elBreakLine = elChild.children[elChild.children.length - 1]; if (elBreakLine && elBreakLine.nodeName == "BR") { // Remove the element elChild.removeChild(elBreakLine); } // See if this is an empty paragraph tag if (elChild.nodeName == "P") { let removeElement = false; let content = elChild.innerHTML.trim(); // See if this is an empty element if (content.length == 0) { // Set the flag removeElement = true; } // Else, see if this is a line break else if (content.length == 1 && content.charCodeAt(0) == 8203) { // Set the flag removeElement = true; } // Remove the element removeElement ? elWebPartZone.removeChild(elChild) : null; } } } // Method to update the visibility of the webparts let updateWebParts = (tab?: Components.INavLinkProps, ev?: Event) => { let selectedTabId = 0; // See if the tab exists if (tab) { // Parse the webparts for (let i = 0; i < _webparts.length; i++) { // Get the webpart let wpTitle = _webparts[i].querySelector(".ms-webpart-titleText") as HTMLDivElement; if (wpTitle && wpTitle.innerText == tab.title) { // Update the selected tab id selectedTabId = i; break; } } } // Else, default the selected tab to the first visible webpart else { // Parse the webparts for (selectedTabId = 0; selectedTabId < _webparts.length; selectedTabId++) { // Break if this webpart has a title if (_webparts[selectedTabId].querySelector(".ms-webpart-titleText")) { break; } } } // Parse the webparts for (let i = 0; i < _webparts.length; i++) { let wp = _webparts[i] as HTMLElement; // Determine the query selector let selector = wp.id ? "#" + wp.id : ".ms-rte-wpbox[wpid='" + wp.getAttribute("wpid") + "']"; // Get the webpart let webpart = document.querySelector(selector) as HTMLDivElement; if (webpart) { // See if we are displaying this webpart if (i == selectedTabId) { // Display the webpart webpart.className = webpart.className.replace(" is-hidden", ""); // See if this tab contains a calendar webpart if (webpart.querySelector(".ms-acal-rootdiv")) { let ev = null; // Create the resize event try { ev = new Event("resize"); } // This will fail for IE catch (e) { // Create the event ev = document.createEvent("Event"); ev.initEvent("resize", true, false); } finally { // Call the window resize event to fix the events ev ? window.dispatchEvent(ev) : null; } } // Call the click if it exists props.onClick ? props.onClick(webpart) : null; } // Ensure the webpart is hidden else if (webpart.classList.contains("is-hidden") == false) { // Hide the webpart webpart.classList.add("is-hidden"); } } } } /** * Main */ let _webparts = []; // Return the webpart let wp = WebPart({ className: props.className, cfgElementId: props.cfgElementId, editForm: props.editForm, elementId: props.elementId, helpProps: props.helpProps, onPostRender: props.onPostRender, onRenderEdit: props.onRenderEdit, wpClassName: ["wp-tabs-main", props.wpClassName || ""].join(' ').trim(), onRenderDisplay: (wpInfo: IWebPartInfo) => { // Set the webparts _webparts = getWebParts(wpInfo); // Parse the webparts let items: Array<Components.INavLinkProps> = []; for (let i = 0; i < _webparts.length; i++) { // Ensure a title exists let wpTitle = _webparts[i].querySelector(".ms-webpart-titleText") as HTMLDivElement; if (wpTitle) { // Add the tab items.push({ isActive: i == 0, title: wpTitle.innerText, onClick: updateWebParts }); } } // Render the navigation _nav = Components.Nav({ className: props.className, el: wpInfo.el, isPills: props.type == WPTabTypes.Pillars, isTabs: true, items }); // Update the webparts updateWebParts(); // See if a custom event exists props.onRenderDisplay ? props.onRenderDisplay(wpInfo) : null; } }) as IWPTabs; // Add the custom methods wp.getNav = () => { return _nav; } wp.getTabs = () => { return _webparts as any; }; // Return the webpart return wp; }