PluginProbe
wpForo Forum / 3.1.6
wpForo Forum v3.1.6
3.1.6 3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 All 138 releases
wpforo / admin / assets / js / backend.js

backend.js in wpForo Forum 3.1.6, at admin/assets/js/backend.js

515 lines 15.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global wpforo */
2
3 jQuery.ajaxSetup({
4 url: ajaxurl,
5 data: {
6 referer: window.location.origin + window.location.pathname,
7 },
8 });
9
10 jQuery(document).ready(function ($) {
11 var wpforo_admin_wrap = $('#wpf-admin-wrap');
12
13 $(document).on('click', '#wpforo-admin-notice-recaptcha .notice-dismiss', function () {
14 var wrap = $(this).closest('#wpforo-admin-notice-recaptcha');
15 $.ajax({
16 type: 'POST', url: ajaxurl, data: {
17 backend: 1, action: 'wpforo_dissmiss_recaptcha_note',
18 },
19 }).done(function (response) {
20 if (parseInt(response)) {
21 wrap.remove();
22 }
23 });
24 });
25
26 var fas = $('[name$="[icon]"]');
27 fas.each(function () {
28 var fa = $(this);
29 fa.iconpicker({
30 placement: 'top',
31 selectedCustomClass: 'wpf-fa-ico-primary-bg',
32 component: '.wpf-fa-ico-preview',
33 collision: true,
34 animation: true,
35 });
36 var w = document.createElement('span');
37 $(w).addClass('wpf-input-group-addon');
38 var i = document.createElement('i');
39 $(i).addClass(fa.val());
40 w.append(i);
41 fa.after(w);
42 fa.on('iconpickerUpdated input propertychange', function () {
43 $(i).removeClass().addClass($(this).val());
44 });
45 });
46
47 wpforo_scrollto_setting_field(window.location);
48 window.onhashchange = function () {
49 wpforo_scrollto_setting_field(window.location);
50 };
51
52 var search_field = document.getElementById('wpf-opt-search-field');
53 if (search_field) autocomplete(search_field, wpforo.settings.info);
54
55 /* -- #################################################### -- */
56
57 /* image adjust and upload from frontend */
58
59 function processfile (file, max_width, max_height, quality, callback) {
60 if (!(/image/i).test(file.type)) {
61 alert('File ' + file.name + ' is not an image.');
62 return false;
63 }
64
65 // read the files
66 var reader = new FileReader();
67 reader.readAsArrayBuffer(file);
68
69 reader.onload = function (event) {
70 // blob stuff
71 var blob = new Blob([event.target.result]); // create blob...
72 window.URL = window.URL || window.webkitURL;
73 var blobURL = window.URL.createObjectURL(blob); // and get its URL
74
75 // helper Image object
76 var image = new Image();
77 image.src = blobURL;
78 //preview.appendChild(image); // preview commented out, I am using the canvas instead
79 image.onload = function () {
80 // have to wait till it's loaded
81 var resized = resizeMe(image, max_width, max_height, quality); // send it to canvas
82 callback(resized);
83 };
84 };
85 }
86
87 // === RESIZE ====
88 function resizeMe (img, max_width, max_height, quality) {
89 var canvas = document.createElement('canvas');
90 var width = img.width;
91 var height = img.height;
92
93 // calculate the width and height, constraining the proportions
94 if (width > height) {
95 if (width > max_width) {
96 //height *= max_width / width;
97 height = Math.round(height *= max_width / width);
98 width = max_width;
99 }
100 } else {
101 if (height > max_height) {
102 //width *= max_height / height;
103 width = Math.round(width *= max_height / height);
104 height = max_height;
105 }
106 }
107
108 // resize the canvas and draw the image data into it
109 canvas.width = width;
110 canvas.height = height;
111 var ctx = canvas.getContext('2d');
112 ctx.drawImage(img, 0, 0, width, height);
113
114 return canvas.toDataURL('image/jpeg', quality); // get the data from canvas as 70% JPG (can be also PNG, etc.)
115 }
116
117 function OpenFileDialog (accept, callback) {
118 // this function must be called from a user
119 // activation event (ie an onclick event)
120
121 // Create an input element
122 var inputElement = document.createElement('input');
123
124 // Set its type to file
125 inputElement.type = 'file';
126
127 // Set accept to the file types you want the user to select.
128 // Include both the file extension and the mime type
129 inputElement.accept = accept;
130
131 // set onchange event to call callback when user has selected file
132 inputElement.addEventListener('change', callback);
133
134 // dispatch a click event to open the file dialog
135 inputElement.dispatchEvent(new MouseEvent('click'));
136 }
137
138 wpforo_admin_wrap.on('click', 'label', {}, function () {
139 $('.wpf-edit-cover', $(this).closest('.wpf-opt-row-cover')).trigger('click');
140 });
141
142 // ***** -- cover image change -- ****** //
143 wpforo_admin_wrap.on('click', '.wpf-opt-row-cover .wpf-edit-cover:not(.wpf-processing)', {}, function () {
144 if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
145 alert('The File APIs are not fully supported in this browser.');
146 return false;
147 }
148 var $this = $(this);
149 OpenFileDialog('image/png,image/jpg,image/jpeg,image/gif', function () {
150 if (this.files.length) {
151 $this.addClass('wpf-processing');
152 $('#wpf-admin-loading-extrawrap').show();
153 processfile(this.files[0], 1120, 460, 0.7, function (imageblob) {
154 $.ajax({
155 type: 'POST',
156 data: {
157 image_blob: imageblob,
158 action: 'wpforo_profiles_default_cover_upload',
159 _wpfnonce: wpforo['nonces']['wpforo_profiles_default_cover_upload'],
160 },
161 }).done(function () {
162 $this.closest('.wpf-cover').css('background-image', 'url(\'' + imageblob + '\')');
163 }).always(function () {
164 $this.removeClass('wpf-processing');
165 $('#wpf-admin-loading-extrawrap').hide();
166 });
167 });
168 }
169 });
170 });
171 });
172
173 function get_parentid (arr, depth) {
174 for (var i = arr.length - 1; i >= 0; i--) {
175 if (arr[i]['depth'] == depth) return arr[i]['forumid'];
176 }
177 }
178
179 function get_forums_hierarchy () {
180
181 var ul_content = document.getElementById('menu-to-edit');
182 var lis = ul_content.getElementsByTagName('LI');
183
184 var forums_hierarchy_arr = new Array();
185
186 for (var i = 0; i < lis.length; i++) {
187 forums_hierarchy_arr[i] = new Array();
188 forums_hierarchy_arr[i]['forumid'] = lis[i].id.replace('menu-item-', '');
189 var depth = lis[i].getAttribute('class').replace('menu-item menu-item-depth-', '');
190
191 forums_hierarchy_arr[i]['depth'] = depth;
192
193 if (depth == 0) {
194 forums_hierarchy_arr[i]['parentid'] = 0;
195 } else {
196 var previous_depth = depth - 1;
197 forums_hierarchy_arr[i]['parentid'] = get_parentid(forums_hierarchy_arr, previous_depth);
198 }
199
200 forums_hierarchy_arr[i]['order'] = i + 1;
201
202 var h_id = 'forumid-' + forums_hierarchy_arr[i]['forumid'];
203 var h_parentid = 'parentid-' + forums_hierarchy_arr[i]['forumid'];
204 var h_order = 'order-' + forums_hierarchy_arr[i]['forumid'];
205
206 document.getElementById(h_id).value = forums_hierarchy_arr[i]['forumid'];
207 document.getElementById(h_parentid).value = forums_hierarchy_arr[i]['parentid'];
208 document.getElementById(h_order).value = forums_hierarchy_arr[i]['order'];
209
210 }
211
212 document.getElementById('forum-hierarchy').submit();
213
214 }
215
216 function mode_changer (v) {
217 if (v) {
218 document.getElementById('forum_submit').value = wpforo_admin.phrases.move;
219 document.getElementById('forum_select').disabled = false;
220 } else {
221 document.getElementById('forum_submit').value = wpforo_admin.phrases.delete;
222 document.getElementById('forum_select').disabled = true;
223 }
224 }
225
226 function select_all () {
227 var sel_all = document.getElementById('cb-select-all-1');
228 var list = document.getElementById('the-list').getElementsByTagName('INPUT');
229 for (var i = 0; i < list.length; i++) document.getElementById(list[i].id).checked = !!sel_all.checked;
230 }
231
232 function costum_or_inherit () {
233 var chack = document.getElementById('custom');
234 document.getElementById('permis').disabled = !!chack.checked;
235 }
236
237 function mode_changer_ug (v) {
238 document.getElementById('ug_select').disabled = !v;
239 }
240
241 function wpforo_scrollto_setting_field (location) {
242 if (location.hash) {
243 var scroll_to;
244 var exreg = new RegExp('&wpf_tab=([^=&?#\\s]+)', 'i');
245 var match = location.href.match(exreg);
246 if (match) {
247 var hash = location.hash.toString().slice(1);
248 var name = match[1] + '\\[' + hash + '\\]';
249 var wrap_row = jQuery('[data-wpf-opt="' + hash + '"]');
250 if (wrap_row.length) {
251 scroll_to = wrap_row.offset().top - 150;
252 wpForoScrollTo(scroll_to, function () {
253 wrap_row.addClass('wpf-selected');
254 if (!jQuery('#wpf-opt-search-field').is(':focus')) {
255 var field = jQuery('[name^=' + name + ']', wrap_row);
256 field.trigger('focus');
257 field.trigger('select');
258 }
259 setTimeout(function () {
260 wrap_row.removeClass('wpf-selected');
261 }, 3000);
262 });
263 }
264 }
265 }
266 }
267
268 function wpforo_admin_tinymce_setup (editor) {
269 editor.on('init', function (e) {
270 wpforo_scrollto_setting_field(window.location);
271 });
272 }
273
274 function wpForoScrollTo (top, callback, element) {
275 var html = element ? element : document.documentElement;
276 var current = html.scrollTop;
277 var delta = top - current;
278 var finish = function () {
279 html.scrollTop = top;
280 if (callback) {
281 callback();
282 }
283 };
284 if (!window.performance.now || delta === 0) {
285 finish();
286 return;
287 }
288 var transition = wpForoEaseOutQuad;
289 var max = 300;
290 if (delta < -max) {
291 current = top + max;
292 delta = -max;
293 } else if (delta > max) {
294 current = top - max;
295 delta = max;
296 } else {
297 transition = wpForoEaseInOutQuad;
298 }
299 var duration = 150;
300 var interval = 7;
301 var time = window.performance.now();
302 var animate = function () {
303 var now = window.performance.now();
304 if (now >= time + duration) {
305 finish();
306 return;
307 }
308 var dt = (now - time) / duration;
309 html.scrollTop = Math.round(current + delta * transition(dt));
310 setTimeout(animate, interval);
311 };
312 setTimeout(animate, interval);
313 }
314
315 function wpForoEaseOutQuad (t) {
316 return t * t;
317 }
318
319 function wpForoEaseInOutQuad (t) {
320 return (t < 0.5) ? (2 * t * t) : ((4 - 2 * t) * t - 1);
321 }
322
323 // ----------- autocomplate settings search ----------------- //
324
325 function autocomplete (inp, arr) {
326 var m;
327 var page = '';
328 var page_regexp = new RegExp('[?&]page=([^=&?#\\s]+)', 'i');
329 m = window.location.href.match(page_regexp);
330 if (m) page = m[1];
331
332 var wpf_tab = '';
333 var wpf_tab_regexp = new RegExp('[?&]wpf_tab=([^=&?#\\s]+)', 'i');
334 m = window.location.href.match(wpf_tab_regexp);
335 if (m) wpf_tab = m[1];
336
337 /*the autocomplete function takes two arguments,
338 the text field element and an array of possible autocompleted values:*/
339 var currentFocus;
340 /*execute a function when someone writes in the text field:*/
341 inp.addEventListener('input', function () {
342 var a, b, val = this.value;
343 /*close any already open lists of autocompleted values*/
344 closeAllLists();
345 if (!val) { return false;}
346 currentFocus = -1;
347 /*create a DIV element that will contain the items (values):*/
348 a = document.createElement('DIV');
349 a.setAttribute('id', this.id + '-autocomplete-list');
350 a.setAttribute('class', 'autocomplete-items');
351 /*append the DIV element as a child of the autocomplete container:*/
352 this.parentNode.appendChild(a);
353 /*for each item in the array...*/
354
355 var pattern = val.trim().split(/\s+/).filter(function (value) { return value.length > 2; }).join('|');
356 if (!pattern) return;
357 var exreg = new RegExp(pattern, 'iug');
358 var relevancy = [];
359 for (var i in arr.core) {
360 var ss, st, sto, sd, sdo;
361 var s = arr.core[i];
362 if ((ss = i.match(exreg))
363 || (s['title'] && (st = s['title'].match(exreg)))
364 || (s['title_original'] && (sto = s['title_original'].match(exreg)))
365 || (s['description'] && (sd = s['description'].match(exreg)))
366 || (s['description_original'] && (sdo = s['description_original'].match(exreg)))) {
367 relevancy.push({
368 setting: s,
369 option: {},
370 label: s['title'],
371 wpf_tab: i,
372 optname: '',
373 points: (ss ? ss.length * 3 : 0)
374 + (st ? st.length * 2 : 0)
375 + (sto ? sto.length * 2 : 0)
376 + (sd ? sd.length : 0)
377 + (sdo ? sdo.length : 0),
378 });
379 }
380
381 var os, ol, olo, od, odo;
382 for (var k in s['options']) {
383 var o = s['options'][k];
384 if ((os = k.match(exreg))
385 || (o['label'] && (ol = o['label'].match(exreg)))
386 || (o['label_original'] && (olo = o['label_original'].match(exreg)))
387 || (o['description'] && (od = o['description'].match(exreg)))
388 || (o['description_original'] && (odo = o['description_original'].match(exreg)))) {
389
390 relevancy.push({
391 label: o['label'],
392 setting: s,
393 option: o,
394 wpf_tab: i,
395 optname: k,
396 points: (os ? os.length * 4 : 0)
397 + (ol ? ol.length * 3 : 0)
398 + (olo ? olo.length * 3 : 0)
399 + (od ? od.length * 2 : 0)
400 + (odo ? odo.length * 2 : 0),
401 });
402 }
403 }
404
405 }
406
407 relevancy.sort(function (a, b) { return b.points - a.points; });
408 relevancy.forEach(function (value) {
409 var _page = value.setting.base && wpforo.board.has_more_boards ? 'wpforo-base-settings' : page;
410 if (!value.setting.base && _page === 'wpforo-base-settings') _page = 'wpforo-settings';
411 b = document.createElement('DIV');
412 if (value.optname) {
413 b.innerHTML = `<strong>OPTION:</strong>&nbsp;<a href="admin.php?page=${_page}&wpf_tab=${value.wpf_tab}#${value.optname}">${value.label} #${value.optname}</a>`;
414 } else {
415 b.innerHTML = `<strong>SETTINGS:</strong>&nbsp;<a href="admin.php?page=${_page}&wpf_tab=${value.wpf_tab}">${value.label}</a>`;
416 }
417 a.appendChild(b);
418 });
419
420 var scrto = relevancy.find(function (value) { return value.wpf_tab === wpf_tab && value.optname; });
421 if (scrto && window.location.hash !== '#' + scrto.optname) {
422 closeAllLists();
423 window.location.hash = '';
424 window.location.hash = scrto.optname;
425 }
426
427 });
428 /*execute a function presses a key on the keyboard:*/
429 inp.addEventListener('keydown', function (e) {
430 var x = document.getElementById(this.id + '-autocomplete-list');
431 if (x) x = x.getElementsByTagName('div');
432 if (e.code === 'ArrowDown') {
433 /*If the arrow DOWN key is pressed,
434 increase the currentFocus variable:*/
435 currentFocus++;
436 /*and make the current item more visible:*/
437 addActive(x);
438 } else if (e.code === 'ArrowUp') { //up
439 /*If the arrow UP key is pressed,
440 decrease the currentFocus variable:*/
441 currentFocus--;
442 /*and make the current item more visible:*/
443 addActive(x);
444 } else if (e.code === 'Home') {
445 currentFocus = 0;
446 addActive(x);
447 } else if (e.code === 'End') {
448 currentFocus = x.length - 1;
449 addActive(x);
450 } else if (e.code === 'Enter') {
451 /*If the ENTER key is pressed, prevent the form from being submitted,*/
452 e.preventDefault();
453 if (currentFocus > -1) {
454 /*and simulate a click on the "active" item:*/
455 if (x) x[currentFocus].querySelector('a').click();
456 }
457 }
458 });
459
460 function addActive (x) {
461 /*a function to classify an item as "active":*/
462 if (!x) return false;
463 /*start by removing the "active" class on all items:*/
464 removeActive(x);
465 if (currentFocus >= x.length) currentFocus = 0;
466 if (currentFocus < 0) currentFocus = (x.length - 1);
467 var autocomplete_items = document.querySelector('.autocomplete-items');
468 /*add class "autocomplete-active":*/
469 x[currentFocus].classList.add('autocomplete-active');
470 var delta = x[currentFocus].offsetTop - autocomplete_items.scrollTop;
471 if (delta < 0 || delta > 300) {
472 wpForoScrollTo(x[currentFocus].offsetTop - 117, undefined, document.querySelector('.autocomplete-items'));
473 }
474 }
475
476 function removeActive (x) {
477 /*a function to remove the "active" class from all autocomplete items:*/
478 for (var i = 0; i < x.length; i++) {
479 x[i].classList.remove('autocomplete-active');
480 }
481 }
482
483 function closeAllLists (elmnt) {
484 /*close all autocomplete lists in the document,
485 except the one passed as an argument:*/
486 var x = document.getElementsByClassName('autocomplete-items');
487 for (var i = 0; i < x.length; i++) {
488 if (elmnt != x[i] && elmnt != inp) {
489 x[i].parentNode.removeChild(x[i]);
490 }
491 }
492 }
493
494 /*execute a function when someone clicks in the document:*/
495 document.addEventListener('click', function (e) { closeAllLists(e.target); });
496 }
497
498 window.addEventListener('load', function () {
499 const chball = document.querySelector('input#all');
500 if (chball) {
501 const chbxs = [...document.querySelectorAll('.wpf-setcon-body form input[type=checkbox]:not(#all)')];
502 chbxs.forEach(function (chbx) {
503 chbx.addEventListener('change', function () {
504 chball.checked = false;
505 });
506 });
507
508 chball.addEventListener('change', function () {
509 chbxs.forEach((elmnt) => {
510 elmnt.checked = this.checked;
511 });
512 });
513 }
514 });
515