PluginProbe
wpForo Forum / 2.3.0
wpForo Forum v2.3.0
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 1.4.2 All 137 releases
wpforo / admin / assets / js / backend.js

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

493 lines 18.3 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 /* image adjust and upload from frontend */
57
58 function processfile( file, max_width, max_height, quality, callback ) {
59 if( !( /image/i ).test( file.type ) ) {
60 alert( "File "+ file.name +" is not an image." );
61 return false;
62 }
63
64 // read the files
65 var reader = new FileReader();
66 reader.readAsArrayBuffer(file);
67
68 reader.onload = function (event) {
69 // blob stuff
70 var blob = new Blob([event.target.result]); // create blob...
71 window.URL = window.URL || window.webkitURL;
72 var blobURL = window.URL.createObjectURL(blob); // and get its URL
73
74 // helper Image object
75 var image = new Image();
76 image.src = blobURL;
77 //preview.appendChild(image); // preview commented out, I am using the canvas instead
78 image.onload = function() {
79 // have to wait till it's loaded
80 var resized = resizeMe(image, max_width, max_height, quality); // send it to canvas
81 callback( resized );
82 }
83 };
84 }
85
86 // === RESIZE ====
87 function resizeMe( img, max_width, max_height, quality ) {
88 var canvas = document.createElement('canvas');
89 var width = img.width;
90 var height = img.height;
91
92 // calculate the width and height, constraining the proportions
93 if(width > height) {
94 if (width > max_width) {
95 //height *= max_width / width;
96 height = Math.round(height *= max_width / width);
97 width = max_width;
98 }
99 } else {
100 if (height > max_height) {
101 //width *= max_height / height;
102 width = Math.round(width *= max_height / height);
103 height = max_height;
104 }
105 }
106
107 // resize the canvas and draw the image data into it
108 canvas.width = width;
109 canvas.height = height;
110 var ctx = canvas.getContext("2d");
111 ctx.drawImage(img, 0, 0, width, height);
112
113 return canvas.toDataURL("image/jpeg", quality); // get the data from canvas as 70% JPG (can be also PNG, etc.)
114 }
115
116 function OpenFileDialog (accept, callback) {
117 // this function must be called from a user
118 // activation event (ie an onclick event)
119
120 // Create an input element
121 var inputElement = document.createElement("input");
122
123 // Set its type to file
124 inputElement.type = "file";
125
126 // Set accept to the file types you want the user to select.
127 // Include both the file extension and the mime type
128 inputElement.accept = accept;
129
130 // set onchange event to call callback when user has selected file
131 inputElement.addEventListener("change", callback)
132
133 // dispatch a click event to open the file dialog
134 inputElement.dispatchEvent(new MouseEvent("click"));
135 }
136
137 wpforo_admin_wrap.on('click', 'label', {}, function(){
138 $( '.wpf-edit-cover', $( this ).closest( '.wpf-opt-row-cover' ) ).trigger( 'click' );
139 });
140
141 // ***** -- cover image change -- ****** //
142 wpforo_admin_wrap.on( 'click', '.wpf-opt-row-cover .wpf-edit-cover:not(.wpf-processing)', {}, function(){
143 if ( !( window.File && window.FileReader && window.FileList && window.Blob ) ) {
144 alert('The File APIs are not fully supported in this browser.');
145 return false;
146 }
147 var $this = $( this );
148 OpenFileDialog('image/png,image/jpg,image/jpeg,image/gif', function(){
149 if( this.files.length ) {
150 $this.addClass( 'wpf-processing' );
151 $( '#wpf-admin-loading-extrawrap' ).show();
152 processfile(this.files[0], 1120, 460, 0.7, function (imageblob) {
153 $.ajax({
154 type: 'POST',
155 data: {
156 image_blob: imageblob,
157 action: 'wpforo_profiles_default_cover_upload',
158 _wpfnonce: wpforo['nonces']['wpforo_profiles_default_cover_upload'],
159 }
160 }).done(function(){
161 $this.closest('.wpf-cover').css('background-image', 'url(\'' + imageblob + '\')');
162 }).always(function(){
163 $this.removeClass('wpf-processing');
164 $( '#wpf-admin-loading-extrawrap' ).hide();
165 });
166 })
167 }
168 });
169 });
170 });
171
172 function get_parentid (arr, depth) {
173 for (var i = arr.length - 1; i >= 0; i--) {
174 if (arr[i]['depth'] == depth) return arr[i]['forumid']
175 }
176 }
177
178 function get_forums_hierarchy () {
179
180 var ul_content = document.getElementById('menu-to-edit')
181 var lis = ul_content.getElementsByTagName('LI')
182
183 var forums_hierarchy_arr = new Array()
184
185 for (var i = 0; i < lis.length; i++) {
186 forums_hierarchy_arr[i] = new Array()
187 forums_hierarchy_arr[i]['forumid'] = lis[i].id.replace('menu-item-', '')
188 var depth = lis[i].getAttribute('class').replace('menu-item menu-item-depth-', '')
189
190 forums_hierarchy_arr[i]['depth'] = depth
191
192 if (depth == 0) {
193 forums_hierarchy_arr[i]['parentid'] = 0
194 } else {
195 var previous_depth = depth - 1
196 forums_hierarchy_arr[i]['parentid'] = get_parentid(forums_hierarchy_arr, previous_depth)
197 }
198
199 forums_hierarchy_arr[i]['order'] = i + 1
200
201 var h_id = 'forumid-' + forums_hierarchy_arr[i]['forumid']
202 var h_parentid = 'parentid-' + forums_hierarchy_arr[i]['forumid']
203 var h_order = 'order-' + forums_hierarchy_arr[i]['forumid']
204
205 document.getElementById(h_id).value = forums_hierarchy_arr[i]['forumid']
206 document.getElementById(h_parentid).value = forums_hierarchy_arr[i]['parentid']
207 document.getElementById(h_order).value = forums_hierarchy_arr[i]['order']
208
209 }
210
211 document.getElementById('forum-hierarchy').submit()
212
213 }
214
215 function mode_changer (v) {
216 if (v) {
217 document.getElementById('forum_submit').value = wpforo_admin.phrases.move
218 document.getElementById('forum_select').disabled = false
219 } else {
220 document.getElementById('forum_submit').value = wpforo_admin.phrases.delete
221 document.getElementById('forum_select').disabled = true
222 }
223 }
224
225 function select_all () {
226 var sel_all = document.getElementById('cb-select-all-1')
227 var list = document.getElementById('the-list').getElementsByTagName('INPUT')
228 for (var i = 0; i < list.length; i++) document.getElementById(list[i].id).checked = !!sel_all.checked
229 }
230
231 function costum_or_inherit() {
232 var chack = document.getElementById('custom')
233 document.getElementById('permis').disabled = !!chack.checked;
234 }
235
236 function mode_changer_ug(v) {
237 document.getElementById('ug_select').disabled = !v;
238 }
239
240 function wpforo_scrollto_setting_field( location ){
241 if( location.hash ){
242 var scroll_to;
243 var exreg = new RegExp('&wpf_tab=([^=&?#\\s]+)', 'i');
244 var match = location.href.match(exreg);
245 if( match ){
246 var hash = location.hash.toString().slice(1);
247 var name = match[1] + '\\['+ hash +'\\]';
248 var wrap_row = jQuery( '[data-wpf-opt="'+ hash +'"]' );
249 if( wrap_row.length ){
250 scroll_to = wrap_row.offset().top - 150;
251 wpForoScrollTo(scroll_to, function () {
252 wrap_row.addClass("wpf-selected");
253 if( ! jQuery( '#wpf-opt-search-field' ).is(':focus') ){
254 var field = jQuery( '[name^='+ name +']', wrap_row );
255 field.trigger('focus');
256 field.trigger('select');
257 }
258 setTimeout(function () {
259 wrap_row.removeClass("wpf-selected");
260 }, 3000);
261 });
262 }
263 }
264 }
265 }
266
267 function wpforo_admin_tinymce_setup(editor){
268 editor.on('init', function(e) {
269 wpforo_scrollto_setting_field(window.location);
270 });
271 }
272
273 function wpForoScrollTo(top, callback, element) {
274 var html = element ? element : document.documentElement;
275 var current = html.scrollTop;
276 var delta = top - current;
277 var finish = function () {
278 html.scrollTop = top;
279 if (callback) {
280 callback();
281 }
282 };
283 if (!window.performance.now || delta === 0) {
284 finish();
285 return;
286 }
287 var transition = wpForoEaseOutQuad;
288 var max = 300;
289 if (delta < -max) {
290 current = top + max;
291 delta = -max;
292 } else if (delta > max) {
293 current = top - max;
294 delta = max;
295 } else {
296 transition = wpForoEaseInOutQuad;
297 }
298 var duration = 150;
299 var interval = 7;
300 var time = window.performance.now();
301 var animate = function () {
302 var now = window.performance.now();
303 if (now >= time + duration) {
304 finish();
305 return;
306 }
307 var dt = (now - time) / duration;
308 html.scrollTop = Math.round(current + delta * transition(dt));
309 setTimeout(animate, interval);
310 };
311 setTimeout(animate, interval);
312 }
313
314 function wpForoEaseOutQuad(t) {
315 return t * t;
316 }
317
318 function wpForoEaseInOutQuad(t) {
319 return (t < 0.5) ? (2 * t * t) : ((4 - 2 * t) * t - 1);
320 }
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 function addActive(x) {
460 /*a function to classify an item as "active":*/
461 if (!x) return false;
462 /*start by removing the "active" class on all items:*/
463 removeActive(x);
464 if (currentFocus >= x.length) currentFocus = 0;
465 if (currentFocus < 0) currentFocus = (x.length - 1);
466 var autocomplete_items = document.querySelector( '.autocomplete-items' );
467 /*add class "autocomplete-active":*/
468 x[currentFocus].classList.add("autocomplete-active");
469 var delta = x[currentFocus].offsetTop - autocomplete_items.scrollTop;
470 if( delta < 0 || delta > 300 ){
471 wpForoScrollTo( x[currentFocus].offsetTop - 117, undefined, document.querySelector( '.autocomplete-items' ) );
472 }
473 }
474 function removeActive(x) {
475 /*a function to remove the "active" class from all autocomplete items:*/
476 for (var i = 0; i < x.length; i++) {
477 x[i].classList.remove("autocomplete-active");
478 }
479 }
480 function closeAllLists(elmnt) {
481 /*close all autocomplete lists in the document,
482 except the one passed as an argument:*/
483 var x = document.getElementsByClassName("autocomplete-items");
484 for (var i = 0; i < x.length; i++) {
485 if (elmnt != x[i] && elmnt != inp) {
486 x[i].parentNode.removeChild(x[i]);
487 }
488 }
489 }
490 /*execute a function when someone clicks in the document:*/
491 document.addEventListener("click", function (e) { closeAllLists(e.target); });
492 }
493