Issues (1)

byceps/static/behavior/common.js (1 issue)

1
/**
2
 * Register a function to be called when the document is "ready", i.e.
3
 * all the markup has been placed on the page.
4
 *
5
 * It does not wait until additional resources (stylesheets, images,
6
 * subframes) have been loaded.
7
 */
8
function onDomReady(callback) {
9
  if (document.readyState === 'complete' || document.readyState !== 'loading') {
10
    // The document has already fully loaded.
11
    callback();
12
  } else {
13
    document.addEventListener('DOMContentLoaded', callback);
14
  }
15
}
16
17
18
// ---------------------------------------------------------------------
19
// XHR requests
20
21
function post_on_click(selector) {
22
  _request_on_click(selector, 'POST');
23
}
24
25
function post_on_click_then_reload(selector) {
26
  _request_on_click_then_reload(selector, 'POST');
27
}
28
29
function confirmed_post_on_click(selector, confirmation_label) {
30
  _confirmed_request_on_click(selector, confirmation_label, 'POST');
31
}
32
33
function confirmed_post_on_click_then_reload(selector, confirmation_label) {
34
  _confirmed_request_on_click_then_reload(selector, confirmation_label, 'POST');
35
}
36
37
function delete_on_click(selector) {
38
  _request_on_click(selector, 'DELETE');
39
}
40
41
function delete_on_click_then_reload(selector) {
42
  _request_on_click_then_reload(selector, 'DELETE');
43
}
44
45
function confirmed_delete_on_click(selector, confirmation_label) {
46
  _confirmed_request_on_click(selector, confirmation_label, 'DELETE');
47
}
48
49
function confirmed_delete_on_click_then_reload(selector, confirmation_label) {
50
  _confirmed_request_on_click_then_reload(selector, confirmation_label, 'DELETE');
51
}
52
53
function _request_on_click(selector, method) {
54
  _onClickCallbackWithHref(selector, href => {
55
    _ajax_then_redirect_to_location_response_header(method, href);
56
  });
57
}
58
59
function _request_on_click_then_reload(selector, method) {
60
  _onClickCallbackWithHref(selector, href => {
61
    _ajax_then_reload(method, href);
62
  });
63
}
64
65
function _confirmed_request_on_click(selector, confirmation_label, method) {
66
  _onClickCallbackWithHref(selector, href => {
67
    if (confirm(confirmation_label)) {
68
      _ajax_then_redirect_to_location_response_header(method, href);
69
    };
70
  });
71
}
72
73
function _confirmed_request_on_click_then_reload(selector, confirmation_label, method) {
74
  _onClickCallbackWithHref(selector, href => {
75
    if (confirm(confirmation_label)) {
76
      _ajax_then_reload(method, href);
77
    };
78
  });
79
}
80
81
82
function _onClickCallbackWithHref(selector, callback) {
83
  const elements = document.querySelectorAll(selector);
84
  elements.forEach(element => {
85
    element.addEventListener('click', event => {
86
      const href = element.getAttribute('href');
87
      callback(href);
88
89
      event.preventDefault();
90
    });
91
  });
92
}
93
94
function _ajax_then_redirect_to_location_response_header(method, request_url) {
95
  _ajax(method, request_url, response => {
96
    if (response.status == 204) {
97
      const redirectUrl = response.headers.get('Location');
98
      if (redirectUrl !== null) {
99
        location.href = redirectUrl;
100
      }
101
    }
102
  });
103
}
104
105
function _ajax_then_reload(method, request_url) {
106
  _ajax(method, request_url, response => {
107
    if (response.status == 204) {
108
      location.href = location.href;
109
    }
110
  });
111
}
112
113
function _ajax(method, url, on_complete) {
114
  fetch(url, {method: method})
115
    .then(response => on_complete(response));
116
}
117
118
119
// ---------------------------------------------------------------------
120
// dropdown menus
121
122
123
/**
124
 * Make dropdown menus open if their respective trigger is clicked.
125
 */
126
function enableDropdownMenuToggles() {
127
  const dropdownToggles = document.querySelectorAll('.dropdown .dropdown-toggle');
128
  dropdownToggles.forEach(triggerElement => {
129
    triggerElement.addEventListener('click', event => {
130
      const dropdown = triggerElement.parentNode;
131
      dropdown.classList.toggle('open');
132
133
      event.preventDefault();
134
    });
135
  });
136
}
137
138
139
/**
140
 * Close all open dropdown menus but the one that has been clicked (if
141
 * any).
142
 */
143
function closeOpenDropdownMenus(clickTarget) {
144
  const openDropdowns = document.querySelectorAll('.dropdown.open');
145
  openDropdowns.forEach(openDropdown => {
146
    if (!openDropdown.contains(clickTarget)) {
147
      // Click was outside of this dropdown menu, so close it.
148
      openDropdown.classList.remove('open');
149
    }
150
  });
151
}
152
153
154
// Add behavior to dropdown menus.
155
onDomReady(() => {
156
  enableDropdownMenuToggles();
157
158
  // Close open dropdowns if user clicks outside of an open dropdown.
159
  document.addEventListener('click', event => closeOpenDropdownMenus(event.target));
160
});
161
162
163
// ---------------------------------------------------------------------
164
// clipboard
165
166
167
/**
168
 * Register an element as click trigger to copy the value of a field to
169
 * the clipboard.
170
 */
171
function enableCopyToClipboard(triggerElementId) {
172
  const triggerElement = document.getElementById(triggerElementId);
173
  if (triggerElement === null) {
174
    return;
175
  }
176
177
  triggerElement.addEventListener('click', () => {
178
    const fieldId = triggerElement.dataset.fieldId;
179
    const field = document.getElementById(fieldId);
180
181
    field.focus();
182
    field.select();
183
    try {
184
      document.execCommand('copy');
185
    } catch (err) {}
186
    field.blur();
187
  });
188
}
189
190
191
// ---------------------------------------------------------------------
192
// forms
193
194
195
// Disable the submit button of forms with class
196
// `disable-submit-button-on-submit` on submit.
197
onDomReady(() => {
198
  const formsWhoseSubmitButtonShouldBeDisabledOnSubmit = document
199
      .querySelectorAll('form.disable-submit-button-on-submit');
200
201
  formsWhoseSubmitButtonShouldBeDisabledOnSubmit.forEach(form => {
202
    form.addEventListener('submit', () => {
203
      const submitButton = form.querySelector('button[type="submit"]');
204
      submitButton.disabled = true;
205
      submitButton.innerHTML += ' <svg class="icon spinning"><use xlink:href="/static/style/icons.svg#spinner"></use></svg>';
206
    });
207
  });
208
});
209
210
211
// ---------------------------------------------------------------------
212
// log-out
213
214
215
// Enable log-out.
216
onDomReady(() => {
217
  document.querySelectorAll('a[data-action="log-out"]')
218
    .forEach(anchor => {
219
      anchor.addEventListener('click', event => {
220
        if (confirm('Wirklich abmelden?')) {
221
          const href = anchor.getAttribute('href');
222
          fetch(href, {method: 'POST'})
223
            .then(response => location.href = anchor.dataset.redirectTarget);
0 ignored issues
show
The parameter response is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
224
        };
225
226
        event.preventDefault();
227
      });
228
    });
229
});
230