Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/pat/modal/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ This will load the page at `/status/server1`, extract the element with id `conte

You can customise the behaviour of modals through options in the `data-pat-modal` attribute.

| Property | Default value | Values | Description | Type |
| ------------ | --------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `class` | | | A class name to be applied to the modal. | String. |
| `closing` |  "close-button" |  ["close-button", "outside"] | Show a "close" button for closing the modal, or let it be closed by clicking outside of the modal area. | One of the mutually exclusive available string values. |
| `close-text` |  "Close" |   | Specify a custom string for the close button. | String. |
| Property | Default value | Values | Description | Type |
| ---------------------- | ----------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `class` | | | A class name to be applied to the modal. | String. |
| `closing` |  "close-button" |  ["close-button", "outside"] | Show a "close" button for closing the modal, or let it be closed by clicking outside of the modal area. | One of the mutually exclusive available string values. |
| `close-text` |  "Close" |   | Specify a custom string for the close button. | String. |
| `panel-header-content` |  `:first:not(.header)` | CSS selector or "none" | Specify a CSS selector which is used for the modal header. If set to "none" no header will be added automatically and you can provide your own. | String. |
| `source` | | CSS selector | CSS selector for the injection source. If not given, the URL fragment of the ``href`` attribute from the modal trigger is used. | String. |
| `target` | `#pat-modal` | CSS selector | CSS selector for the injection target. | String. |
29 changes: 29 additions & 0 deletions src/pat/modal/index-modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Demo page</title>
<link rel="stylesheet" href="/style/common.css" type="text/css" />
<script
src="/bundle.min.js"
type="text/javascript"
charset="utf-8"
></script>
</head>
<body>
<div id="pat-modal" class="pat-modal">
<h1>Example modal</h1>
<div class="container">
<p>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
quae ab illo inventore veritatis et quasi architecto beatae
vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia
voluptas sit aspernatur aut odit aut fugit, sed quia
consequuntur magni dolores eos qui ratione voluptatem sequi
nesciunt.
</p>
</div>
</div>
</body>
</html>
11 changes: 11 additions & 0 deletions src/pat/modal/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@
Modal with a custom header</a>.
</p>

<p>
Open a
<a href="#modal-in-modal"
class="pat-modal">
Modal which contains a link to another modal.</a>.
</p>

<div id="modal-on-load" class="pat-modal">
<h1>Modal example with auto load</h1>
<article class="pat-rich">
Expand Down Expand Up @@ -171,5 +178,9 @@ <h1 class="custom-header">Custom header</h1>
</style>
</template>

<template id="modal-in-modal">
<a href="./index-modal.html#pat-modal::element" class="pat-modal" data-pat-modal="target: #pat-modal::element">Open a modal</a>
</template>

</body>
</html>
5 changes: 4 additions & 1 deletion src/pat/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ parser.addArgument("class");
parser.addArgument("closing", ["close-button"], ["close-button", "outside"], true);
parser.addArgument("close-text", "Close");
parser.addArgument("panel-header-content", ":first:not(.header)");
parser.addArgument("source", null); // If not given, the href should specify the source via a url fragment.
parser.addArgument("target", "#pat-modal");

export default Base.extend({
name: "modal",
Expand All @@ -42,7 +44,8 @@ export default Base.extend({

_init_inject1() {
const opts = {
target: "#pat-modal",
...(this.options.source && { source: this.options.source }),
target: this.options.target,
class:
"pat-modal" + (this.options["class"] ? " " + this.options["class"] : ""),
};
Expand Down
89 changes: 89 additions & 0 deletions src/pat/modal/modal.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,4 +314,93 @@ describe("pat-modal", function () {
expect(spy_destroy).toHaveBeenCalledTimes(1);
});
});

it("2.1 - Allow to open a modal in a modal", async function () {
document.body.innerHTML = `
<a class="pat-modal"
href="#modal-source"
>open modal 1</a>
<template id="modal-source">
<a class="pat-modal"
href="#modal-modal-source"
data-pat-modal="
target: #pat-modal::element;
"
>Open another modal</a>
</template>
<template id="modal-modal-source">
<div class="pat-modal" id="pat-modal">
modal in modal.
</div>
</template>
`;
const el = document.querySelector(".pat-modal");
new pattern(el);
await utils.timeout(1); // wait a tick for async to settle.

el.click();
await utils.timeout(1); // wait a tick for async to settle.

expect(document.querySelectorAll("#pat-modal").length).toBe(1);

const trigger_sub = document.querySelector("#pat-modal .pat-modal");
expect(trigger_sub).toBeTruthy();

trigger_sub.click();
await utils.timeout(1); // wait a tick for async to settle.
expect(document.querySelectorAll("#pat-modal").length).toBe(1);
expect(document.querySelector("#pat-modal").textContent).toMatch(
/modal in modal\./
);
});

it("2.2 - Allow to open a modal in a modal via ajax", async function () {
document.body.innerHTML = `
<a class="pat-modal"
href="#modal-source"
>open modal 1</a>
<template id="modal-source">
<a class="pat-modal"
href="./modal.html"
data-pat-modal="
source: #pat-modal::element;
target: #pat-modal::element;
"
>Open another modal</a>
</template>
`;

jest.spyOn($, "ajax").mockImplementation(() => deferred);
answer(`
<html>
<body>
<main>
<div class="pat-modal" id="pat-modal">
modal in modal.
</div>
</main>
</body>
</html>
`);

const el = document.querySelector(".pat-modal");
new pattern(el);
await utils.timeout(1); // wait a tick for async to settle.

el.click();
await utils.timeout(1); // wait a tick for async to settle.

expect(document.querySelectorAll("#pat-modal").length).toBe(1);

const trigger_sub = document.querySelector("#pat-modal .pat-modal");
expect(trigger_sub).toBeTruthy();

trigger_sub.click();
await utils.timeout(1); // wait a tick for async to settle.

expect(document.querySelectorAll("#pat-modal").length).toBe(1);
expect(document.querySelector("#pat-modal").textContent).toMatch(
/modal in modal\./
);
});
});