Skip to content

Commit f9d1492

Browse files
committed
maint(pat notification): Code simplification and modernization.
1 parent 62a38c9 commit f9d1492

File tree

3 files changed

+132
-112
lines changed

3 files changed

+132
-112
lines changed

src/pat/notification/documentation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Description
44

5-
Notifications are used in applications to notify the user of status changes that happen within the application. Notifications could appear as inline messages, or projected (temporarily) as an overlay not he screen.
5+
Notifications are used in applications to notify the user of status changes that happen within the application. Notifications could appear as inline messages, or projected (temporarily) as an overlay to the screen.
66

77
## Documentation
88

src/pat/notification/notification.js

Lines changed: 105 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
/**
2-
* Patterns notification - Display (self-healing) notifications.
3-
*
4-
* Copyright 2013 Marko Durkovic
5-
*/
1+
// Patterns notification - Display (self-healing) notifications.
62
import $ from "jquery";
73
import Base from "../../core/base";
4+
import dom from "../../core/dom";
5+
import events from "../../core/events";
86
import inject from "../inject/inject";
97
import logging from "../../core/logging";
108
import Parser from "../../core/parser";
9+
import utils from "../../core/utils";
1110

1211
const log = logging.getLogger("notification");
12+
//log.setLevel(logging.Level.DEBUG);
1313

