Skip to content

Commit 311b626

Browse files
committed
Add ability to target loading elements.
1 parent a3dedb6 commit 311b626

File tree

6 files changed

+222
-49
lines changed

6 files changed

+222
-49
lines changed

django_unicorn/static/js/attribute.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export class Attribute {
1313
this.isField = false;
1414
this.isPoll = false;
1515
this.isLoading = false;
16+
this.isTarget = false;
1617
this.isKey = false;
1718
this.isPK = false;
1819
this.isError = false;
@@ -40,14 +41,18 @@ export class Attribute {
4041
this.isPoll = true;
4142
} else if (contains(this.name, ":loading")) {
4243
this.isLoading = true;
44+
} else if (contains(this.name, ":target")) {
45+
this.isTarget = true;
4346
} else if (this.name === "unicorn:key" || this.name === "u:key") {
4447
this.isKey = true;
4548
} else if (this.name === "unicorn:pk" || this.name === "u:pk") {
4649
this.isPK = true;
4750
} else if (contains(this.name, ":error:")) {
4851
this.isError = true;
4952
} else {
50-
const actionEventType = this.name.replace("unicorn:", "").replace("u:", "");
53+
const actionEventType = this.name
54+
.replace("unicorn:", "")
55+
.replace("u:", "");
5156

5257
if (
5358
actionEventType !== "id" &&

django_unicorn/static/js/component.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ export class Component {
3232
this.root = undefined;
3333
this.modelEls = [];
3434
this.dbEls = [];
35+
this.loadingEls = [];
36+
this.keyEls = [];
3537
this.errors = {};
3638
this.poll = {};
3739

@@ -104,6 +106,17 @@ export class Component {
104106
if (!this.modelEls.some((e) => e.isSame(element))) {
105107
this.modelEls.push(element);
106108
}
109+
} else if (hasValue(element.loading)) {
110+
this.loadingEls.push(element);
111+
112+
// Hide loading elements that are shown when an action happens
113+
if (element.loading.show) {
114+
element.hide();
115+
}
116+
}
117+
118+
if (hasValue(element.key)) {
119+
this.keyEls.push(element);
107120
}
108121

109122
element.actions.forEach((action) => {

django_unicorn/static/js/element.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export class Element {
3030
this.actions = [];
3131
this.db = {};
3232
this.field = {};
33-
33+
this.target = null;
3434
this.key = null;
3535
this.errors = [];
3636

@@ -82,7 +82,13 @@ export class Element {
8282
this.loading.removeClass = attribute.value;
8383
} else if (attribute.modifiers.class) {
8484
this.loading.class = attribute.value;
85+
} else if (attribute.modifiers.remove) {
86+
this.loading.hide = true;
87+
} else {
88+
this.loading.show = true;
8589
}
90+
} else if (attribute.isTarget) {
91+
this.target = attribute.value;
8692
} else if (attribute.eventType) {
8793
const action = {};
8894
action.name = attribute.value;
@@ -171,6 +177,20 @@ export class Element {
171177
this.el.focus();
172178
}
173179

180+
/**
181+
* Hide the element.
182+
*/
183+
hide() {
184+
this.el.hidden = "hidden";
185+
}
186+
187+
/**
188+
* Show the element.
189+
*/
190+
show() {
191+
this.el.hidden = null;
192+
}
193+
174194
/**
175195
* A key that takes into consideration the db name and pk.
176196
*/

django_unicorn/static/js/eventListeners.js

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
$,
23
args,
34
generateDbKey,
45
hasValue,
@@ -86,15 +87,18 @@ export function addActionEventListener(component, eventType) {
8687
if (eventArg.startsWith("$event")) {
8788
// Remove any extra whitespace, everything before and including "$event", and the ending paren
8889
// let eventArg = action.name.trim();
89-
eventArg = eventArg.trim().slice(eventArg.indexOf("$event") + 6).trim();
90-
90+
eventArg = eventArg
91+
.trim()
92+
.slice(eventArg.indexOf("$event") + 6)
93+
.trim();
94+
9195
const originalSpecialVariable = `$event${eventArg}`;
9296
let data = event;
9397
let invalidPiece = false;
94-
98+
9599
eventArg.split(".").forEach((piece) => {
96100
piece = piece.trim();
97-
101+
98102
if (piece) {
99103
// TODO: Handle method calls with args
100104
if (piece.endsWith("()")) {
@@ -108,34 +112,67 @@ export function addActionEventListener(component, eventType) {
108112
}
109113
}
110114
});
111-
115+
112116
if (invalidPiece) {
113-
console.error(`${originalSpecialVariable} could not be retrieved`)
117+
console.error(
118+
`'${originalSpecialVariable}' could not be retrieved`
119+
);
114120
action.name = action.name.replace(originalSpecialVariable, "");
115121
} else if (data) {
116122
if (typeof data === "string") {
117123
// Wrap strings in quotes
118124
data = `"${data}"`;
119125
}
120-
121-
action.name = action.name.replace(originalSpecialVariable, data);
126+
127+
action.name = action.name.replace(
128+
originalSpecialVariable,
129+
data
130+
);
122131
}
123132
}
124133
});
125134

126135
if (targetElement.loading) {
127136
if (targetElement.loading.attr) {
128-
targetElement.el[targetElement.loading.attr] = targetElement.loading.attr;
129-
}
130-
131-
if (targetElement.loading.class) {
137+
targetElement.el[targetElement.loading.attr] =
138+
targetElement.loading.attr;
139+
} else if (targetElement.loading.class) {
132140
targetElement.el.classList.add(targetElement.loading.class);
141+
} else if (targetElement.loading.removeClass) {
142+
targetElement.el.classList.remove(
143+
targetElement.loading.removeClass
144+
);
133145
}
146+
}
147+
148+
// Look at all elements with a loading attribute
149+
component.loadingEls.forEach((loadingElement) => {
150+
if (loadingElement.target) {
151+
let targetedEl = $(`#${loadingElement.target}`, component.root);
134152

135-
if (targetElement.loading.removeClass) {
136-
targetElement.el.classList.remove(targetElement.loading.removeClass);
153+
if (!targetedEl) {
154+
component.keyEls.forEach((keyElement) => {
155+
if (!targetedEl && keyElement.key === loadingElement.target) {
156+
targetedEl = keyElement.el;
157+
}
158+
});
159+
}
160+
161+
if (targetedEl) {
162+
if (targetElement.el.isSameNode(targetedEl)) {
163+
if (loadingElement.loading.hide) {
164+
loadingElement.hide();
165+
} else if (loadingElement.loading.show) {
166+
loadingElement.show();
167+
}
168+
}
169+
}
170+
} else if (loadingElement.loading.hide) {
171+
loadingElement.hide();
172+
} else if (loadingElement.loading.show) {
173+
loadingElement.show();
137174
}
138-
}
175+
});
139176

140177
if (action.key) {
141178
if (action.key === toKebabCase(event.key)) {

django_unicorn/static/js/utils.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,8 @@ export function walk(el, callback) {
113113
}
114114
}
115115

116-
117116
export function args(func) {
118-
func = func.trim()
117+
func = func.trim();
119118

120119
if (!contains(func, "(") || !func.endsWith(")")) {
121120
return [];
@@ -136,7 +135,7 @@ export function args(func) {
136135
for (let idx = 0; idx < func.length; idx++) {
137136
const c = func.charAt(idx);
138137
currentArg += c;
139-
138+
140139
if (c === "[") {
141140
bracketCount++;
142141
} else if (c === "]") {
@@ -151,10 +150,15 @@ export function args(func) {
151150
curlyCount--;
152151
} else if (c === "'") {
153152
inSingleQuote = !inSingleQuote;
154-
} else if (c === "\"") {
153+
} else if (c === '"') {
155154
inDoubleQuote = !inDoubleQuote;
156155
} else if (c === ",") {
157-
if (!inSingleQuote && !inDoubleQuote && bracketCount === 0 && parenthesisCount === 0) {
156+
if (
157+
!inSingleQuote &&
158+
!inDoubleQuote &&
159+
bracketCount === 0 &&
160+
parenthesisCount === 0
161+
) {
158162
// Remove the trailing comma
159163
currentArg = currentArg.slice(0, currentArg.length - 1);
160164

@@ -164,7 +168,12 @@ export function args(func) {
164168
}
165169

166170
if (idx === func.length - 1) {
167-
if (!inSingleQuote && !inDoubleQuote && bracketCount === 0 && parenthesisCount === 0) {
171+
if (
172+
!inSingleQuote &&
173+
!inDoubleQuote &&
174+
bracketCount === 0 &&
175+
parenthesisCount === 0
176+
) {
168177
functionArgs.push(currentArg.trim());
169178
currentArg = "";
170179
}

0 commit comments

Comments
 (0)