Skip to content

Commit

Permalink
Feat: shadow dom, fixes issue #889 (#890)
Browse files Browse the repository at this point in the history
* feat: add `shadowRoot` option for grids inside a shadow DOM tree

* add shadow DOM example
  • Loading branch information
megatron0000 authored Oct 30, 2023
1 parent 3102983 commit 548355e
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 4 deletions.
111 changes: 111 additions & 0 deletions examples/example1a-shadow-dom.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="shortcut icon" type="image/ico" href="favicon.ico" />
<title>SlickGrid example 1a: Basic grid inside a shadow DOM</title>
<link rel="stylesheet" href="../dist/styles/css/example-demo.css" type="text/css"/>
</head>
<body>
<table width="100%">
<tr>
<td valign="top" width="50%">
<div id="host"></div>
</td>
<td valign="top">
<div>
<h2>
<a href="/examples/index.html" style="text-decoration: none; font-size: 22px">&#x2302;</a>
Demonstrates:
</h2>
</div>
<ul>
<li>how to load a grid inside a shadow DOM tree</li>
</ul>
<h2>View Source:</h2>
<ul>
<li><A href="https://github.com/6pac/SlickGrid/blob/master/examples/example1a-shadow-dom.html" target="_sourcewindow"> View the source for this example on Github</a></li>
</ul>
</td>
</tr>
</table>

<script src="https://cdn.jsdelivr.net/npm/sortablejs/Sortable.min.js"></script>
<script src="sortable-cdn-fallback.js"></script>

<script src="../dist/browser/slick.core.js"></script>
<script src="../dist/browser/slick.interactions.js"></script>
<script src="../dist/browser/slick.grid.js"></script>

<script>
var grid;
var columns = [
{id: "title", name: "Title", field: "title"},
{id: "duration", name: "Duration", field: "duration"},
{id: "%", name: "% Complete", field: "percentComplete", width: 90 },
{id: "start", name: "Start", field: "start"},
{id: "finish", name: "Finish", field: "finish"},
{id: "effort-driven", name: "Effort Driven", field: "effortDriven", width: 90 }
];

var data = [];
for (var i = 0; i < 500; i++) {
data[i] = {
title: "Task " + i,
duration: "5 days",
percentComplete: Math.round(Math.random() * 100),
start: "01/01/2009",
finish: "01/05/2009",
effortDriven: (i % 5 == 0)
};
}

/**
* Build the shadow DOM. In this example, it will
* have just a div for the grid, and a <link>
* for the Alpine style.
*
* Notice that the <link> tag must be placed inside
* the shadow DOM tree, it cannot be placed on the <head>
* tag because the shadow DOM is unaffected by external
* styles
*/

var host = document.querySelector("#host");
var shadow = host.attachShadow({ mode: "open" });
var gridContainer = document.createElement("div");
gridContainer.style.width = "600px";
gridContainer.style.height = "500px";
gridContainer.classList.add("slick-container");
shadow.appendChild(gridContainer);

var linkElement = document.createElement("link");
linkElement.type = "text/css";
linkElement.rel = "stylesheet";
linkElement.href = "../dist/styles/css/slick-alpine-theme.css";
shadow.appendChild(linkElement);

/**
* Since the grid is inside a shadow DOM tree, we have
* to pass the root of this tree to the option `shadowRoot`
*/

var options = {
enableCellNavigation: true,
enableColumnReorder: false,
shadowRoot: shadow
};

/**
* Since the <link> tag was loaded dynamically, it will take
* some time to download the referenced css file. We must
* wait for the style to finish loading, otherwise Slick.Grid
* will break
*/

linkElement.addEventListener("load", () => {
grid = new Slick.Grid(gridContainer, data, columns, options);
})
</script>
</body>
</html>
1 change: 1 addition & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ <h2>Basic Use</h2>
<div>
<ul>
<li><a href="./example1-simple.html">Basic use with minimal configuration</a></li>
<li><a href="./example1a-shadow-dom.html">Basic use within a shadow DOM tree</a></li>
<li><a href="./example2-formatters.html">Adding some formatting</a></li>
<li><a href="./example7-events.html">Handling events and context menu</a></li>
<li><a href="./example14-highlighting.html">Highlighting and flashing cells</a></li>
Expand Down
3 changes: 3 additions & 0 deletions src/models/gridOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ export interface GridOption<C extends BaseColumn = BaseColumn> {
/** Defaults to true, which leads to render a separate span for the number and styles it with css class <i>slick-sort-indicator-numbered</i> */
sortColNumberInSeparateSpan?: boolean;

/** Defaults to undefined. If we are inside a shadow DOM tree, this must be the shadow root of the tree */
shadowRoot?: ShadowRoot

/**
* Defaults to false, which leads to suppress the cell from becoming active when cell as an editor and is clicked.
* This flag was originally enabled to work properly with (Row Selections & Inline Editors) features but it caused problem when also used with CellExternalCopyManager,
Expand Down
8 changes: 4 additions & 4 deletions src/slick.grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
maxSupportedCssHeight: 1000000000,
sanitizer: undefined, // sanitize function, built in basic sanitizer is: Slick.RegexSanitizer(dirtyHtml)
logSanitizedHtml: false, // log to console when sanitised - recommend true for testing of dev and production
mixinDefaults: true
mixinDefaults: true,
shadowRoot: undefined
};

protected _columnDefaults = {
Expand Down Expand Up @@ -2303,8 +2304,7 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
protected createCssRules() {
this._style = document.createElement('style');
this._style.nonce = 'random-string';
document.head.appendChild(this._style);

(this._options.shadowRoot || document.head).appendChild(this._style);
const sheet = this._style.sheet;
if (sheet) {
const rowHeight = (this._options.rowHeight! - this.cellHeightDiff);
Expand All @@ -2329,7 +2329,7 @@ export class SlickGrid<TData = any, C extends Column<TData> = Column<TData>, O e
protected getColumnCssRules(idx: number) {
let i: number;
if (!this.stylesheet) {
const sheets: any = document.styleSheets;
const sheets: any = (this._options.shadowRoot || document).styleSheets;
for (i = 0; i < sheets.length; i++) {
if ((sheets[i].ownerNode || sheets[i].owningElement) === this._style) {
this.stylesheet = sheets[i];
Expand Down

0 comments on commit 548355e

Please sign in to comment.