1414
export const parser = new Parser("notification");
1515
parser.addArgument("type", "static", ["static", "banner"]);
@@ -21,68 +21,43 @@ parser.addArgument("close-text", "Close");
2121
export default Base.extend({
2222
name: "notification",
2323
trigger: ".pat-notification",
24-
25-
// this is generic functionality and should be moved to lib
26-
parseUnit(value, unit) {
27-
var unitRe = new RegExp(unit + "$"),
28-
numericRe = new RegExp("^[0-9.]+");
29-
30-
if (!unitRe.test(value)) {
31-
throw "value " + value + "is not in unit " + unit;
32-
}
33-
34-
var mod = value.replace(numericRe, "");
35-
mod = mod.replace(unitRe, "");
36-
37-
value = parseFloat(value);
38-
if (!mod.length) {
39-
return value;
40-
}
41-
42-
var factors = {
43-
M: 1000000,
44-
k: 1000,
45-
m: 0.001,
46-
u: 0.000001,
47-
};
48-
49-
return value * factors[mod];
50-
},
51-
52-
parseUnitOrOption(value, unit, options) {
53-
if (options.indexOf(value) >= 0) {
54-
return value;
55-
}
56-
57-
return this.parseUnit(value, unit);
58-
},
59-
6024
count: 0,
6125

6226
init($el, opts) {
63-
if ($el.is("a,form")) {
27+
if (this.el.matches("a, form")) {
6428
this._init_inject($el, opts);
6529
} else {
66-
this._initNotification($el, opts);
30+
this._init_notification($el, opts);
6731
}
6832
},
6933

70-
_initNotification($el, opts) {
34+
_init_notification($el, opts) {
7135
this.count++;
7236

73-
var options = parser.parse($el, opts);
74-
var closetext = options.closeText;
37+
const el = $el[0];
38+
const options = parser.parse($el, opts);
39+
const closetext = options.closeText;
40+
41+
const wrapper = document.createElement("div");
42+
wrapper.setAttribute("id", `pat-notification-${this.count}`);
43+
wrapper.setAttribute("class", "pat-notification-panel");
44+
dom.wrap(el, wrapper);
7545

76-
$el = $el
77-
.wrap("<div/>")
78-
.parent()
79-
.attr("id", "pat-notification-" + this.count)
80-
.addClass("pat-notification-panel")
81-
.on("mouseenter.pat-notification", this.onMouseEnter.bind(this))
82-
.on("mouseleave.pat-notification", this.onMouseLeave.bind(this));
46+
events.add_event_listener(
47+
wrapper,
48+
"mouseenter",
49+
"notification__mouseenter",
50+
this.onMouseEnter.bind(this)
51+
);
52+
events.add_event_listener(
53+
wrapper,
54+
"mouseleave",
55+
"notification__mouseleave",
56+
this.onMouseLeave.bind(this)
57+
);
8358

8459
if (options["class"]) {
85-
$el.addClass(options["class"]);
60+
wrapper.classList.add(options["class"]);
8661
}
8762

8863
if (!Array.isArray(options.controls)) {
@@ -91,133 +66,152 @@ export default Base.extend({
9166

9267
// add close icon if requested
9368
if (options.controls.indexOf("icons") >= 0) {
94-
$el.append(
95-
"<button type='button' class='close-panel'>" + closetext + "</button>"
69+
wrapper.append(
70+
dom.create_from_string(
71+
`<button type="button" class="close-panel">${closetext}</button>`
72+
)
9673
);
9774
}
9875

9976
// add close button if requested
10077
if (options.controls.indexOf("buttons") >= 0) {
101-
$el.append(
102-
"<div class='button-bar'><button type='button' class='close-panel'>" +
103-
closetext +
104-
"</button></div>"
78+
wrapper.append(
79+
dom.create_from_string(
80+
`<div class="button-bar">
81+
<button type="button" class="close-panel">${closetext}</button>
82+
</div>`
83+
)
10584
);
10685
}
10786

108-
if ($el.find(".close-panel").length) {
109-
$el.on("click.pat-notification", ".close-panel", this.onClick.bind(this));
87+
if (wrapper.querySelector(".close-panel")) {
88+
events.add_event_listener(
89+
wrapper.querySelector(".close-panel"),
90+
"click",
91+
"notification__click",
92+
this.onClick.bind(this)
93+
);
11094
} else {
111-
$el.on("click.pat-notification", this.onClick.bind(this));
95+
events.add_event_listener(
96+
wrapper,
97+
"click",
98+
"notification__click",
99+
this.onClick.bind(this)
100+
);
112101
}
113102

114103
if (options.type === "banner") {
115-
var $container = $("#pat-notification-banners");
116-
if (!$container.length) {
117-
$container = $("<div/>")
118-
.attr("id", "pat-notification-banners")
119-
.addClass("pat-notification-container")
120-
.appendTo("body");
104+
let container = document.querySelector("#pat-notification-banners");
105+
if (!container) {
106+
container = document.createElement("div");
107+
container.setAttribute("id", "pat-notification-banners");
108+
container.setAttribute("class", "pat-notification-container");
109+
document.body.append(container);
121110
}
122-
$container.append($el);
111+
container.append(wrapper);
123112
}
124113

125-
var healing = this.parseUnitOrOption(options.healing, "s", ["persistent"]);
114+
let healing = options.healing;
115+
if (healing !== "persistent") {
116+
healing = utils.parseTime(healing);
117+
}
126118

127-
log.debug("Healing value is", healing);
128-
$el.data("healing", healing);
119+
log.debug(`Healing value is: ${healing}`);
120+
dom.set_data(wrapper, "healing", healing);
129121

130122
$el.animate({ opacity: 1 }, "fast", () => {
131-
this.initRemoveTimer($el);
123+
this.init_remove_timer(wrapper);
132124
});
133125
},
134126

135127
_init_inject($el) {
136-
var inject_opts = {
137-
target: "#pat-notification-temp",
138-
};
139128
$el[0].addEventListener("pat-inject-success", (e) => {
140-
var $trigger = $(e.target),
141-
cfg = parser.parse($trigger, { type: "banner" });
129+
const $trigger = $(e.target);
130+
const cfg = parser.parse($trigger, { type: "banner" });
142131

143-
var $el = $("#pat-notification-temp")
132+
const $temp = $("#pat-notification-temp")
144133
.contents()
145134
.wrapAll("<div/>")
146135
.parent()
147136
.addClass("pat-notification");
148137

149138
if ($trigger.is("a")) {
150-
$trigger.after($el);
139+
$trigger.after($temp);
151140
} else {
152-
$el.prependTo($trigger);
141+
$temp.prependTo($trigger);
153142
}
154-
this._initNotification($el, cfg);
143+
this._init_notification($temp, cfg);
155144

156145
// XXX: Do this later as inject tries to access its target afterwards.
157146
// This should be fixed in injection.
158147
setTimeout(() => {
159148
$("#pat-notification-temp").remove();
160149
}, 0);
161150
});
162-
inject.init($el, inject_opts);
151+
inject.init($el, {
152+
target: "#pat-notification-temp",
153+
});
163154
},
164155

165-
initRemoveTimer($el) {
166-
var healing = $el.data("healing");
156+
init_remove_timer(panel) {
157+
const healing = dom.get_data(panel, "healing");
167158
if (healing !== "persistent") {
168-
clearTimeout($el.data("timer"));
169-
$el.data(
159+
clearTimeout(dom.get_data(panel, "timer"));
160+
dom.set_data(
161+
panel,
170162
"timer",
171163
setTimeout(() => {
172-
this.remove($el);
173-
}, healing * 1000)
164+
log.debug("Timeout reached.");
165+
this.remove(panel);
166+
}, healing)
174167
);
175168
}
176169
},
177170

178171
onMouseEnter(e) {
179-
$(e.target).data("persistent", true);
172+
dom.set_data(e.target, "persistent", true);
180173
},
181174

182175
onMouseLeave(e) {
183-
var $this = $(e.target);
184-
185-
$this.data("persistent", false);
186-
this.initRemoveTimer($this);
176+
const panel = e.target;
177+
dom.set_data(panel, "persistent", false);
178+
this.init_remove_timer(panel);
187179
},
188180

189181
onClick(e) {
190-
var $this = $(e.delegateTarget);
191-
192-
$this.data("persistent", false);
193-
this.remove($this);
182+
const panel = e.target.closest(".pat-notification-panel");
183+
dom.set_data(panel, "persistent", false);
184+
this.remove(panel);
194185
},
195186

196-
remove($el) {
197-
if ($el.data("persistent") || $el.data("removing")) {
187+
remove(panel) {
188+
if (
189+
dom.get_data(panel, "persistent") === true ||
190+
dom.get_data(panel, "removing") === true
191+
) {
198192
return;
199193
}
194+
const $panel = $(panel);
200195

201-
$el.data("removing", true);
196+
dom.set_data(panel, "removing", true);
202197

203-
$el.stop(true).animate(
198+
$panel.stop(true).animate(
204199
{ opacity: 0 },
205200
{
206201
step() {
207-
if ($el.data("persistent")) {
202+
if (dom.get_data(panel, "persistent") === true) {
208203
// remove the timer and show notification
209-
clearTimeout($el.data("timer"));
210-
$el.stop(true).animate({ opacity: 1 });
211-
$el.data("removing", false);
204+
clearTimeout(dom.get_data(panel, "timer"));
205+
$panel.stop(true).animate({ opacity: 1 });
206+
dom.set_data(panel, "removing", false);
212207
return false;
213208
}
214209
},
215210

216211
complete() {
217-
var $this = $(this);
218-
$this.off(".pat-notification");
219-
$this.slideUp("slow", () => {
220-
$this.remove();
212+
$panel.off(".pat-notification");
213+
$panel.slideUp("slow", () => {
214+
$panel.remove();
221215
});
222216
},
223217
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import Pattern from "./notification";
2+
3+
describe("pat notification", function () {
4+
afterEach(() => {
5+
document.body.innerHTML = "";
6+
});
7+
8+
it("Gets initialized and will disappear as per default settings.", function () {
9+
document.body.innerHTML = `
10+
<p class="pat-notification">
11+
okay
12+
</p>
13+
`;
14+
15+
const el = document.querySelector(".pat-notification");
16+
expect(el.parentNode).toBe(document.body);
17+
18+
new Pattern(el);
19+
20+
expect(el.parentNode).not.toBe(document.body);
21+
expect(el.parentNode.classList.contains("pat-notification-panel")).toBe(true);
22+
23+
// With jQuery animation, we cannot easily test closing the panel yet.
24+
// TODO: Fix when jQuery animation was removed.
25+
});
26+
});

0 commit comments

Comments
 (0)