-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhome.js
239 lines (232 loc) · 14 KB
/
home.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
import createNotification from './all/create-notification';
import deleteTrick from './trick/removal/delete-trick';
import imageListLoader from './all/image-list-loader';
import request from './all/ajax-request';
import URIHelper from './all/encode-decode-uri';
export default () => {
// ------------------- Home page -------------------
let element = document.getElementById('st-trick-list');
if (element) { // element !== undefined && element !== null
// No trick was found! So this will stop all the script.
if (0 === element.querySelectorAll('.uk-card').length) {
return;
}
// Get defined parameters from server side
let loadingMode = element.querySelector('.uk-grid').getAttribute('data-loading-mode'),
definedLimit = parseInt(element.querySelector('.uk-grid').getAttribute('data-limit'), 10),
nodes = element.querySelectorAll('.uk-card'),
countAll = parseInt(element.querySelector('.uk-grid').getAttribute('data-count'), 10),
last = nodes[nodes.length - 1],
lastOffset = parseInt(last.parentElement.getAttribute('data-offset'), 10),
limit = parseInt(element.querySelector('.uk-grid').getAttribute('data-limit'), 10),
requestPath = element.querySelector('.uk-grid').getAttribute('data-path'),
technicalError = element.querySelector('.uk-grid').getAttribute('data-technical-error'),
listEnded = element.querySelector('.uk-grid').getAttribute('data-ended'),
ajaxPrevented = false;
const loadMoreButton = document.getElementById('st-home-load-more');
// Trick list image loader behavior when page is loaded.
nodes.forEach(card => {
imageListLoader(document.getElementById('st-card-image-' + card.parentElement.getAttribute('data-offset')));
// ------------------------------------------------------------------------------------------------------------
// Manage trick deletion
let trickRemovalLink = card.querySelector('.st-delete-trick');
if (trickRemovalLink) {
deleteTrick(card.querySelector('.st-delete-trick'));
}
});
// Prevent AJAX request from being called if all cards are already loaded.
if ((loadingMode === 'DESC' && lastOffset === 0) ||
(loadingMode === 'ASC' && lastOffset === countAll - 1)) {
ajaxPrevented = true;
} else {
// Show load more button which is hidden by default
loadMoreButton.classList.remove('uk-hidden');
}
// Trick list anchor "Let's go!" mouse behaviors for slideshow:
const toHomeListButton = document.getElementById('st-home-list-anchor');
toHomeListButton.addEventListener('mouseover', () => {
if (toHomeListButton) {
// Add class which hides slideshow nav
document.querySelector('.uk-slideshow .uk-slidenav-previous').classList.add('uk-hidden');
document.querySelector('.uk-slideshow .uk-slidenav-next').classList.add('uk-hidden');
}
});
toHomeListButton.addEventListener('mouseout', () => {
if (toHomeListButton) {
// Remove class which hides slideshow nav
document.querySelector('.uk-slideshow .uk-slidenav-previous').classList.remove('uk-hidden');
document.querySelector('.uk-slideshow .uk-slidenav-next').classList.remove('uk-hidden');
}
});
// To top: show button if at least "limit + 1" tricks are shown.
const toTopButton = document.getElementById('st-home-top');
const toTop = () => {
nodes = element.querySelectorAll('.uk-card');
if (toTopButton) {
if (nodes.length <= 10) {
// Hide
toTopButton.classList.add('uk-hidden');
// Remove scrollspy behavior
toTopButton.removeAttribute('uk-scrollspy');
} else {
// Show
toTopButton.classList.remove('uk-hidden');
// Add scrollspy behavior
toTopButton.setAttribute('uk-scrollspy', 'cls:uk-animation-slide-right-medium; delay: 500; repeat: true');
}
}
};
toTop();
// Load more
if (loadMoreButton) {
loadMoreButton.addEventListener('click', () => {
nodes = element.querySelectorAll('.uk-card');
last = nodes[nodes.length - 1];
// Get offset from last card shown
let endOffset = parseInt(last.parentElement.getAttribute('data-offset'), 10);
let minOffset = 0;
let maxOffset = countAll - 1;
// check loading mode to define startOffset
let startOffset = loadingMode === 'DESC' ? endOffset - limit : endOffset + 1;
// Check a valid startOffset for both modes
let validOffset = (startOffset >= -limit) && (startOffset < maxOffset + limit + 1);
// Check a valid limit for both modes
let validLimit = (limit >= 1); // && (limit < maxOffset + 1); will restrict limit max value with possible issue
// Check correctly defined order
let validOrder = (loadingMode === 'DESC') || (loadingMode === 'ASC');
// Error: check if startOffset or limit values are wrong: so reset list to default parameters for descending order
// Descending order is also initial state if loading mode is wrong.
if (!validOrder || (loadingMode === 'DESC' && (!validOffset || !validLimit))) {
startOffset = maxOffset + 1 - limit;
// Error: check if offset or limit values are wrong: so reset list to default parameters for ascending order
} else if (loadingMode === 'ASC' && (!validOffset || !validLimit)) {
startOffset = 0;
// Particular case: check if calculated startOffset is not under minOffset: lowest startOffset must be 0 for descending order
} else if (loadingMode === 'DESC' && startOffset < minOffset) {
startOffset = minOffset;
// A modulo can be used instead of enOffset, but for client side, the new limit value is already available with it:
// limit = (0 == countAll % limit) ? 1 : countAll % limit;
limit = endOffset;
// Particular case: check if calculated startOffset + limit is not over maxOffset for ascending order
} else if (loadingMode === 'ASC' && startOffset + limit > maxOffset) {
limit = maxOffset + 1 - startOffset;
}
// ------------------------------------------------------------------------------------------------------------
// AJAX request
if (!ajaxPrevented) {
// Prepare path to AJAX action
const pathHandler = URIHelper();
requestPath = pathHandler.uriOnString.encode(requestPath);
startOffset = pathHandler.uriOnString.encodeParamWithRFC3986(startOffset.toString());
limit = pathHandler.uriOnString.encodeParamWithRFC3986(limit.toString());
const obj = {
headers: {'X-Requested-With': 'XMLHttpRequest'},
url: limit !== definedLimit ? (requestPath + '/' + startOffset + '/' + limit) : (requestPath + '/' + startOffset),
async: true,
withCredentials: false,
responseType: 'text', // 'document' does not work in this case!
onLoadStartFunction: () => {
// Disable button
document.querySelector('#st-home-load-more').classList.add('uk-disabled');
// Show loading spinner
document.querySelector('#st-home-load-more .st-home-spinner').classList.remove('uk-hidden');
},
};
request(obj).then(response => {
let tmp = document.createElement("div");
tmp.innerHTML = response.toString();
let cards = tmp.querySelectorAll('.st-card-container');
let listError = false;
let endReached = false;
cards.forEach((card, index) => {
// Manage error to display reinitialized default list.
if (index === 0 && card.getAttribute('data-error') !== null) {
document.querySelector('#st-trick-list .uk-grid').innerHTML = '';
listError = true;
}
// Add appearance effect on trick list container
element.setAttribute(
'uk-scrollspy',
'target: > .uk-card; cls: uk-animation-fade; delay: 1000'
);
// Hide card element before feeding and show
card.classList.add('uk-hidden');
// Show card
let to = setTimeout(() => {
card.classList.remove('uk-hidden');
document.querySelector('#st-trick-list .uk-grid').insertAdjacentHTML('beforeend', card.outerHTML);
// Trick list image loader behavior after insertion
imageListLoader(document.getElementById('st-card-image-' + card.getAttribute('data-offset')));
// Last card
if (index === cards.length - 1) {
// Hide loading spinner
document.querySelector('#st-home-load-more .st-home-spinner').classList.add('uk-hidden');
// Check end of list
if (loadingMode === 'DESC' && parseInt(card.getAttribute('data-offset')) === 0) {
// Hide Load more button
document.querySelector('#st-home-load-more').classList.add('uk-hidden');
endReached = true;
} else if (loadingMode === 'ASC' && parseInt(card.getAttribute('data-offset')) === maxOffset) {
// Hide Load more button
document.querySelector('#st-home-load-more').classList.add('uk-hidden');
endReached = true;
}
// Max offset is reached: show notification
if (!listError && endReached) {
createNotification(
listEnded,
null,
true,
'info',
'info',
5000
);
}
// List error is triggered: show notification
if (listError) {
createNotification(
cards[0].getAttribute('data-error'),
null,
true,
'error',
'warning',
5000
);
}
// Enable button
document.querySelector('#st-home-load-more').classList.remove('uk-disabled');
toTop();
// ------------------------------------------------------------------------------------------------------------
// Manage trick deletion also here to update removal links list after AJAX request success
let trickDeletionLink = card.querySelector('.st-delete-trick');
if (trickDeletionLink !== null) {
deleteTrick(trickDeletionLink);
}
}
clearTimeout(to);
}, (index + 1) * 250);
});
})
// It is important to chain to prevent ajax request from being called twice!
.catch(xhr => {
// Hide spinner
document.querySelector('#st-home-load-more').classList.add('uk-hidden');
// Technical error: show notification
let error;
error = (xhr.status !== undefined && xhr.statusText !== undefined) ? `error: ${xhr.status} - ${xhr.statusText}` : '';
// Aborted request
error = 0 !== xhr.status ? error : '';
createNotification(
technicalError + error,
null,
true,
'error',
'warning',
0
);
});
}
});
}
}
};