diff --git a/CHANGES.md b/CHANGES.md
index 516ea4540..0a5860873 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -14,6 +14,8 @@
- pat-slideshow-builder
- simplePlaceholder from jquery-ext.
- IE11 is not supported by default anymore. There is a ``polyfills`` bundle, which adds IE11 support for the time being.
+- pat tooltip: Remove undocumented "souce: content-html" parameter.
+- pat tooltip: Remove undocumented "souce: auto" parameter. This parameter should not be used as it is not explicit enough and would lead to unintuitive behavior.
### Features
diff --git a/src/pat/tooltip/tooltip.js b/src/pat/tooltip/tooltip.js
index 1fd19001a..471eb433d 100644
--- a/src/pat/tooltip/tooltip.js
+++ b/src/pat/tooltip/tooltip.js
@@ -30,13 +30,7 @@ const all_positions = [
parser.addArgument("position-list", [], all_positions, true);
parser.addArgument("position-policy", "auto", ["auto", "force"]);
parser.addArgument("trigger", "click", ["click", "hover"]);
-parser.addArgument("source", "title", [
- "auto",
- "ajax",
- "content",
- "content-html",
- "title",
-]);
+parser.addArgument("source", "title", ["ajax", "content", "title"]);
parser.addArgument("ajax-data-type", "html", ["html", "markdown"]);
parser.addArgument("closing", "auto", ["auto", "sticky", "close-button"]);
parser.addArgument("delay");
@@ -44,8 +38,6 @@ parser.addArgument("mark-inactive", true);
parser.addArgument("class");
parser.addArgument("target", "body");
-// parser.addArgument("height", "auto", ["auto", "max"]);
-
export default Base.extend({
name: "tooltip",
trigger: ".pat-tooltip, .pat-tooltip-ng",
@@ -94,7 +86,10 @@ export default Base.extend({
el.classList.add("inactive");
}
- if (this.options.trigger === "click") {
+ if (
+ this.options.trigger === "click" &&
+ this.options.source === "ajax"
+ ) {
// prevent default action for "click" and "mouseenter click"
el.addEventListener("click", (event) => {
event.preventDefault();
@@ -173,26 +168,15 @@ export default Base.extend({
},
source: () => {
- if (opts.source === "auto") {
- const href = this.el.getAttribute("href");
- if (typeof href !== "string") {
- log.error(
- `href must be specified if 'source' is set to 'auto'`
- );
- return;
- }
- if (href.indexOf("#") === 0) {
- opts.source = "content";
- } else {
- opts.source = "ajax";
- }
- }
let content;
if (opts.source === "title") {
// Tooltip content from title attribute
content = this.el.getAttribute("title");
- }
- if (["content", "ajax"].includes(opts.source)) {
+ } else if (opts.source === "content") {
+ // Tooltiop content from trigger child content.
+ content = this.el.innerHTML;
+ tippy_options.allowHTML = true;
+ } else if (opts.source === "ajax") {
// Tooltiop content from AJAX request.
content = document.createElement("progress");
tippy_options.allowHTML = true;
@@ -276,7 +260,7 @@ export default Base.extend({
this.tippy.setProps({ trigger: "click" });
}
- if (["content", "ajax"].includes(this.options.source)) {
+ if (this.options.source === "ajax") {
await this._getContent();
}
@@ -321,7 +305,7 @@ export default Base.extend({
this.tippy.setProps({ trigger: "mouseenter focus" });
}
- if (["content", "ajax"].includes(this.options.source)) {
+ if (this.options.source === "ajax") {
this.tippy.setContent(document.createElement("progress"));
this.ajax_state.canFetch = true;
}
@@ -334,6 +318,7 @@ export default Base.extend({
const { url, selector, modifier } = this.get_url_parts(
this.el.getAttribute("href")
);
+ let content;
if (url) {
// Tooltip from remote page.
this.ajax_state = {
@@ -347,21 +332,18 @@ export default Base.extend({
// TODO: use pat-inject, once it supports async
const response = await fetch(url);
const text = await response.text();
- const content = handler(text, url, selector, modifier);
- this.tippy.setContent(content);
+ content = handler(text, url, selector, modifier);
} catch (e) {
log.error(`Error on ajax request ${e}`);
}
this.ajax_state.isFetching = false;
} else if (selector) {
// Tooltip content from current DOM tree.
- const content = document.querySelector(selector);
- if (!content) {
- return;
- }
- this.tippy.setContent(content[modifier]);
- } else {
- this.tippy.setContent(this.el.innerHTML);
+ content = document.querySelector(selector);
+ content = content ? content[modifier] : undefined;
+ }
+ if (content) {
+ this.tippy.setContent(content);
}
},
diff --git a/src/pat/tooltip/tooltip.test.js b/src/pat/tooltip/tooltip.test.js
index 7fbb142d6..3d5d901ea 100644
--- a/src/pat/tooltip/tooltip.test.js
+++ b/src/pat/tooltip/tooltip.test.js
@@ -834,11 +834,11 @@ describe("pat-tooltip", () => {
});
});
describe(`if the 'source' parameter is 'content'`, () => {
- it("and the href-hashtag reference cannot be found, it will show the content of the link", async (done) => {
+ it("it will show the content of the link", async (done) => {
const content = "Local content";
const $el = testutils.createTooltip({
data: "source: content; trigger: hover",
- href: "#",
+ href: "#lab",
content: content,
});
const instance = new pattern($el);
@@ -855,29 +855,6 @@ describe("pat-tooltip", () => {
document.querySelector(".tippy-box").textContent
).toBe(content);
- done();
- });
- it("and the href-reference can be found, it will show that in the modal", async (done) => {
- const content = "Local content";
- const $el = testutils.createTooltip({
- data: "source: content; trigger: hover",
- href: "#tooltip-source",
- });
- testutils.createTooltipSource();
- const instance = new pattern($el);
- const spy_show = spyOn(
- instance.tippy.props,
- "onShow"
- ).and.callThrough();
-
- testutils.mouseenter($el);
- await utils.timeout(1);
-
- expect(spy_show).toHaveBeenCalled();
- expect(
- document.querySelector(".tippy-box strong").textContent
- ).toBe(content);
-
done();
});
});
@@ -945,66 +922,76 @@ describe("pat-tooltip", () => {
done();
});
});
- describe(`if the "source" parameter is "auto"`, () => {
- describe(`if the "href" points to a document fragment`, () => {
- it(`will revert to "content"`, (done) => {
- const $el = testutils.createTooltip({
- data: "source: auto",
- href: "#tooltip-source",
- });
- testutils.createTooltipSource();
- const instance = new pattern($el);
-
- // options.source is changed to "content"
- expect(instance.options.source).toEqual("content");
+ });
- done();
- });
+ describe("test the different `source` parameters", () => {
+ it("source: title will use the title attribute", async (done) => {
+ const $el = testutils.createTooltip({
+ data: "source: title; trigger: click",
});
- describe(`if the "href" points to an external URL`, () => {
- it(`will revert to "ajax"`, (done) => {
- const $el = testutils.createTooltip({
- data: "source: auto",
- href: "/tests/content.html#content",
- });
- const instance = new pattern($el);
+ const title = $el[0].title;
+ const instance = new pattern($el);
- // options.source is changed to "ajax"
- expect(instance.options.source).toEqual("ajax");
+ testutils.click($el);
+ await utils.timeout(1);
- done();
- });
+ const expected = document.querySelector(
+ ".tooltip-container .tippy-content"
+ ).textContent;
+ expect(expected).toBe(title);
+
+ done();
+ });
+
+ it("source: content use the content of the link", async (done) => {
+ const content = "Local content";
+ const $el = testutils.createTooltip({
+ data: "source: content; trigger: click",
+ content: content,
});
+ const instance = new pattern($el);
+
+ testutils.click($el);
+ await utils.timeout(1);
+
+ expect(document.querySelector(".tippy-box").textContent).toBe(
+ content
+ );
+
+ done();
});
- });
- describe(`if the 'source' parameter is 'ajax'`, () => {
- it("the default click action is prevented", (done) => {
- global.fetch = jest.fn().mockImplementation(mockFetch());
+ it("source: ajax and an external url will fetch its contents via ajax", async (done) => {
+ global.fetch = jest
+ .fn()
+ .mockImplementation(
+ mockFetch("External content fetched via an HTTP request.")
+ );
const $el = testutils.createTooltip({
data: "source: ajax",
- href: "tests/content.html#content",
+ href: "http://test.com",
});
const instance = new pattern($el);
- const click = new Event("click");
-
- const call_order = [];
- spyOn(click, "preventDefault").and.callFake(() =>
- call_order.push("preventDefault")
- );
- spyOn(instance, "_getContent").and.callFake(() =>
- call_order.push("_getContent")
- );
+ const spy_content = spyOn(
+ instance,
+ "_getContent"
+ ).and.callThrough();
+ const spy_show = spyOn(
+ instance.tippy.props,
+ "onShow"
+ ).and.callThrough();
- $el[0].dispatchEvent(click);
- $el[0].dispatchEvent(click);
- $el[0].dispatchEvent(click);
+ testutils.click($el);
+ await utils.timeout(1); // wait a tick for async fetch
- //expect(spy_ajax).toHaveBeenCalledBefore(spy_prevented);
- expect(call_order.indexOf("_getContent")).toEqual(0);
- expect(call_order.includes("preventDefault")).toBeTruthy();
+ expect(global.fetch).toHaveBeenCalled();
+ expect(spy_content).toHaveBeenCalled();
+ expect(spy_show).toHaveBeenCalled();
+ expect(
+ document.querySelector(".tippy-box .tippy-content").textContent
+ ).toBe("External content fetched via an HTTP request.");
global.fetch.mockClear();
delete global.fetch;
@@ -1012,7 +999,7 @@ describe("pat-tooltip", () => {
done();
});
- it("will fetch its contents via ajax", async (done) => {
+ it("source: ajax with a local selector will not use ajax but get the contents from the current DOM", async (done) => {
global.fetch = jest
.fn()
.mockImplementation(
@@ -1021,11 +1008,14 @@ describe("pat-tooltip", () => {
const $el = testutils.createTooltip({
data: "source: ajax",
- href: "http://test.com",
+ href: "#lab",
});
const instance = new pattern($el);
- const spy_ajax = spyOn(instance, "_getContent").and.callThrough();
+ const spy_content = spyOn(
+ instance,
+ "_getContent"
+ ).and.callThrough();
const spy_show = spyOn(
instance.tippy.props,
"onShow"
@@ -1034,11 +1024,47 @@ describe("pat-tooltip", () => {
testutils.click($el);
await utils.timeout(1); // wait a tick for async fetch
- expect(spy_ajax).toHaveBeenCalled();
+ expect(global.fetch).not.toHaveBeenCalled();
+ expect(spy_content).toHaveBeenCalled();
expect(spy_show).toHaveBeenCalled();
expect(
- document.querySelector(".tippy-box .tippy-content").textContent
- ).toBe("External content fetched via an HTTP request.");
+ document.querySelector(".tippy-box .tippy-content .pat-tooltip")
+ ).toBeTruthy();
+
+ global.fetch.mockClear();
+ delete global.fetch;
+
+ done();
+ });
+ });
+
+ describe(`if the 'source' parameter is 'ajax'`, () => {
+ it("the default click action is prevented", (done) => {
+ global.fetch = jest.fn().mockImplementation(mockFetch());
+
+ const $el = testutils.createTooltip({
+ data: "source: ajax",
+ href: "tests/content.html#content",
+ });
+ const instance = new pattern($el);
+ const click = new Event("click");
+
+ const call_order = [];
+
+ spyOn(click, "preventDefault").and.callFake(() =>
+ call_order.push("preventDefault")
+ );
+ spyOn(instance, "_getContent").and.callFake(() =>
+ call_order.push("_getContent")
+ );
+
+ $el[0].dispatchEvent(click);
+ $el[0].dispatchEvent(click);
+ $el[0].dispatchEvent(click);
+
+ //expect(spy_ajax).toHaveBeenCalledBefore(spy_prevented);
+ expect(call_order.indexOf("_getContent")).toEqual(0);
+ expect(call_order.includes("preventDefault")).toBeTruthy();
global.fetch.mockClear();
delete global.fetch;
@@ -1262,98 +1288,98 @@ this will be extracted.
done();
});
});
+ });
- describe("patterns-injected events", () => {
- it("it throws the ``patterns-injected`` event", async (done) => {
- global.fetch = jest
- .fn()
- .mockImplementation(mockFetch("External content"));
+ describe("patterns-injected events", () => {
+ it("it throws the ``patterns-injected`` event", async (done) => {
+ global.fetch = jest
+ .fn()
+ .mockImplementation(mockFetch("External content"));
- let called = false;
- $(document.body).on("patterns-injected", () => {
- called = true;
- });
+ let called = false;
+ $(document.body).on("patterns-injected", () => {
+ called = true;
+ });
- const $el = testutils.createTooltip({
- data: "source: ajax; trigger: click",
- href: "http://test.com",
- });
- const instance = new pattern($el);
+ const $el = testutils.createTooltip({
+ data: "source: ajax; trigger: click",
+ href: "http://test.com",
+ });
+ const instance = new pattern($el);
- testutils.click($el);
- await utils.timeout(1); // wait a tick for async fetch
+ testutils.click($el);
+ await utils.timeout(1); // wait a tick for async fetch
- expect(called).toBeTruthy();
+ expect(called).toBeTruthy();
- global.fetch.mockClear();
- delete global.fetch;
+ global.fetch.mockClear();
+ delete global.fetch;
- done();
- });
+ done();
+ });
- it.skip("triggers event handlers in other patterns", async (done) => {
- // TODO: fix tests
- global.fetch = jest
- .fn()
- .mockImplementation(
- mockFetch(``)
- );
+ it.skip("triggers event handlers in other patterns", async (done) => {
+ // TODO: fix tests
+ global.fetch = jest
+ .fn()
+ .mockImplementation(
+ mockFetch(``)
+ );
- const form = document.createElement("form");
- form.setAttribute("action", "test.html");
- form.setAttribute("class", "pat-autosubmit");
- document.body.appendChild(form);
+ const form = document.createElement("form");
+ form.setAttribute("action", "test.html");
+ form.setAttribute("class", "pat-autosubmit");
+ document.body.appendChild(form);
- const $el = testutils.createTooltip({
- data: "source: ajax; trigger: click; target: form",
- href: "http://test.com",
- });
- const instance = new pattern($el);
+ const $el = testutils.createTooltip({
+ data: "source: ajax; trigger: click; target: form",
+ href: "http://test.com",
+ });
+ const instance = new pattern($el);
- const instance2 = new autosubmit($(form));
- const spy_handler1 = spyOn(
- instance2,
- "refreshListeners"
- ).and.callThrough();
- const spy_handler2 = spyOn(
- instance2,
- "onInputChange"
- ).and.callThrough();
+ const instance2 = new autosubmit($(form));
+ const spy_handler1 = spyOn(
+ instance2,
+ "refreshListeners"
+ ).and.callThrough();
+ const spy_handler2 = spyOn(
+ instance2,
+ "onInputChange"
+ ).and.callThrough();
- testutils.click($el);
- await utils.timeout(1); // wait a tick for async fetch
+ testutils.click($el);
+ await utils.timeout(1); // wait a tick for async fetch
- document.body.querySelector("input[name=test]").click();
- await utils.timeout(1); // wait a tick for async fetch
+ document.body.querySelector("input[name=test]").click();
+ await utils.timeout(1); // wait a tick for async fetch
- // TODO: check why this isn't called
- // manual tests show expected behavior.
- expect(spy_handler1).toHaveBeenCalled();
- expect(spy_handler2).toHaveBeenCalled();
+ // TODO: check why this isn't called
+ // manual tests show expected behavior.
+ expect(spy_handler1).toHaveBeenCalled();
+ expect(spy_handler2).toHaveBeenCalled();
- global.fetch.mockClear();
- delete global.fetch;
+ global.fetch.mockClear();
+ delete global.fetch;
- done();
- });
+ done();
+ });
- it("only scans the tooltip content once", async (done) => {
- const $el = testutils.createTooltip({
- data: "source: content; trigger: click",
- });
- const instance = new pattern($el);
+ it("only scans the tooltip content once", async (done) => {
+ const $el = testutils.createTooltip({
+ data: "source: content; trigger: click",
+ });
+ const instance = new pattern($el);
- const spy_scan = spyOn(registry, "scan");
+ const spy_scan = spyOn(registry, "scan");
- testutils.click($el);
- await utils.timeout(1); // wait a tick for async fetch
+ testutils.click($el);
+ await utils.timeout(1); // wait a tick for async fetch
- // Test, if registry.scan isn't invoked twice - another time by
- // pat-inject.
- expect(spy_scan).toHaveBeenCalledTimes(1);
+ // Test, if registry.scan isn't invoked twice - another time by
+ // pat-inject.
+ expect(spy_scan).toHaveBeenCalledTimes(1);
- done();
- });
+ done();
});
});
@@ -1417,7 +1443,7 @@ this will be extracted.
document.body.appendChild(content);
const $el = testutils.createTooltip({
- data: "source: content; trigger: click",
+ data: "source: ajax; trigger: click",
href: "#local-content::element",
});
const instance = new pattern($el);
@@ -1441,7 +1467,7 @@ this will be extracted.
document.body.appendChild(content);
const $el = testutils.createTooltip({
- data: "source: content; trigger: click",
+ data: "source: ajax; trigger: click",
href: "#local-content",
});
const instance = new pattern($el);