PluginProbe
wpForo Forum / 3.2.1
wpForo Forum v3.2.1
3.2.1 3.2.0 3.1.7 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 All 141 releases
wpforo / assets / js / frontend.js

frontend.js in wpForo Forum 3.2.1, at assets/js/frontend.js

1,546 lines 52.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global wpforo */
2 var $wpf = Object.assign(window.jQuery);
3
4 // Mute jQuery Migrate Warnings
5 $wpf.migrateMute = true;
6
7 $wpf.fn.extend({
8 visible: function () {
9 return this.css('visibility', 'visible');
10 },
11 invisible: function () {
12 return this.css('visibility', 'hidden');
13 },
14 visibilityToggle: function () {
15 return this.css('visibility', function (i, visibility) {
16 return (visibility === 'visible') ? 'hidden' : 'visible';
17 });
18 },
19 showFlex: function () {
20 return this.css('display', 'flex');
21 },
22 wpfInsertAtCaret: function (myValue) {
23 return this.each(function () {
24 if (document.selection) {
25 //For browsers like Internet Explorer
26 this.focus();
27 var sel = document.selection.createRange();
28 sel.text = myValue;
29 } else if (this.selectionStart || this.selectionStart === 0) {
30 //For browsers like Firefox and Webkit based
31 var startPos = this.selectionStart;
32 var endPos = this.selectionEnd;
33 this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length);
34 this.selectionStart = startPos + myValue.length;
35 this.selectionEnd = startPos + myValue.length;
36 } else {
37 this.value += myValue;
38 }
39 });
40 },
41 isOnScreen: function (cbTrue, cbFalse) {
42 var win = $wpf(window);
43
44 var viewport = {
45 top: win.scrollTop(),
46 left: win.scrollLeft(),
47 };
48 viewport.right = viewport.left + win.width();
49 viewport.bottom = viewport.top + win.height();
50
51 var bounds = this.offset();
52 bounds.right = bounds.left + this.outerWidth();
53 bounds.bottom = bounds.top + this.outerHeight();
54
55 var isOnScreen = (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
56
57 if (!cbTrue && !cbFalse) {
58 return isOnScreen;
59 } else {
60 return isOnScreen
61 ? cbTrue && cbTrue(viewport, bounds)
62 : cbFalse && cbFalse(viewport, bounds);
63 }
64 },
65 });
66
67 // returns the cookie with the given name,
68 // or undefined if not found
69 function wpforo_getCookie (name) {
70 let matches = document.cookie.match(new RegExp(
71 '(?:^|; )' + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + '=([^;]*)',
72 ));
73 return matches ? decodeURIComponent(matches[1]) : undefined;
74 }
75
76 function wpforo_setCookie (name, value, options = {}) {
77
78 options = {
79 path: '/',
80 // add other defaults here if necessary
81 ...options,
82 };
83
84 if (options.expires instanceof Date) {
85 options.expires = options.expires.toUTCString();
86 }
87
88 let updatedCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value);
89
90 for (let optionKey in options) {
91 updatedCookie += '; ' + optionKey;
92 let optionValue = options[optionKey];
93 if (optionValue !== true) {
94 updatedCookie += '=' + optionValue;
95 }
96 }
97
98 document.cookie = updatedCookie;
99 }
100
101 function wpforo_deleteCookie (name) {
102 wpforo_setCookie(name, '', {
103 'max-age': -1,
104 });
105 }
106
107 function wpforo_get_browser_timezone () {
108 if (typeof Intl === 'object' && typeof Intl.DateTimeFormat === 'function') {
109 try {
110 const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
111 if (timeZone !== undefined && timeZone !== null) return timeZone;
112 } catch (error) {
113 console.error('Error accessing time zone:', error);
114 }
115 } else {
116 console.error('Intl.DateTimeFormat is not supported in this environment.');
117 }
118
119 return '';
120 }
121
122 /**
123 * Trigger a custom event.
124 *
125 * @param {Element|Document} target HTML element to dispatch the event on.
126 * @param {string} name Event name.
127 * @param [detail = null] Event addintional data information.
128 */
129 function wpforo_trigger_custom_event (target, name, detail) {
130 if (typeof detail === 'undefined') detail = null;
131 var event;
132 if (typeof CustomEvent === 'function') {
133 event = new CustomEvent(name, { bubbles: true, cancelable: true, detail: detail });
134 } else {
135 event = document.createEvent('Event');
136 event.initEvent(name, true, true);
137 event.detail = detail;
138 }
139
140 target.dispatchEvent(event);
141 window['wpforo_break_after_custom_event_'.name] = false;
142 }
143
144 function wpforo_tinymce_initializeIt (selector, do_not_focus) {
145 if (wpforo_editor.is_tinymce_loaded()) {
146 $wpf(selector).each(function () {
147 if (this.id) {
148 var editor_settings = window['wpforo_editor_settings_' + this.id] || wpforo['editor_settings'];
149 var settings = {
150 selector: '#' + this.id,
151 relative_urls: false,
152 remove_script_host: false,
153 convert_urls: false,
154 keep_styles: false,
155 end_container_on_empty_block: true,
156 wpeditimage_html5_captions: true,
157 force_br_newlines: false,
158 force_p_newlines: true,
159 menubar: false,
160 branding: false,
161 elementpath: true,
162 statusbar: true,
163 fix_list_elements: true,
164 browser_spellcheck: true,
165 entities: '38,amp,60,lt,62,gt',
166 entity_encoding: 'raw',
167 resize: 'vertical',
168 preview_styles: 'font-family font-size font-weight font-style text-decoration text-transform',
169 forced_root_block: '',
170 plugins: editor_settings['plugins'],
171 external_plugins: editor_settings['external_plugins'],
172 min_height: editor_settings['editor_height'],
173 indent: editor_settings['indent'],
174 height: editor_settings['editor_height'],
175 wpautop: editor_settings['wpautop'],
176 wp_keep_scroll_position: editor_settings['wp_keep_scroll_position'],
177 add_unload_trigger: editor_settings['add_unload_trigger'],
178 };
179 settings = Object.assign(settings, editor_settings['tinymce']);
180 tinymce.init(settings).then(function (e) {
181 if (!do_not_focus && e.length) {
182 wpforo_editor.focus(e[0].id);
183 wpforo_editor.set_active(e[0].id);
184 }
185 });
186
187 }
188 });
189 }
190 }
191
192 function wpforo_tinymce_setup (editor) {
193 editor.on('init', function (e) {
194 wpforo_trigger_custom_event(document, 'wpforo_tinymce_init', e);
195 });
196 editor.on('focus', function (e) {
197 wpforo_trigger_custom_event(document, 'wpforo_tinymce_focus', e);
198 wpforo_editor.set_active(editor.id);
199 });
200 editor.on('Dirty ExecCommand KeyPress SetContent', function (e) {
201 wpforo_trigger_custom_event(document, 'wpforo_tinymce_content_changed', e);
202 });
203 editor.on('paste', function (e) {
204 wpforo_trigger_custom_event(document, 'wpforo_tinymce_paste', e);
205 });
206 editor.shortcuts.add('ctrl+13', 'submit', function (e) {
207 wpforo_trigger_custom_event(document, 'wpforo_tinymce_ctrl_enter', e);
208 $wpf('form[data-textareaid="' + editor.id + '"]').find('[type=submit]').trigger('click');
209 });
210 editor.shortcuts.add('ctrl+s', 'Save Draft', function (e) {
211 wpforo_trigger_custom_event(document, 'wpforo_tinymce_ctrl_s', e);
212 });
213 }
214
215 var wpforo_editor = {
216 active_textareaid: '',
217 main_textareaid: '',
218 fix_textareaid: function (textareaid) {
219 if (typeof textareaid !== 'undefined') {
220 return textareaid;
221 } else if (this.active_textareaid) {
222 return this.active_textareaid;
223 } else {
224 var tinymce_active_editor_id = this.get_tinymce_active_editor_id();
225 if (tinymce_active_editor_id) {
226 this.active_textareaid = tinymce_active_editor_id;
227 return tinymce_active_editor_id;
228 }
229 }
230 return '';
231 },
232 get_active_textareaid: function () {
233 return this.fix_textareaid();
234 },
235 set_active: function (textareaid) {
236 if (this.is_exists(textareaid)) {
237 this.active_textareaid = textareaid;
238 if (this.is_tinymce(textareaid)) tinymce.setActive(tinymce.get(textareaid));
239 }
240 },
241 clear_active: function () {
242 this.active_textareaid = '';
243 },
244 set_main: function (textareaid, also_set_active) {
245 if (!textareaid) {
246 var wpforo_main_form = $wpf('form.wpforo-main-form[data-textareaid]');
247 if (wpforo_main_form.length) textareaid = wpforo_main_form.data('textareaid');
248 }
249 if (this.is_exists(textareaid)) {
250 this.main_textareaid = textareaid;
251 if (also_set_active) this.set_active(textareaid);
252 }
253 },
254 get_main: function () {
255 if (!this.main_textareaid) this.set_main();
256 return this.main_textareaid;
257 },
258 clear_main: function () {
259 this.main_textareaid = '';
260 },
261 get_tinymce_active_editor_id: function () {
262 if (this.is_tinymce_loaded() && typeof tinymce.activeEditor === 'object' && tinymce.activeEditor && tinymce.activeEditor.id) {
263 return tinymce.activeEditor.id;
264 }
265 return '';
266 },
267 is_tinymce_loaded: function () {
268 return typeof tinymce !== 'undefined';
269 },
270 is_tinymce: function (textareaid) {
271 textareaid = this.fix_textareaid(textareaid);
272 return !!(textareaid && this.is_tinymce_loaded() && tinymce.get(textareaid));
273 },
274 is_textarea: function (textareaid) {
275 textareaid = this.fix_textareaid(textareaid);
276 return !!(textareaid && !this.is_tinymce(textareaid) && $wpf('textarea#' + textareaid).length);
277 },
278 is_exists: function (textareaid) {
279 return !!(textareaid && this.is_tinymce(textareaid) || this.is_textarea(textareaid));
280 },
281 get_form: function (textareaid) {
282 textareaid = this.fix_textareaid(textareaid);
283 var textarea = $wpf('textarea[id="' + textareaid + '"]');
284 if (textarea.length) {
285 var form = textarea.closest('form');
286 if (form.length) return form;
287 }
288 return null;
289 },
290 get_form_body_wrap: function (textareaid) {
291 textareaid = this.fix_textareaid(textareaid);
292 var ed;
293 var body_wrap = null;
294 if (this.is_tinymce(textareaid)) {
295 ed = tinymce.get(textareaid);
296 if (ed && ed.iframeElement) {
297 body_wrap = ed.iframeElement.parentElement;
298 }
299 } else {
300 ed = document.getElementById(textareaid);
301 if (ed) {
302 body_wrap = ed.parentElement;
303 }
304 }
305 return body_wrap ? $wpf(body_wrap) : null;
306 },
307 scrollto: function (textareaid) {
308 textareaid = this.fix_textareaid(textareaid);
309 var scrollto = null;
310 var bodyWrap = this.get_form_body_wrap(textareaid);
311 if (bodyWrap !== null) scrollto = bodyWrap.offset().top - 100;
312 if (scrollto !== null && !bodyWrap.isOnScreen()) {
313 $wpf('html').scrollTop(scrollto);
314 }
315 },
316 tinymce_focus: function (textareaid, caret_to_end) {
317 textareaid = this.fix_textareaid(textareaid);
318 if (this.is_tinymce(textareaid)) {
319 this.scrollto(textareaid);
320 var focus_mce = tinymce.get(textareaid);
321 focus_mce.focus();
322 if (caret_to_end) {
323 focus_mce.selection.select(focus_mce.getBody(), true);
324 focus_mce.selection.collapse(false);
325 }
326 }
327 },
328 textarea_focus: function (textareaid, caret_to_end) {
329 textareaid = this.fix_textareaid(textareaid);
330 if (this.is_textarea(textareaid)) {
331 this.scrollto(textareaid);
332 var textarea = $wpf('textarea#' + textareaid);
333 var textarea_val = textarea.val();
334 textarea.trigger('focus');
335 if (caret_to_end) {
336 textarea.val('');
337 textarea.val(textarea_val);
338 }
339 }
340 },
341 focus: function (textareaid, caret_to_end) {
342 textareaid = this.fix_textareaid(textareaid);
343 if (this.is_tinymce(textareaid)) {
344 this.tinymce_focus(textareaid, caret_to_end);
345 } else if (this.is_textarea(textareaid)) {
346 this.textarea_focus(textareaid, caret_to_end);
347 }
348 },
349 insert_content: function (content, textareaid, format, focus) {
350 textareaid = this.fix_textareaid(textareaid);
351 format = format ? format : 'raw';
352 if (focus === undefined) focus = true;
353 if (this.is_tinymce(textareaid)) {
354 tinymce.get(textareaid).insertContent(content, { format: format });
355 if (focus) this.tinymce_focus(textareaid);
356 } else if (this.is_textarea(textareaid)) {
357 $wpf('textarea#' + textareaid).wpfInsertAtCaret(content);
358 if (focus) this.textarea_focus(textareaid);
359 }
360 },
361 set_content: function (content, textareaid, format, focus) {
362 textareaid = this.fix_textareaid(textareaid);
363 format = format ? format : 'raw';
364 if (focus === undefined) focus = true;
365 if (this.is_tinymce(textareaid)) {
366 tinymce.get(textareaid).setContent(content, { format: format });
367 if (focus) this.tinymce_focus(textareaid, true);
368 } else if (this.is_textarea(textareaid)) {
369 $wpf('textarea#' + textareaid).val(content);
370 if (focus) this.textarea_focus(textareaid, true);
371 }
372 },
373 get_content: function (format, textareaid) {
374 textareaid = this.fix_textareaid(textareaid);
375 format = format ? format : 'text';
376 var content = '';
377 if (this.is_tinymce(textareaid)) {
378 content = tinymce.get(textareaid).getContent({ format: format });
379 } else if (this.is_textarea(textareaid)) {
380 content = $wpf('textarea#' + textareaid).val();
381 if (format === 'text' && content) {
382 content = content.replace(/<(iframe|embed)[^<>]*?>.*?<\/\1>/gi, '');
383 content = content.replace(/(<([^<>]+?)>)/gi, '');
384 }
385 }
386 return content.trim();
387 },
388 get_stats: function (textareaid) {
389 textareaid = this.fix_textareaid(textareaid);
390
391 var text = this.get_content('text', textareaid);
392 var raw_text = this.get_content('raw', textareaid);
393 var chars = text.length;
394 var words = text.split(/[\w\u2019'-]+/).length - 1;
395 var imgs = (raw_text.match(/<img[^<>]*?src=['"][^'"]+?['"][^<>]*?>/gi) || []).length;
396 var links = (raw_text.match(/<a[^<>]*?href=['"][^'"]+?['"][^<>]*?>.+?<\/a>/gi) || []).length;
397 var embeds = (raw_text.match(/<(iframe|embed)[^<>]*?>.*?<\/\1>/gi) || []).length;
398
399 return {
400 chars: chars,
401 words: words,
402 imgs: imgs,
403 links: links,
404 embeds: embeds,
405 has_content: !!(chars || imgs || links || embeds),
406 };
407 },
408 };
409
410 function wpforo_notice_get_timeout (type) {
411 if (!type) type = 'neutral';
412 if (wpforo.notice.timeouts[type] !== undefined) return parseInt(wpforo.notice.timeouts[type]);
413 return 8000;
414 }
415
416 function wpforo_notice_clear () {
417 var msg_box = $wpf('#wpf-msg-box');
418 msg_box.hide();
419 msg_box.empty();
420 }
421
422 function wpforo_notice_show (notice, type) {
423 if (!notice) return;
424 type = (type === 'success' || type === 'error' ? type : 'neutral');
425
426 var n = notice.search(/<p(?:\s[^<>]*?)?>/i);
427 if (n < 0) {
428 var phrase = wpforo_phrase(notice);
429 if (arguments.length > 2) {
430 for (var i = 2; i < arguments.length; i++) {
431 if (arguments[i] !== undefined) phrase = phrase.replace(/%[dfs]/, arguments[i]);
432 }
433 }
434 notice = '<p class="' + type + '">' + phrase + '</p>';
435 }
436
437 notice = $wpf(notice);
438 $wpf('#wpforo-notifications-bar').appendTo('body');
439 var msg_box = $wpf('#wpf-msg-box');
440 msg_box.append(notice);
441 msg_box.show(150);
442 var timeout = wpforo_notice_get_timeout(type);
443 if (timeout) {
444 notice.delay(timeout).fadeOut(200, function () {
445 $wpf(this).remove();
446 });
447 }
448 }
449
450 function wpforo_notice_hide () {
451 $wpf('#wpf-msg-box').hide();
452 }
453
454 function wpforo_load_show (msg) {
455 msg = typeof msg !== 'undefined' ? msg : 'Working';
456 msg = String(msg);
457 msg = wpforo_phrase(msg);
458 $wpf('#wpforo-notifications-bar').appendTo('body');
459 var load = $wpf('#wpforo-load');
460 $wpf('.loadtext', load).text(msg);
461 load.showFlex();
462 }
463
464 function wpforo_load_hide () {
465 $wpf('#wpforo-load').hide();
466 }
467
468 function wpforo_init_dialog () {
469 $wpf('#wpforo-dialog-extra-wrap').on('click', '#wpforo-dialog-close', function () {
470 wpforo_dialog_hide();
471 });
472 $wpf(document).on('mousedown', '#wpforo-dialog-extra-wrap', function (e) {
473 if (!$wpf(e.target).closest('#wpforo-dialog').length) wpforo_dialog_hide();
474 });
475 $wpf(document).on('keydown', function (e) {
476 if (e.code === 'Escape') wpforo_dialog_hide();
477 });
478 }
479
480 function wpforo_dialog_show (title, content, w, h) {
481 var dialog = $wpf('#wpforo-dialog');
482 if (content) {
483 var dialog_body = $wpf('#wpforo-dialog-body', dialog);
484 dialog_body.children().appendTo('#wpforo-dialog-backups');
485 dialog_body.empty();
486 if (content instanceof $wpf || content instanceof Element) {
487 content = $wpf(content);
488 content.appendTo(dialog_body);
489 content.show();
490 content.css('visibility', 'visible');
491 if (!title) title = content.data('title');
492 } else if (typeof content === 'string') {
493 dialog_body.html(content);
494 }
495 }
496 if (title) $wpf('#wpforo-dialog-title', dialog).html(wpforo_phrase(title));
497 if (w) dialog.css('width', w);
498 if (h) dialog.css('height', h);
499 $wpf('#wpforo-dialog-extra-wrap').appendTo('body');
500 $wpf('html').addClass('wpforo-dialog-visible');
501 $wpf('body').addClass('wpforo-dialog-visible animated fadeIn');
502 }
503
504 function wpforo_dialog_hide () {
505 $wpf('html').removeClass('wpforo-dialog-visible');
506 $wpf('body').removeClass('wpforo-dialog-visible animated fadeIn');
507 }
508
509 function wpforo_phrase (phrase_key) {
510 // if( !(window.wpforo_phrases && typeof window.wpforo_phrases === 'object' && Object.keys(window.wpforo_phrases).length) ) wpforo_init_phrases();
511 if (window.wpforo_phrases && typeof window.wpforo_phrases === 'object' && Object.keys(window.wpforo_phrases).length) {
512 var phrase_key_lower = phrase_key.toLowerCase();
513 if (window.wpforo_phrases[phrase_key_lower] !== undefined) phrase_key = window.wpforo_phrases[phrase_key_lower];
514 }
515 return phrase_key;
516 }
517
518 function wpforo_getTextSelection () {
519 $wpf('#wpf_multi_quote').remove();
520 if (window.getSelection) {
521 var sel = window.getSelection();
522 if (sel && sel.anchorNode && sel.anchorNode.parentNode && sel.anchorNode.parentNode.tagName !== 'A') {
523 var selectedText = sel.toString().trim();
524 if (sel.rangeCount && selectedText.length) {
525 var getRangeAt_0 = sel.getRangeAt(0);
526 var rangeBounding = getRangeAt_0.getBoundingClientRect();
527 var bodyBounding = document.documentElement.getBoundingClientRect();
528 var left = rangeBounding.left + rangeBounding.width / 2 + Math.abs(bodyBounding.left) - 15;
529 var top = rangeBounding.bottom + Math.abs(bodyBounding.top) + 50;
530
531 var parent = $wpf(getRangeAt_0.commonAncestorContainer).closest('.wpforo-post-content, .wpforo-comment-content');
532 var noNeedParent = $wpf(getRangeAt_0.commonAncestorContainer).closest('.wpforo-post-signature, .wpforo-post-content-bottom, .wpf-post-button-actions');
533 var noNeedChild = $wpf(getRangeAt_0.endContainer).closest('.wpforo-post-signature, .wpforo-post-content-bottom, .wpf-post-button-actions');
534
535 if (parent.length && !noNeedParent.length && !noNeedChild.length) {
536 var toolTip = $wpf('<div id="wpf_multi_quote"></div>');
537 toolTip.css({ top: top, left: left });
538 var link = $wpf('<span class="wpf-multi-quote" title="' + wpforo_phrase('Quote this text') + '"><i class="fas fa-quote-left"></i></span>').on('mousedown touchstart', function () {
539 var container = document.createElement('div');
540 for (var i = 0; i < sel.rangeCount; ++i) container.appendChild(sel.getRangeAt(i).cloneContents());
541 var post_wrap = $wpf(getRangeAt_0.startContainer).parents('[data-postid]');
542 var userid = post_wrap.data('userid');
543 if (!userid) userid = 0;
544 var postid = post_wrap.data('postid');
545 if (!postid) postid = 0;
546 var editorContent = '';
547 if (wpforo_editor.is_tinymce()) {
548 editorContent = '[quote data-userid="' + userid + '" data-postid="' + postid + '"]<p>' + container.innerHTML.replace(/\s*data-[\w-]+="[^"]*?"/gi, '') + '</p>[/quote]<p></p>';
549 } else {
550 editorContent = '[quote data-userid="' + userid + '" data-postid="' + postid + '"]' + container.innerHTML.replace(/\s*data-[\w-]+="[^"]*?"/gi, '') + '[/quote]';
551 }
552 wpforo_editor.insert_content(editorContent);
553 $wpf(this).remove();
554 });
555 toolTip.append(link);
556 $wpf('body').append(toolTip);
557 }
558 }
559
560 }
561 }
562 }
563
564 window.wpforo_fix_form_data_attributes = function () {
565 $wpf('form textarea[data-isbody=1]:first').each(function () {
566 var form = $wpf(this).closest('form');
567 var id = $wpf(this).attr('id');
568 form.attr('data-textareaid', id);
569 form.prop('data-textareaid', id);
570 form.data('textareaid', id);
571 });
572 };
573
574 $wpf(document).ready(function ($) {
575 var iwpfp = $('body.is_wpforo_page-1');
576 if (iwpfp.length) $('html').addClass('is_wpforo_page-1');
577
578 var wpforo_wrap = $('#wpforo-wrap');
579
580 wpforo_setCookie('wpforo_browser_timezone', wpforo_get_browser_timezone(), { secure: true, 'max-age': 86400 });
581
582 var scroll_to;
583 var exreg = new RegExp('\/' + wpforo.settings_slugs['postid'] + '\/(\\d+)\/?$', 'i');
584 var match = location.pathname.match(exreg);
585 if (match) {
586 scroll_to = $('#post-' + match[1]);
587 } else {
588 //scroll_to = $("#m_, .wpforo-members-content, .wpforo-search-content", wpforo_wrap);
589 }
590 if (scroll_to !== undefined && scroll_to.length) {
591 $('html, body').scrollTop(scroll_to.offset().top - 25);
592 }
593
594 wpforo_init_dialog();
595
596 if ($('form.wpforo-main-form').length) {
597 document.onselectionchange = function () {
598 wpforo_getTextSelection();
599 };
600 }
601
602 window.onbeforeunload = function (e) {
603 var forms = $('form[data-textareaid]').not(':hidden');
604 if (forms.length) {
605 var i, textareaid;
606 for (i = 0; i < forms.length; i++) {
607 textareaid = $(forms[i]).data('textareaid');
608 if (wpforo_editor.get_stats(textareaid).has_content) {
609 e = e || window.event;
610 e.returnValue = wpforo_phrase('Write something clever here..');
611 return wpforo_phrase('Write something clever here..');
612 }
613 }
614 }
615 };
616
617 window.wpforo_fix_form_data_attributes();
618 wpforo_tinymce_initializeIt('[data-wpforoeditor="tinymce"]', true);
619
620 setTimeout(function () {
621 wpforo_editor.fix_textareaid();
622 wpforo_editor.set_main('', true);
623
624 var forum_sels = $('.wpf-topic-form-extra-wrap .wpf-topic-form-forumid', wpforo_wrap);
625 if (forum_sels.length) {
626 forum_sels.each(function (i, f) {
627 f = $(f);
628 var forum_opts = $('option:not([value="0"]):not([disabled])', f);
629 if (forum_opts.length === 1) {
630
631 var wpf_topic_form_extra_wrap = f.closest('.wpf-topic-form-extra-wrap');
632 wpf_topic_form_extra_wrap.attr('data-is_just_one_forum', true);
633 wpf_topic_form_extra_wrap.prop('data-is_just_one_forum', true);
634 wpf_topic_form_extra_wrap.data('is_just_one_forum', true);
635
636 f.val(forum_opts[0].getAttribute('value')).trigger('change');
637 }
638 });
639 }
640
641 }, 1000);
642
643 wpforo_wrap.on('click drop', 'form[data-textareaid]', function () {
644 var textareaid = $(this).data('textareaid');
645 wpforo_editor.set_active(textareaid);
646 });
647
648 wpforo_wrap.on('focus', 'form[data-textareaid] textarea', function () {
649 var textareaid = $(this).parents('form[data-textareaid]').data('textareaid');
650 if (textareaid === this.id) wpforo_editor.set_active(this.id);
651 });
652
653 wpforo_wrap.on('keydown', 'form[data-textareaid]', function (e) {
654 if ((e.ctrlKey || e.metaKey) && (e.code === 'Enter' || e.code === 'NumpadEnter')) {
655 $('[type=submit]', $(this)).trigger('click');
656 } else if (((e.ctrlKey || e.metaKey) && e.code === 'KeyS') || e.code === 'Pause' || e.code === 'MediaPlayPause') {
657 wpforo_trigger_custom_event(document, 'wpforo_textarea_ctrl_s', e);
658 e.preventDefault();
659 return false;
660 }
661 });
662
663 if ($('.wpforo-recent-content .wpf-p-error', wpforo_wrap).length) { $('.wpf-navi', wpforo_wrap).remove(); }
664
665 /**
666 * prevent multi submitting
667 * disable form elements for 10 seconds
668 */
669 window.wpforo_prev_submit_time = 0;
670 wpforo_wrap.on('submit', 'form', function (e) {
671 if (window.wpforo_prev_submit_time) {
672 if (Date.now() - window.wpforo_prev_submit_time < 10000) return false;
673 } else {
674 var textareaid = $(this).data('textareaid');
675 if (textareaid) {
676 var bodyminlength = $(this).data('bodyminlength');
677 var bodymaxlength = $(this).data('bodymaxlength');
678 if (bodyminlength || bodymaxlength) {
679 var body_stat = wpforo_editor.get_stats(textareaid);
680 if (bodyminlength) {
681 if (body_stat.chars < bodyminlength && !body_stat.embeds && !body_stat.links && !body_stat.imgs) {
682 wpforo_notice_show('Content characters length must be greater than %d', 'error', bodyminlength);
683 return false;
684 }
685 }
686 if (bodymaxlength) {
687 if (body_stat.chars > bodymaxlength) {
688 wpforo_notice_show('Content characters length must be smaller than %d', 'error', bodymaxlength);
689 return false;
690 }
691 }
692 }
693
694 wpforo_trigger_custom_event(document, 'wpforo_post_submit', { e, textareaid });
695 if (window['wpforo_break_after_custom_event_wpforo_post_submit']) {
696 window['wpforo_break_after_custom_event_wpforo_post_submit'] = false;
697 return false;
698 }
699 }
700
701 wpforo_load_show();
702 window.wpforo_prev_submit_time = Date.now();
703 window.onbeforeunload = null;
704 setTimeout(function () {
705 window.wpforo_prev_submit_time = 0;
706 wpforo_load_hide();
707 }, 10000);
708 }
709 });
710
711 wpforo_wrap.on('click', '.wpf-spoiler-head', function () {
712 var spoiler_wrap = $(this).parents('.wpf-spoiler-wrap');
713 if (spoiler_wrap.length) {
714 spoiler_wrap = $(spoiler_wrap[0]);
715 if (!spoiler_wrap.hasClass('wpf-spoiler-processing')) {
716 spoiler_wrap.toggleClass('wpf-spoiler-open').addClass('wpf-spoiler-processing');
717 var spoiler_body = $('.wpf-spoiler-body', spoiler_wrap);
718 if (spoiler_body.length) {
719 var spoiler_chevron = $('.wpf-spoiler-chevron', spoiler_wrap);
720 $(spoiler_chevron[0]).toggleClass('fa-chevron-down fa-chevron-up');
721 $(spoiler_body[0]).slideToggle(500, function () {
722 spoiler_wrap.removeClass('wpf-spoiler-processing');
723 if (!spoiler_wrap.hasClass('wpf-spoiler-open')) {
724 $('.wpf-spoiler-wrap.wpf-spoiler-open .wpf-spoiler-head', spoiler_wrap).trigger('click');
725 }
726 });
727 }
728 }
729 }
730 });
731
732 wpforo_wrap.on('click', '#add_wpftopic:not(.not_reg_user)', function () {
733 var form = $('.wpf-topic-create');
734 $(this).attr('disabled', 'disabled');
735 form.slideToggle('slow', () => {
736 var stat = form.is(':hidden');
737 if (!window.add_wpftopic_phrase) window.add_wpftopic_phrase = $(this).html();
738 var add_wpftopic = (stat ? window.add_wpftopic_phrase : '<i class="fas fa-times" aria-hidden="true"></i>');
739 $(this).html(add_wpftopic);
740 wpforo_editor.set_content('');
741 $('[name="thread[title]"]').trigger('focus');
742 $('html').scrollTop(($(this).offset().top - 35));
743 $(this).removeAttr('disabled');
744 });
745 });
746
747 wpforo_wrap.on('click', '.wpf-answer-button .wpf-button:not(.not_reg_user)', function () {
748 $(this).closest('.wpf-bottom-bar').hide();
749 });
750
751 wpforo_wrap.on('click', '.wpforo-section .add_wpftopic:not(.not_reg_user)', function () {
752 var wrap = $(this).parents('div.wpforo-section');
753 var form_wrap = $('.wpf-topic-form-extra-wrap', wrap);
754
755 var is_just_one_forum = form_wrap.data('is_just_one_forum');
756 if (!is_just_one_forum) $('.wpf-topic-form-ajax-wrap').empty();
757 var stat = form_wrap.is(':hidden');
758 $('.wpf-topic-form-extra-wrap').slideUp('slow');
759 var add_wpftopic;
760 if (stat) {
761 add_wpftopic = '<i class="fas fa-times" aria-hidden="true"></i>';
762 form_wrap.slideDown('slow');
763 } else {
764 add_wpftopic = '<i class="fas fa-feather-alt" aria-hidden="true"></i>' + $(this).data('phrase');
765 form_wrap.slideUp('slow');
766 }
767 if (!is_just_one_forum) {
768 var option_no_selected = $('option.wpf-topic-form-no-selected-forum');
769 option_no_selected.show();
770 option_no_selected.prop('selected', true);
771 }
772 $(this).html(add_wpftopic);
773 $('html').scrollTop((wrap.offset().top - 30));
774 });
775
776 wpforo_wrap.on('click', '.not_reg_user', function () {
777 wpforo_load_show();
778 wpforo_notice_show(wpforo.notice.login_or_register);
779 wpforo_load_hide();
780 });
781
782 $(document).on('click', '#wpf-msg-box p', function () {
783 $(this).remove();
784 });
785
786 /* Home page loyouts toipcs toglle */
787 wpforo_wrap.on('click', '.topictoggle', function () {
788 wpforo_load_show();
789
790 var id = $(this).attr('id');
791
792 id = id.replace('img-arrow-', '');
793 $('.wpforo-last-topics-' + id).slideToggle('slow');
794 if ($(this).hasClass('topictoggle') && $(this).hasClass('fa-chevron-down')) {
795 $('#img-arrow-' + id).removeClass('fa-chevron-down').addClass('fa-chevron-up');
796 } else {
797 $('#img-arrow-' + id).removeClass('fa-chevron-up').addClass('fa-chevron-down');
798 }
799
800 id = id.replace('button-arrow-', '');
801 $('.wpforo-last-posts-' + id).slideToggle('slow');
802 if ($(this).hasClass('topictoggle') && $(this).hasClass('wpfcl-0') && $(this).hasClass('fa-chevron-down')) {
803 $('#button-arrow-' + id).removeClass('fa-chevron-down').addClass('fa-chevron-up');
804 } else {
805 $('#button-arrow-' + id).removeClass('fa-chevron-up').addClass('fa-chevron-down');
806 }
807
808 wpforo_load_hide();
809 });
810
811 /* Home page loyouts toipcs toglle */
812 wpforo_wrap.on('click', '.wpforo-membertoggle', function () {
813 var id = $(this).attr('id');
814 id = id.replace('wpforo-memberinfo-toggle-', '');
815 $('#wpforo-memberinfo-' + id).slideToggle('slow');
816 if ($(this).find('i').hasClass('fa-caret-down')) {
817 $(this).find('i').removeClass('fa-caret-down').addClass('fa-caret-up');
818 } else {
819 $(this).find('i').removeClass('fa-caret-up').addClass('fa-caret-down');
820 }
821 });
822
823 /* Threaded Layout Hide Replies */
824 wpforo_wrap.on('click', '.wpf-post-replies-bar', function () {
825 var id = $(this).attr('id');
826 id = id.replace('wpf-ttgg-', '');
827 $('#wpf-post-replies-' + id).slideToggle('slow');
828 var $angleIcon = $(this).find('.wpforo-ttgg i');
829 if ($angleIcon.hasClass('fa-angle-down')) {
830 $angleIcon.removeClass('fa-angle-down').addClass('fa-angle-up');
831 $(this).find('.wpforo-ttgg').attr('wpf-tooltip', wpforo_phrase('Hide Replies'));
832 } else {
833 $angleIcon.removeClass('fa-angle-up').addClass('fa-angle-down');
834 $(this).find('.wpforo-ttgg').attr('wpf-tooltip', wpforo_phrase('Show Replies'));
835 }
836 });
837
838 //Reply
839 wpforo_wrap.on('click', '.wpforo-reply:not(.wpforo_layout_4)', function () {
840 wpforo_load_show();
841
842 var main_form = $('form.wpforo-main-form[data-textareaid]');
843 var wrap = main_form.closest('.wpf-form-wrapper');
844 wrap.show();
845
846 $('.wpf-reply-form-title').html(wpforo_phrase('Leave a reply'));
847
848 var post_wrap = $(this).closest('[id^=post-][data-postid]');
849 var parentpostid = post_wrap.data('postid');
850 if (!parentpostid) parentpostid = 0;
851 $('.wpf-form-post-parentid', main_form).val(parentpostid);
852
853 var userid = parseInt(post_wrap.data('userid'));
854 var mention = post_wrap.data('mention');
855 var isowner = parseInt(post_wrap.data('isowner'));
856 var content = (!isowner && userid && mention ? '@' + mention + (wpforo_editor.is_tinymce(wpforo_editor.get_main()) ? '&nbsp;' : ' ') : '');
857
858 wpforo_editor.set_content(content, wpforo_editor.get_main());
859
860 $('html').scrollTop(wrap.offset().top);
861
862 wpforo_load_hide();
863
864 });
865
866 //Answer
867 wpforo_wrap.on('click', '.wpforo-answer', function () {
868 wpforo_load_show();
869
870 var main_form = $('form.wpforo-main-form[data-textareaid]');
871 var wrap = main_form.closest('.wpf-form-wrapper');
872 wrap.show();
873
874 $('.wpf-reply-form-title').html(wpforo_phrase('Your answer'));
875
876 $('.wpf-form-postid', main_form).val(0);
877 $('.wpf-form-post-parentid', main_form).val(0);
878
879 var post_wrap = $(this).closest('[id^=post-][data-postid]');
880
881 var userid = parseInt(post_wrap.data('userid'));
882 var mention = post_wrap.data('mention');
883 var isowner = parseInt(post_wrap.data('isowner'));
884 var content = (!isowner && userid && mention ? '@' + mention + (wpforo_editor.is_tinymce(wpforo_editor.get_main()) ? '&nbsp;' : ' ') : '');
885
886 wpforo_editor.set_content(content, wpforo_editor.get_main());
887
888 $('html').scrollTop(wrap.offset().top);
889
890 wpforo_load_hide();
891
892 });
893
894 wpforo_wrap.on('click', '.wpforo-qa-comment, .wpforo-reply.wpf-action.wpforo_layout_4', function () {
895 var wrap = $(this).parents('.reply-wrap,.wpforo-qa-item-wrap');
896 var post_wrap = $('.post-wrap', wrap);
897 if (!post_wrap.length) post_wrap = wrap;
898 var parentid = post_wrap.data('postid');
899 if (!parentid) parentid = post_wrap.attr('id').replace('post-', '');
900 if (!parentid) parentid = 0;
901 var form = $('.wpforo-post-form');
902 var textareaid = form.data('textareaid');
903 var textarea_wrap = $('.wpf_post_form_textarea_wrap', form);
904 var textarea = $('#' + textareaid, textarea_wrap);
905 var textareatype = textarea_wrap.data('textareatype');
906 $('.wpf_post_parentid').val(parentid);
907 $('.wpforo-qa-comment,.wpforo-reply.wpf-action.wpforo_layout_4').show();
908 $(this).hide();
909 $('.wpforo-portable-form-wrap', wrap).show();
910 if (!$('.wpforo-post-form', wrap).length) form.appendTo($('.wpforo-portable-form-wrap', wrap));
911
912 form.show();
913 if (textareatype && textareatype === 'rich_editor') {
914 textarea_wrap.html('<textarea id="' + textareaid + '" class="wpf_post_body" name="post[body]"></textarea>');
915 wpforo_tinymce_initializeIt('#' + textareaid);
916 } else {
917 textarea.val('');
918 textarea.trigger('focus');
919 }
920
921 var userid = parseInt(post_wrap.data('userid'));
922 var mention = post_wrap.data('mention');
923 var isowner = parseInt(post_wrap.data('isowner'));
924 var content = (!isowner && userid && mention ? '@' + mention + (wpforo_editor.is_tinymce(textareaid) ? '&nbsp;' : ' ') : '');
925
926 wpforo_editor.set_content(content, textareaid);
927 });
928
929 wpforo_wrap.on('click', '.wpf-button-close-form', function () {
930 $(this).parents('.wpforo-portable-form-wrap').hide();
931 $('.wpforo-post-form').hide();
932 $('.wpforo-qa-comment,.wpforo-reply.wpf-action.wpforo_layout_4').show();
933 wpforo_editor.set_content('');
934 });
935
936 //mobile menu responsive toggle
937 wpforo_wrap.on('click', '#wpforo-menu .wpf-res-menu', function () {
938 $('#wpforo-menu .wpf-menu').toggle();
939 });
940 var wpfwin = $(window).width();
941 var wpfwrap = wpforo_wrap.width();
942 if (wpfwin >= 602 && wpfwrap < 800) {
943 wpforo_wrap.on('focus', '#wpforo-menu .wpf-search-field', function () {
944 $('#wpforo-menu .wpf-menu li').hide();
945 wpforo_wrap.find('#wpforo-menu .wpf-res-menu').show();
946 $('#wpforo-menu .wpf-search-field').css('transition-duration', '0s');
947 });
948 wpforo_wrap.on('blur', '#wpforo-menu .wpf-search-field', function () {
949 wpforo_wrap.find('#wpforo-menu .wpf-res-menu').hide();
950 $('#wpforo-menu .wpf-menu li').show();
951 $('#wpforo-menu .wpf-search-field').css('transition-duration', '0.4s');
952 });
953 }
954
955 // password show/hide switcher */
956 wpforo_wrap.on('click', '.wpf-show-password', function () {
957 var btn = $(this);
958 var parent = btn.parents('.wpf-field-wrap');
959 var input = $(':input', parent);
960 if (input.attr('type') === 'password') {
961 input.attr('type', 'text');
962 btn.removeClass('fa-eye-slash');
963 btn.addClass('fa-eye');
964 } else {
965 input.attr('type', 'password');
966 btn.removeClass('fa-eye');
967 btn.addClass('fa-eye-slash');
968 }
969 });
970
971 //Turn off on dev mode
972 //$(window).on('resize', function(){ if (window.RT) { clearTimeout(window.RT); } window.RT = setTimeout(function(){ this.location.reload(false);}, 100); });
973
974 wpforo_wrap.on('change', '#wpforo_split_form #wpf_split_create_new', function () {
975 var checked = $('#wpf_split_create_new').is(':checked'),
976 target_url = $('#wpf_split_target_url'),
977 append = $('#wpf_split_append'),
978 new_title = $('#wpf_split_new_title'),
979 forumid = $('#wpf_split_forumid');
980 if (checked) {
981 target_url.children('input').prop('disabled', true);
982 target_url.hide();
983 append.children('input').prop('disabled', true);
984 append.hide();
985 new_title.children('input').prop('disabled', false);
986 new_title.show();
987 forumid.children('select').prop('disabled', false);
988 forumid.show();
989 } else {
990 target_url.children('input').prop('disabled', false);
991 target_url.show();
992 append.children('input').prop('disabled', false);
993 append.show();
994 new_title.children('input').prop('disabled', true);
995 new_title.hide();
996 forumid.children('select').prop('disabled', true);
997 forumid.hide();
998 }
999 });
1000
1001 //Facebook Share Buttons
1002 wpforo_wrap.on('click', '.wpf-fb', function () {
1003 var item_url = $(this).data('wpfurl');
1004 // Facebook deprecated custom parameters - content comes from Open Graph meta tags
1005 var share_url = 'https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(item_url);
1006 window.open(share_url, 'facebook-share', 'width=580,height=400');
1007 });
1008 //Share Buttons Toggle
1009 wpforo_wrap.on('mouseover', '.wpf-sb', function () {
1010 $(this).find('.wpf-sb-toggle').find('i').addClass('wpfsa');
1011 $(this).find('.wpf-sb-buttons').show();
1012 });
1013 wpforo_wrap.on('mouseout', '.wpf-sb', function () {
1014 $(this).find('.wpf-sb-toggle').find('i').removeClass('wpfsa');
1015 $(this).find('.wpf-sb-buttons').hide();
1016 });
1017 wpforo_wrap.on('mouseover', '.wpf-sb-toggle', function () {
1018 $(this).next().filter('.wpf-sb-buttons').parent().find('i').addClass('wpfsa');
1019 });
1020 wpforo_wrap.on('mouseout', '.wpf-sb-toggle', function () {
1021 $(this).next().filter('.wpf-sb-buttons').parent().find('i').removeClass('wpfsa');
1022 });
1023
1024 //Forum Rules
1025 wpforo_wrap.on('click', '#wpf-open-rules', function () {
1026 $('.wpforo-legal-rules').toggle();
1027 return false;
1028 });
1029 wpforo_wrap.on('click', '#wpflegal-rules-yes', function () {
1030 $('#wpflegal_rules').prop('checked', true);
1031 $('#wpflegal-rules-not').removeClass('wpflb-active-not');
1032 $(this).addClass('wpflb-active-yes');
1033 setTimeout(function () { $('.wpforo-legal-rules').slideToggle('slow'); }, 500);
1034 });
1035 wpforo_wrap.on('click', '#wpflegal-rules-not', function () {
1036 $('#wpflegal_rules').prop('checked', false);
1037 $('#wpflegal-rules-yes').removeClass('wpflb-active-yes');
1038 $(this).addClass('wpflb-active-not');
1039 });
1040
1041 //Forum Privacy Buttons
1042 wpforo_wrap.on('click', '#wpf-open-privacy', function () {
1043 $('.wpforo-legal-privacy').toggle();
1044 return false;
1045 });
1046 wpforo_wrap.on('click', '#wpflegal-privacy-yes', function () {
1047 $('#wpflegal_privacy').prop('checked', true);
1048 $('#wpflegal-privacy-not').removeClass('wpflb-active-not');
1049 $(this).addClass('wpflb-active-yes');
1050 setTimeout(function () { $('.wpforo-legal-privacy').slideToggle('slow'); }, 500);
1051 });
1052 wpforo_wrap.on('click', '#wpflegal-privacy-not', function () {
1053 $('#wpflegal_privacy').prop('checked', false);
1054 $('#wpflegal-privacy-yes').removeClass('wpflb-active-yes');
1055 $(this).addClass('wpflb-active-not');
1056 });
1057
1058 //Facebook Login Button
1059 wpforo_wrap.on('click', '#wpflegal_fblogin', function () {
1060 if ($(this).is(':checked')) {
1061 $('.wpforo_fb-button').attr('style', 'pointer-events:auto; opacity:1;');
1062 } else {
1063 $('.wpforo_fb-button').attr('style', 'pointer-events: none; opacity:0.6;');
1064 }
1065 });
1066
1067 wpforo_wrap.on('click', '.wpf-load-threads .wpf-forums', function () {
1068 $('.wpf-cat-forums', $(this).parents('div.wpfl-4')).slideToggle('slow');
1069 $('i', $(this)).toggleClass('fa-chevron-down fa-chevron-up');
1070 });
1071
1072 wpforo_wrap.on('click', '[data-copy-wpf-furl], [data-copy-wpf-shurl]', function () {
1073 var urls = [];
1074 var full_url = $(this).data('copy-wpf-furl');
1075 if (full_url) urls.push(decodeURIComponent(full_url));
1076 var short_url = $(this).data('copy-wpf-shurl');
1077 if (short_url) urls.push(decodeURIComponent(short_url));
1078 if (urls.length) {
1079 var label = '';
1080 var html = '';
1081 urls.forEach(function (url, i) {
1082 label = (urls.length === 2 && i === 1) ? wpforo_phrase('Short') : wpforo_phrase('Full');
1083 html += '<div class="wpforo-copy-url-wrap">' +
1084 '<div class="wpforo-copy-input">' +
1085 '<div class="wpforo-copy-input-header">' +
1086 '<label class="wpforo-copy-url-label">' +
1087 '<i class="fas fa-link wpfsx"></i>' +
1088 '<span class="wpforo-copy-url-label-txt">' + label + '</span>' +
1089 '</label>' +
1090 '</div>' +
1091 '<div class="wpforo-copy-input-body">' +
1092 '<input dir="ltr" readonly class="wpforo-copy-url" type="text" value="' + url + '">' +
1093 '</div>' +
1094 '</div>' +
1095 '<div class="wpforo-copied-txt"><span>' + wpforo_phrase('Copied') + '</span></div>' +
1096 '</div>';
1097 });
1098 var title = wpforo_phrase('Share Urls');
1099 wpforo_dialog_show(title, html, '40%', '260px');
1100 }
1101 });
1102
1103 // Topic ID copy to clipboard
1104 wpforo_wrap.on('click', '.wpf-topic-id[data-topicid]', function () {
1105 var $el = $(this);
1106 var topicid = $el.data('topicid');
1107 if (topicid) {
1108 var originalTooltip = $el.attr('wpf-tooltip');
1109 navigator.clipboard.writeText(topicid.toString()).then(function () {
1110 $el.attr('wpf-tooltip', wpforo_phrase('Copied!'));
1111 setTimeout(function () {
1112 $el.attr('wpf-tooltip', originalTooltip);
1113 }, 1500);
1114 }).catch(function () {
1115 // Fallback for older browsers
1116 var temp = $('<input>');
1117 $('body').append(temp);
1118 temp.val(topicid).select();
1119 document.execCommand('copy');
1120 temp.remove();
1121 $el.attr('wpf-tooltip', wpforo_phrase('Copied!'));
1122 setTimeout(function () {
1123 $el.attr('wpf-tooltip', originalTooltip);
1124 }, 1500);
1125 });
1126 }
1127 });
1128
1129 $(document).on('click', '.wpforo-copy-url-wrap', function () {
1130 var wrap = $(this);
1131 var input = $('input.wpforo-copy-url', wrap);
1132 if (input.length) {
1133 input[0].select();
1134 if (document.execCommand('copy')) {
1135 wrap.addClass('wpforo-copy-animate');
1136 setTimeout(function () {
1137 wrap.removeClass('wpforo-copy-animate');
1138 }, 1000);
1139 }
1140 }
1141 });
1142
1143 wpforo_wrap.on('click', '.wpf-toggle .wpf-toggle-advanced', function () {
1144 var wrap = $(this).closest('.wpf-toggle-wrap');
1145 $('.wpf-ico', $(this)).toggleClass('fa-chevron-down fa-chevron-up');
1146 $('.wpf-search-advanced-fields', wrap).slideToggle(350);
1147 });
1148
1149 wpforo_wrap.on('click', '.wpf-toggle .wpf-toggle-custom', function () {
1150 var wrap = $(this).closest('.wpf-toggle-wrap');
1151 $('.wpf-ico', $(this)).toggleClass('fa-chevron-down fa-chevron-up');
1152 $('.wpf-search-custom-fields', wrap).slideToggle(350);
1153 });
1154
1155 wpforo_wrap.on('click', 'form[data-textareaid] .wpforo-delete-custom-file', function () {
1156 if (confirm(wpforo_phrase('Are you sure you want to delete this file?'))) {
1157 var wrap = $(this).closest('.wpf-field-file-wrap');
1158 var fieldKey = $(this).data('fieldkey');
1159 if (fieldKey) wrap.html('<input type="hidden" name="wpftcf_delete[]" value="' + fieldKey + '">');
1160 }
1161 });
1162
1163 wpforo_wrap.on('change', '#wpf-profile-action', function () {
1164 var val = $(this).val();
1165 var exreg = new RegExp('^https?://', 'i');
1166 if (val.match(exreg)) location.href = val;
1167 });
1168 });
1169
1170 /**
1171 *
1172 * @param { jQuery|Element|Document } element
1173 * @param { string } name
1174 * @param { string|number|integer } value
1175 */
1176 function wpforo_setAttr (element, name, value) {
1177 if (element instanceof $wpf || element instanceof Element) {
1178 element = $wpf(element);
1179 element.prop(name, value);
1180 element.attr(name, value);
1181
1182 var match = name.match(new RegExp('^data-(.+)', 'i'));
1183 if (match) element.data(match[1], value);
1184 }
1185 }
1186
1187 function wpforo_confirm (msg, e) {
1188 if (!confirm(msg)) {
1189 e = e || window.event;
1190 e.stopPropagation();
1191 e.preventDefault();
1192 return false;
1193 }
1194
1195 return true;
1196 }
1197
1198 class wpfMultiInput extends HTMLElement {
1199 constructor () {
1200 super();
1201 this.innerHTML += `<style>
1202 wpf-multi-input input::-webkit-calendar-picker-indicator,
1203 wpf-multi-input datalist{
1204 display: none !important;
1205 }
1206 #wpforo #wpforo-wrap wpf-multi-input .wpf-invalid-msg{
1207 display: none;
1208 color: red;
1209 font-weight: bold;
1210 }
1211 #wpforo #wpforo-wrap .wpf-multi-item > .wpf-multi-item-action{
1212 margin: 0 3px;
1213 cursor: pointer;
1214 }
1215 #wpforo #wpforo-wrap .wpf-multi-item > .wpf-multi-item-action:hover > i{
1216 color: black;
1217 transform: scale(1.2);
1218 }
1219 #wpforo #wpforo-wrap .wpf-multi-item.wpf-multi-item-known-1 > .wpf-save-variant{
1220 display: none !important;
1221 }
1222 </style>`;
1223 this._shadowRoot = this.attachShadow({ mode: 'open' });
1224 this._shadowRoot.innerHTML = `<style>
1225 /* NB use of pointer-events to only allow events from the × icon */
1226 ::slotted(div.wpf-multi-item) {
1227 background-color: var(--wpf-multi-input-item-bg-color, #dedede) !important;
1228 border: var(--wpf-multi-input-item-border, 1px solid #ccc) !important;
1229 border-radius: 2px !important;
1230 color: #222 !important;
1231 display: inline-block !important;
1232 font-size: var(--wpf-multi-input-item-font-size, 14px) !important;
1233 margin: 5px !important;
1234 padding: 2px 5px 2px 5px !important;
1235 position: relative !important;
1236 top: -1px !important;
1237 }
1238 ::slotted(div.wpf-multi-item:hover) {
1239 background-color: #eee !important;
1240 color: black !important;
1241 }
1242 ::slotted(div.wpf-multi-item > .wpf-multi-item-action){
1243 margin: 0 3px;
1244 cursor: pointer;
1245 }
1246 ::slotted(.wpf-multi-item.wpf-multi-item-known-1 > .wpf-save-variant){
1247 display: none !important;
1248 }
1249 ::slotted(div.wpf-multi-item > .wpf-multi-item-action:hover > i){
1250 color: black;
1251 transform: scale(1.2);
1252 }
1253 ::slotted(input){
1254 border: 2px solid transparent !important;
1255 }
1256 ::slotted(input.wpf-invalid){
1257 border-color: red !important;
1258 }
1259 </style><slot></slot>`;
1260
1261 this._datalist = this.querySelector('datalist');
1262 this._dbVariants = [];
1263 const dbvariants = this.dataset['dbvariants'];
1264 if (dbvariants) this._dbVariants = JSON.parse(dbvariants);
1265
1266 this._input = this.querySelector('input');
1267 this._input.onblur = this._handleBlur.bind(this);
1268 this._input.oninput = this._handleInput.bind(this);
1269 this._input.onkeyup = (event) => {
1270 this._handleKeyup(event);
1271 };
1272 this._input.form.onsubmit = (event) => {
1273 this._handleSubmit(event);
1274 };
1275 this._items = [...this.querySelectorAll('.wpf-multi-item')];
1276 this._items.forEach((item) => {
1277 item.querySelector('.wpf-del').onclick = () => {
1278 this._deleteItem(item);
1279 };
1280 const save_button = item.querySelector('.wpf-save-variant');
1281 if (save_button) {
1282 save_button.onclick = () => {
1283 this._saveItem(item);
1284 };
1285 }
1286 });
1287
1288 this._allowDuplicates = this.hasAttribute('allow-duplicates') || this._input.hasAttribute('allow-duplicates');
1289 this._allowCustomValues = this.hasAttribute('allow-custom-values') || this._input.hasAttribute('allow-custom-values');
1290 this._isRequired = this.hasAttribute('required') || this._input.hasAttribute('required');
1291 this._input.removeAttribute('required');
1292
1293 this._invalidMsg = this.querySelector('.wpf-invalid-msg');
1294 }
1295
1296 // Called by _handleKeydown() when the value of the input is an allowed value.
1297 _addItem (value) {
1298 if (!value.trim()) return;
1299 if (!this._allowCustomValues && !this._dbVariants.includes(value)) return;
1300 if (!this._allowDuplicates && this.getValues().includes(value)) return;
1301 this._input.value = '';
1302 const item = document.querySelector('template#wpf-multi-item-template').cloneNode(true).content.firstChild;
1303 item.classList.remove('wpf-multi-item-known-0', 'wpf-multi-item-known-1');
1304 item.classList.add((this._dbVariants.includes(value) ? 'wpf-multi-item-known-1' : 'wpf-multi-item-known-0'));
1305 item.querySelector('.wpf-multi-item-value').textContent = value;
1306 item.querySelector('.wpf-del').onclick = () => {
1307 this._deleteItem(item);
1308 };
1309 const save_button = item.querySelector('.wpf-save-variant');
1310 if (save_button) {
1311 save_button.onclick = () => {
1312 this._saveItem(item);
1313 };
1314 }
1315 this.insertBefore(item, this._input);
1316
1317 // Remove value from datalist options and from _allowedValues array.
1318 // Value is added back if an item is deleted (see _deleteItem()).
1319 if (!this._allowDuplicates && this._dbVariants.includes(value)) {
1320 for (const option of this._datalist.options) {
1321 if (option.value === value) {
1322 option.remove();
1323 }
1324 }
1325 }
1326 }
1327
1328 // Called when the × icon is tapped/clicked or
1329 // by _handleKeydown() when Backspace is entered.
1330 _deleteItem (item) {
1331 if (!item.classList.contains('wpf-multi-item')) return;
1332 const value = item.querySelector('.wpf-multi-item-value').textContent;
1333 item.remove();
1334 // If duplicates aren't allowed, value is removed (in _addItem())
1335 // as a datalist option and from the _allowedValues array.
1336 // So — need to add it back here.
1337 if (!this._allowDuplicates && this._dbVariants.includes(value)) {
1338 const option = document.createElement('option');
1339 option.value = value;
1340 // Insert as first option seems reasonable...
1341 this._datalist.insertBefore(option, this._datalist.firstChild);
1342 }
1343 }
1344
1345 _saveItem (item) {
1346 if (!item.classList.contains('wpf-multi-item')) return;
1347 const value = item.querySelector('.wpf-multi-item-value').textContent;
1348
1349 if (typeof value === 'string') {
1350 if (item.parentNode instanceof Node && item.parentNode.dataset && typeof item.parentNode.dataset['fieldkey'] === 'string') {
1351 this._ajaxSaveItem(+item.parentNode.dataset['formid'], item.parentNode.dataset['fieldkey'].trim(), value, () => {
1352 item.classList.remove('wpf-multi-item-known-0');
1353 item.classList.add('wpf-multi-item-known-1');
1354 });
1355 }
1356 }
1357 }
1358
1359 _ajaxSaveItem (formid, fieldKey, value, resolve, reject) {
1360 if (!value.trim()) return;
1361 wpforo_load_show('Saving...');
1362
1363 $wpf.ajax({
1364 type: 'POST',
1365 data: {
1366 formid,
1367 fieldKey,
1368 value,
1369 action: 'wpforotcf_append_field_values',
1370 _wpfnonce: wpforo['nonces']['wpforotcf_append_field_values'],
1371 },
1372 }).done(function (r) {
1373 if (r.success) {
1374 if (resolve) resolve();
1375 } else {
1376 if (reject) reject();
1377 }
1378 }).always(function () {
1379 wpforo_load_hide();
1380 });
1381 }
1382
1383 // Avoid stray text remaining in the input element that's not in a div.item.
1384 _handleBlur () {
1385 this._input.value = '';
1386 }
1387
1388 // Called when input text changes,
1389 // either by entering text or selecting a datalist option.
1390 _handleInput () {
1391 // Add a div.item, but only if the current value
1392 // of the input is an allowed value
1393 const match = this._dbVariants.find(v => v.toLowerCase() === this._input.value.toLowerCase());
1394 if (match !== undefined) this._addItem(match);
1395 }
1396
1397 // Called when text is entered or keys pressed in the input element.
1398 _handleKeyup (event) {
1399 const itemToDelete = event.target.previousElementSibling;
1400 const value = this._input.value;
1401
1402 // On Backspace, delete the div.item to the left of the input
1403 if (value === '' && event.key === 'Backspace' && itemToDelete) {
1404 this._deleteItem(itemToDelete);
1405 // Add a div.item, but only if the current value
1406 // of the input is an allowed value
1407 } else if (event.key === 'Enter' && value.trim()) {
1408 if (this._allowCustomValues) {
1409 event.preventDefault();
1410 this._addItem(value);
1411 } else if (this._dbVariants.includes(value) && !this.getValues().includes(value)) {
1412 event.preventDefault();
1413 this._addItem(value);
1414 }
1415 }
1416 }
1417
1418 _handleSubmit (event) {
1419 if (this._input.value) {
1420 event.preventDefault();
1421 setTimeout(wpforo_load_hide, 100);
1422 if (this._allowCustomValues) this._addItem(this._input.value);
1423 this._input.value = '';
1424 return;
1425 }
1426
1427 const values = this.getValues();
1428 if (this._isRequired && !values.length) {
1429 event.preventDefault();
1430 this._input.classList.add('wpf-invalid');
1431 this._invalidMsg.style = 'display: inline-block';
1432 let i = 0;
1433 const intervalHendler = setInterval(() => {
1434 this._input.classList.toggle('wpf-invalid');
1435 if (i++ >= 4) {
1436 this._input.classList.add('wpf-invalid');
1437 wpforo_load_hide();
1438 clearInterval(intervalHendler);
1439 setTimeout(() => {
1440 this._input.classList.remove('wpf-invalid');
1441 this._invalidMsg.style = 'display: none;';
1442 }, 3000);
1443 }
1444 }, 50);
1445 } else if (values.length) {
1446 const name = this._input.name;
1447 this._input.removeAttribute('name');
1448 values.forEach((val) => {
1449 const hidden = document.createElement('input');
1450 hidden.type = 'hidden';
1451 hidden.name = name;
1452 hidden.value = val;
1453 this._input.form.append(hidden);
1454 });
1455 }
1456 }
1457
1458 // Public method for getting item values as an array.
1459 getValues () {
1460 const values = [];
1461 const items = this.querySelectorAll('.wpf-multi-item');
1462 for (const item of items) {
1463 values.push(item.querySelector('.wpf-multi-item-value').textContent);
1464 }
1465 return values;
1466 }
1467 }
1468
1469 window.customElements.define('wpf-multi-input', wpfMultiInput);
1470
1471 class wpfAutocompleteInput extends HTMLElement {
1472 constructor () {
1473 super();
1474 this.innerHTML += `<style>
1475 wpf-autocomplete-input input::-webkit-calendar-picker-indicator,
1476 wpf-autocomplete-input datalist{
1477 display: none !important;
1478 }
1479 #wpforo #wpforo-wrap wpf-autocomplete-input .wpf-invalid-msg{
1480 display: none;
1481 color: red;
1482 font-weight: bold;
1483 }
1484 </style>`;
1485 this._shadowRoot = this.attachShadow({ mode: 'open' });
1486 this._shadowRoot.innerHTML = `<style>
1487 ::slotted(input){
1488 border: 2px solid transparent !important;
1489 }
1490 ::slotted(input.wpf-invalid){
1491 border-color: red !important;
1492 }
1493 </style><slot></slot>`;
1494 this._datalist = this.querySelector('datalist');
1495 this._dbVariants = [];
1496 const dbvariants = this.dataset['dbvariants'];
1497 if (dbvariants) this._dbVariants = JSON.parse(dbvariants);
1498
1499 this._input = this.querySelector('input');
1500 this._input.form.onsubmit = (event) => {
1501 this._handleSubmit(event);
1502 };
1503
1504 this._allowCustomValues = this.hasAttribute('allow-custom-values') || this._input.hasAttribute('allow-custom-values');
1505 this._isRequired = this.hasAttribute('required') || this._input.hasAttribute('required');
1506 this._invalidMsgRequired = this.querySelector('.wpf-invalid-msg.wpf-required');
1507 this._invalidMsgNotAllowedValue = this.querySelector('.wpf-invalid-msg.wpf-not-allowed-value');
1508 }
1509
1510 _handleSubmit (event) {
1511 const value = this._input.value;
1512 if (!this._isRequired && !value) return;
1513 let prevent = false;
1514 if (this._isRequired && !value) {
1515 this._invalidMsg = this._invalidMsgRequired;
1516 prevent = true;
1517 } else if (!this._allowCustomValues && !this._dbVariants.includes(value)) {
1518 this._invalidMsg = this._invalidMsgNotAllowedValue;
1519 prevent = true;
1520 }
1521 if (prevent) {
1522 event.preventDefault();
1523 wpforo_load_hide();
1524 this._input.classList.add('wpf-invalid');
1525 this._invalidMsg.style = 'display: inline-block';
1526 let i = 0;
1527 const intervalHendler = setInterval(() => {
1528 this._input.classList.toggle('wpf-invalid');
1529 if (i++ >= 4) {
1530 this._input.classList.add('wpf-invalid');
1531 wpforo_load_hide();
1532 clearInterval(intervalHendler);
1533 setTimeout(() => {
1534 this._input.classList.remove('wpf-invalid');
1535 this._invalidMsg.style = 'display: none;';
1536 }, 3000);
1537 }
1538 }, 50);
1539 }
1540 }
1541 }
1542
1543 window.customElements.define('wpf-autocomplete-input', wpfAutocompleteInput);
1544
1545
1546