(function ($) { 'use strict'; /* ── Utilities ──────────────────────────────────────────────── */ function wbfPost(action, data, cb, errCb) { data.action = action; data.nonce = WBF.nonce; $.post(WBF.ajax_url, data, function (res) { if (res.success) cb(res.data); else if (errCb) errCb(res.data); }); } function showMsg($el, msg, ok) { $el.text(msg).css('color', ok ? '#56cf7e' : '#f05252').show(); setTimeout(function () { $el.fadeOut(); }, 4000); } /* ── Auth Tabs ──────────────────────────────────────────────── */ $(document).on('click', '.wbf-auth-tab', function () { var tab = $(this).data('tab'); $('.wbf-auth-tab').removeClass('active'); $(this).addClass('active'); $('.wbf-auth-panel').removeClass('active'); $('[data-panel="' + tab + '"]').addClass('active'); }); /* ── Auth Modal öffnen ──────────────────────────────────────── */ $(document).on('click', '#wbfOpenLogin, .wbf-login-link', function (e) { e.preventDefault(); $('[data-tab="login"]').trigger('click'); $('#wbfAuthModal').addClass('active'); }); $(document).on('click', '#wbfOpenRegister, .wbf-register-link', function (e) { e.preventDefault(); $('[data-tab="register"]').trigger('click'); $('#wbfAuthModal').addClass('active'); }); /* ── Modal schließen bei Klick außerhalb ────────────────────── */ $(document).on('click', '.wbf-modal', function (e) { if ($(e.target).hasClass('wbf-modal')) $(this).removeClass('active'); }); /* ── Login ──────────────────────────────────────────────────── */ $(document).on('keydown', '.wbf-field-password', function (e) { if (e.key === 'Enter') $(this).closest('.wbf-auth-box').find('.wbf-login-submit-btn').trigger('click'); }); /* ── Registrieren ───────────────────────────────────────────── */ $(document).on('click', '.wbf-reg-submit-btn', function () { var $btn = $(this).prop('disabled', true).html(''); wbfPost('wbf_register', { username: $(this).closest('.wbf-auth-box').find('.wbf-field-reg-user').val(), display_name: $(this).closest('.wbf-auth-box').find('.wbf-field-reg-name').val(), email: $(this).closest('.wbf-auth-box').find('.wbf-field-reg-email').val(), password: $(this).closest('.wbf-auth-box').find('.wbf-field-reg-pass').val() }, function () { location.reload(); }, function (d) { showMsg($btn.closest('.wbf-auth-box').find('.wbf-reg-msg'), d.message || 'Fehler', false); $btn.prop('disabled', false).html(' Konto erstellen'); }); }); /* ── Logout — direkt via Link (?wbf_do_logout=1) ───────────── */ // Kein JS nötig — Logout-Button ist jetzt ein Link /* ── Neuer Thread Modal ─────────────────────────────────────── */ window.wbfShowNewThread = function (catId) { if (WBF.logged_in !== 'yes') { $('#wbfAuthModal').addClass('active'); return; } if (catId) $('#wbfThreadCat').val(catId); $('#wbfNewThreadModal').addClass('active'); }; $(document).on('click', '#wbfSubmitThread', function () { var $btn = $(this).prop('disabled', true).html(''); wbfPost('wbf_new_thread', { category_id: $('#wbfThreadCat').val(), title: $('#wbfThreadTitle').val(), content: $('#wbfThreadContent').val(), tags: $('#wbfThreadTags').val() }, function (d) { var base = WBF.forum_url || window.location.href.split('?')[0]; var sep = base.indexOf('?') !== -1 ? '&' : '?'; window.location.href = base + sep + 'forum_thread=' + d.thread_id; }, function (d) { showMsg($('#wbfThreadMsg'), d.message || 'Fehler', false); $btn.prop('disabled', false).html(' Thread erstellen'); }); }); /* ══════════════════════════════════════════════════════════ FEATURE: Tag-Input Widget ══════════════════════════════════════════════════════════ */ var wbfTagList = []; // aktuell ausgewählte Tags var wbfTagTimer = null; function wbfUpdateTagHidden() { $('#wbfThreadTags').val(wbfTagList.join(', ')); } function wbfAddTag(name) { name = name.replace(/^#+/, '').trim().toLowerCase(); if (!name || name.length < 2 || name.length > 30) return; if (wbfTagList.length >= 10) { return; } if (wbfTagList.indexOf(name) !== -1) return; wbfTagList.push(name); wbfUpdateTagHidden(); wbfRenderTagPills(); $('#wbfTagInput').val(''); $('#wbfTagSuggest').hide().empty(); } function wbfRemoveTag(name) { wbfTagList = wbfTagList.filter(function(t){ return t !== name; }); wbfUpdateTagHidden(); wbfRenderTagPills(); } function wbfRenderTagPills() { var $pills = $('#wbfTagPills'); $pills.empty(); wbfTagList.forEach(function(tag) { $pills.append( $('') .text('#' + tag) .append($('').on('click', function(){ wbfRemoveTag(tag); })) ); }); // Show/hide count hint var remaining = 10 - wbfTagList.length; if (remaining <= 3 && remaining > 0) { $pills.append('' + remaining + ' übrig'); } } // Keydown on tag input $(document).on('keydown', '#wbfTagInput', function(e) { var val = $(this).val().trim(); if (e.key === 'Enter' || e.key === ',' || e.key === ' ') { e.preventDefault(); if (val) wbfAddTag(val); } else if (e.key === 'Backspace' && !val && wbfTagList.length) { wbfRemoveTag(wbfTagList[wbfTagList.length - 1]); } }); // Autocomplete on input $(document).on('input', '#wbfTagInput', function() { var q = $(this).val().replace(/^#+/, '').trim(); clearTimeout(wbfTagTimer); if (q.length < 1) { $('#wbfTagSuggest').hide().empty(); return; } wbfTagTimer = setTimeout(function() { wbfPost('wbf_tag_suggest', { q: q }, function(d) { var $s = $('#wbfTagSuggest'); if (!d.tags || !d.tags.length) { $s.hide().empty(); return; } $s.empty(); d.tags.forEach(function(tag) { if (wbfTagList.indexOf(tag.slug) !== -1) return; $s.append( $('
') .html('' + $('').text(tag.name).html() + '' + tag.use_count + '') .on('click', function(){ wbfAddTag(tag.name); }) ); }); $s.show(); }); }, 200); }); // Click on tag input wrap focuses input $(document).on('click', '#wbfTagInputWrap', function(e) { if (!$(e.target).is('button')) $('#wbfTagInput').focus(); }); // Reset tags when modal closes $(document).on('click', '#wbfNewThreadModal .wbf-modal__close, #wbfNewThreadModal', function(e) { if ($(e.target).hasClass('wbf-modal') || $(e.target).hasClass('wbf-modal__close')) { wbfTagList = []; wbfRenderTagPills(); $('#wbfTagInput').val(''); $('#wbfTagSuggest').hide(); } }); // Hide suggest on outside click $(document).on('click', function(e) { if (!$(e.target).closest('#wbfTagInputWrap').length) { $('#wbfTagSuggest').hide(); } }); /* ── Antwort senden ─────────────────────────────────────────── */ $(document).on('input', '#wbfReplyContent', function () { $('#wbfReplyCounter').text($(this).val().length + ' Zeichen'); }); $(document).on('click', '#wbfSubmitReply', function () { var $btn = $(this).prop('disabled', true).html(''); var threadId = $(this).data('thread'); wbfPost('wbf_new_post', { thread_id: threadId, content: $('#wbfReplyContent').val() }, function (d) { $('#wbfPosts').append(d.html); $('#wbfReplyContent').val(''); $('#wbfReplyCounter').text('0 Zeichen'); $btn.prop('disabled', false).html(' Antwort senden'); $('html, body').animate({ scrollTop: $('#post-' + d.post_id).offset().top - 80 }, 400); $(document).trigger('wbf:post_added', [d.post_id]); }, function (d) { alert(d.message || 'Fehler beim Senden.'); $btn.prop('disabled', false).html(' Antwort senden'); }); }); /* ── Like ───────────────────────────────────────────────────── */ $(document).on('click', '.wbf-like-btn', function () { if (WBF.logged_in !== 'yes') { $('#wbfAuthModal').addClass('active'); return; } var $btn = $(this); wbfPost('wbf_toggle_like', { object_id: $btn.data('id'), object_type: $btn.data('type') }, function (d) { $btn.find('.wbf-like-count').text(d.count); $btn.toggleClass('wbf-liked', d.action === 'liked'); }); }); /* ── Mod-Aktionen ───────────────────────────────────────────── */ $(document).on('click', '.wbf-mod-btn', function () { var action = $(this).data('action'); var id = $(this).data('id'); var $btn = $(this); // Move modal — open inline, no AJAX yet if (action === 'open_move') { $('#wbfMoveThreadId').val(id); $('#wbfMoveMsg').hide(); $('#wbfMoveModal').addClass('active'); return; } var confirmMsgs = { 'delete_thread': 'Thread wirklich löschen? Alle Antworten werden entfernt.', 'delete_post': 'Post wirklich löschen?', 'archive_thread': 'Thread archivieren? Er wird aus der Kategorie ausgeblendet.' }; if (confirmMsgs[action] && !confirm(confirmMsgs[action])) return; $btn.prop('disabled', true).css('opacity', '.5'); wbfPost('wbf_mod_action', { mod_action: action, object_id: id }, function (d) { if (d.action === 'deleted') { window.location.href = window.location.pathname; } else if (d.action === 'archived') { // Redirect back — page.reload keeps the archived thread visible until refresh history.back(); } else if (d.action === 'post_deleted') { $('#post-' + id).fadeOut(300, function () { $(this).remove(); }); } else { location.reload(); } }, function (d) { alert(d.message || 'Aktion fehlgeschlagen.'); $btn.prop('disabled', false).css('opacity', '1'); }); }); /* ── Thread verschieben ─────────────────────────────────────── */ $(document).on('click', '#wbfSubmitMove', function () { var $btn = $(this).prop('disabled', true).html(''); var threadId = $('#wbfMoveThreadId').val(); var catId = $('#wbfMoveCatSelect').val(); wbfPost('wbf_move_thread', { thread_id: threadId, category_id: catId }, function (d) { showMsg($('#wbfMoveMsg'), '✔ ' + (d.message || 'Verschoben!'), true); $btn.prop('disabled', false).html(' Verschieben'); setTimeout(function () { $('#wbfMoveModal').removeClass('active'); location.reload(); }, 1200); }, function (d) { showMsg($('#wbfMoveMsg'), d.message || 'Fehler.', false); $btn.prop('disabled', false).html(' Verschieben'); }); }); /* ── Profil speichern ───────────────────────────────────────── */ $(document).on('click', '#wbfSaveProfile', function () { var $btn = $(this).prop('disabled', true); wbfPost('wbf_update_profile', { display_name: $('#wbfEditName').val(), bio: $('#wbfEditBio').val(), signature: $('#wbfEditSignature').val(), new_password: $('#wbfNewPassword').val() }, function (d) { showMsg($('#wbfProfileMsg'), d.message, true); $btn.prop('disabled', false); }, function (d) { showMsg($('#wbfProfileMsg'), d.message || 'Fehler', false); $btn.prop('disabled', false); }); }); /* ── Signatur Zeichenzähler ─────────────────────────────────── */ $(document).on('input', '#wbfEditSignature', function () { $('#wbfSigCount').text($(this).val().length); }); /* ── Avatar Upload ──────────────────────────────────────────── */ $(document).on('change', '#wbfAvatarFile', function () { var file = this.files[0]; if (!file) return; var fd = new FormData(); fd.append('action', 'wbf_upload_avatar'); fd.append('nonce', WBF.nonce); fd.append('avatar', file); $.ajax({ url: WBF.ajax_url, type: 'POST', data: fd, processData: false, contentType: false, success: function (res) { if (res.success) { $('.wbf-profile-page__avatar').attr('src', res.data.avatar_url); } } }); }); /* ══════════════════════════════════════════════════════════ FEATURE: Ungelesene Beiträge ══════════════════════════════════════════════════════════ */ var WBF_STORAGE_KEY = 'wbf_last_seen'; function wbfGetLastSeen() { try { return JSON.parse(localStorage.getItem(WBF_STORAGE_KEY) || '{}'); } catch (e) { return {}; } } function wbfSetLastSeen(data) { try { localStorage.setItem(WBF_STORAGE_KEY, JSON.stringify(data)); } catch (e) {} } function wbfMarkNewThreads() { var lastSeen = wbfGetLastSeen(); $('.wbf-thread-row[data-thread-id]').each(function () { var $row = $(this); var threadId = $row.data('thread-id').toString(); var lastReply = $row.data('last-reply'); if (!lastReply) return; var seenAt = lastSeen[threadId]; var isNew = !seenAt || new Date(lastReply) > new Date(seenAt); if (isNew) { $row.addClass('wbf-thread-row--has-new'); $row.find('.wbf-new-badge').show(); } }); } function wbfMarkNewPosts() { var $container = $('[data-thread-view]'); if (!$container.length) return; var threadId = $container.data('thread-view').toString(); var lastSeen = wbfGetLastSeen(); var seenAt = lastSeen[threadId]; $('.wbf-post[data-created]').each(function () { var created = $(this).data('created'); if (!created) return; if (seenAt && new Date(created) > new Date(seenAt)) { $(this).addClass('wbf-post--new'); } }); lastSeen[threadId] = new Date().toISOString(); wbfSetLastSeen(lastSeen); } $(function () { wbfMarkNewThreads(); wbfMarkNewPosts(); }); $(document).on('wbf:post_added', function (e, postId) { $('#post-' + postId).addClass('wbf-post--new'); var $container = $('[data-thread-view]'); if (!$container.length) return; var threadId = $container.data('thread-view').toString(); var lastSeen = wbfGetLastSeen(); lastSeen[threadId] = new Date().toISOString(); wbfSetLastSeen(lastSeen); }); /* ══════════════════════════════════════════════════════════ FEATURE: Editor-Toolbar — Bold, Italic, Bild, Smilies ══════════════════════════════════════════════════════════ */ function wbfInsertAtCursor($ta, text) { var el = $ta[0]; var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + text + val.slice(end); el.selectionStart = el.selectionEnd = start + text.length; $ta.trigger('input'); el.focus(); } function wbfWrapSelection($ta, before, after) { var el = $ta[0]; var sel = el.value.slice(el.selectionStart, el.selectionEnd) || 'Text'; wbfInsertAtCursor($ta, before + sel + after); } function wbfGetTargetTextarea($toolbar) { return $('#' + $toolbar.data('target')); } // ── BBCode-Wrap-Helfer ──────────────────────────────────────── function wbfBBWrap($ta, tag) { var el = $ta[0]; var sel = el.value.slice(el.selectionStart, el.selectionEnd) || 'Text'; wbfInsertAtCursor($ta, '[' + tag + ']' + sel + '[/' + tag + ']'); } $(document).on('click', '.wbf-tb-btn', function (e) { e.preventDefault(); e.stopPropagation(); var $btn = $(this); var action = $btn.data('action'); var $toolbar = $btn.closest('.wbf-editor-toolbar'); var $ta = wbfGetTargetTextarea($toolbar); // ── Standard BBCode wrap [tag]sel[/tag] ─────────────────── if (action === 'bb') { var bb = $btn.data('bb'); if (bb === 'hr') { wbfInsertAtCursor($ta, '\n[hr]\n'); } else { wbfBBWrap($ta, bb); } // ── Dropdown-Toggle ─────────────────────────────────────── } else if (action === 'dropdown') { var panelId = 'wbf-' + $btn.data('target') + '-panel-' + $toolbar.data('target'); var $panel = $('#' + panelId); var wasOpen = $panel.is(':visible'); $('.wbf-tb-dropdown__panel').hide(); if (!wasOpen) $panel.show(); // ── Farbe ───────────────────────────────────────────────── } else if (action === 'bb-color') { var color = $btn.data('color'); var el = $ta[0]; var sel = el.value.slice(el.selectionStart, el.selectionEnd) || 'Text'; wbfInsertAtCursor($ta, '[color=' + color + ']' + sel + '[/color]'); $('.wbf-tb-dropdown__panel').hide(); // ── Größe ───────────────────────────────────────────────── } else if (action === 'bb-size') { var size = $btn.data('size'); var el2 = $ta[0]; var sel2 = el2.value.slice(el2.selectionStart, el2.selectionEnd) || 'Text'; wbfInsertAtCursor($ta, '[size=' + size + ']' + sel2 + '[/size]'); $('.wbf-tb-dropdown__panel').hide(); // ── Liste ───────────────────────────────────────────────── } else if (action === 'bb-list') { var ordered = $btn.data('ordered') ? '=1' : ''; wbfInsertAtCursor($ta, '[list' + ordered + ']\n[*] Punkt 1\n[*] Punkt 2\n[/list]'); // ── Spoiler ─────────────────────────────────────────────── } else if (action === 'bb-spoiler') { var title = prompt('Spoiler-Titel (optional):', '') || ''; var el3 = $ta[0]; var sel3 = el3.value.slice(el3.selectionStart, el3.selectionEnd) || 'Inhalt hier'; var tag3 = title ? '[spoiler=' + title + ']' : '[spoiler]'; wbfInsertAtCursor($ta, tag3 + sel3 + '[/spoiler]'); // ── Link ────────────────────────────────────────────────── } else if (action === 'bb-url') { var href = prompt('URL eingeben:', 'https://'); if (href && href.length > 7) { var el4 = $ta[0]; var sel4 = el4.value.slice(el4.selectionStart, el4.selectionEnd) || href; wbfInsertAtCursor($ta, '[url=' + href + ']' + sel4 + '[/url]'); } // ── Bild-URL ────────────────────────────────────────────── } else if (action === 'bb-img') { var imgUrl = prompt('Bild-URL eingeben:', 'https://'); if (imgUrl && imgUrl.length > 8) { wbfInsertAtCursor($ta, '[img]' + imgUrl + '[/img]'); } // ── Bild hochladen ──────────────────────────────────────── } else if (action === 'img-upload') { $btn.find('.wbf-img-file-input').trigger('click'); // ── Emoji-Picker ────────────────────────────────────────── } else if (action === 'emoji') { var $picker = $toolbar.find('.wbf-emoji-picker'); var wasOpen2 = $picker.is(':visible'); $('.wbf-emoji-picker, .wbf-tb-dropdown__panel').hide(); if (!wasOpen2) $picker.show(); } }); // Dropdown-Panel schließen bei Klick außerhalb $(document).on('click', function (e) { if (!$(e.target).closest('.wbf-tb-dropdown, .wbf-tb-dropdown__panel').length) { $('.wbf-tb-dropdown__panel').hide(); } }); /* ── Bild hochladen ─────────────────────────────────────────── */ $(document).on('change', '.wbf-img-file-input', function () { var file = this.files[0]; if (!file) return; var $input = $(this); var $btn = $input.closest('.wbf-tb-btn'); var $toolbar = $input.closest('.wbf-editor-toolbar'); var $ta = wbfGetTargetTextarea($toolbar); $btn.addClass('wbf-tb-btn--loading'); var $prog = $toolbar.find('.wbf-tb-upload-progress'); if (!$prog.length) { $prog = $(' Wird hochgeladen…'); $toolbar.append($prog); } $prog.addClass('active'); var fd = new FormData(); fd.append('action', 'wbf_upload_post_image'); fd.append('nonce', WBF.nonce); fd.append('image', file); $.ajax({ url: WBF.ajax_url, type: 'POST', data: fd, processData: false, contentType: false, success: function (res) { if (res.success) { wbfInsertAtCursor($ta, '[img]' + res.data.url + '[/img]'); } else { alert(res.data.message || 'Fehler beim Hochladen.'); } }, error: function () { alert('Verbindungsfehler beim Hochladen.'); }, complete: function () { $btn.removeClass('wbf-tb-btn--loading'); $prog.removeClass('active'); $input.val(''); } }); }); /* ── Emoji einfügen ─────────────────────────────────────────── */ $(document).on('click', '.wbf-emoji-item', function (e) { e.stopPropagation(); var $toolbar = $(this).closest('.wbf-editor-toolbar'); wbfInsertAtCursor(wbfGetTargetTextarea($toolbar), $(this).data('emoji')); $toolbar.find('.wbf-emoji-picker').hide(); }); $(document).on('click', function (e) { if (!$(e.target).closest('.wbf-editor-toolbar').length) { $('.wbf-emoji-picker').hide(); } }); /* ══════════════════════════════════════════════════════════ FEATURE: Beitrag melden (auch eigene) ══════════════════════════════════════════════════════════ */ $(document).on('click', '.wbf-report-btn', function (e) { e.preventDefault(); if (WBF.logged_in !== 'yes') { $('#wbfAuthModal').addClass('active'); return; } $('#wbfReportId').val($(this).data('id')); $('#wbfReportType').val($(this).data('type') || 'post'); $('#wbfReportReason').val(''); $('#wbfReportNote').val(''); $('#wbfReportMsg').hide(); $('#wbfReportModal').addClass('active'); }); $(document).on('click', '#wbfSubmitReport', function () { var reason = $('#wbfReportReason').val(); if (!reason) { showMsg($('#wbfReportMsg'), 'Bitte einen Grund auswählen.', false); return; } var $btn = $(this).prop('disabled', true).html(''); wbfPost('wbf_report_post', { object_id: $('#wbfReportId').val(), object_type: $('#wbfReportType').val(), reason: reason, note: $('#wbfReportNote').val() }, function (d) { showMsg($('#wbfReportMsg'), d.message, true); var postId = $('#wbfReportId').val(); $('.wbf-report-btn[data-id="' + postId + '"]') .replaceWith(''); setTimeout(function () { $('#wbfReportModal').removeClass('active'); }, 1800); $btn.prop('disabled', false).html(' Melden'); }, function (d) { showMsg($('#wbfReportMsg'), d.message || 'Fehler beim Melden.', false); $btn.prop('disabled', false).html(' Melden'); }); }); /* ══════════════════════════════════════════════════════════ FEATURE: Beitrag inline bearbeiten ══════════════════════════════════════════════════════════ */ $(document).on('click', '.wbf-edit-post-btn', function (e) { e.preventDefault(); var postId = $(this).data('id'); $('#wbf-post-content-' + postId).hide(); $('#wbf-post-edit-' + postId).show().find('textarea').focus(); }); $(document).on('click', '.wbf-cancel-edit-btn', function () { var postId = $(this).data('id'); $('#wbf-post-content-' + postId).show(); $('#wbf-post-edit-' + postId).hide(); }); $(document).on('click', '.wbf-save-edit-btn', function () { var $btn = $(this).prop('disabled', true).html(''); var postId = $btn.data('id'); var $wrap = $('#wbf-post-edit-' + postId); var $msg = $wrap.find('.wbf-edit-msg'); wbfPost('wbf_edit_post', { post_id: postId, content: $wrap.find('textarea').val() }, function (d) { $('#wbf-post-content-' + postId).html(d.content).show(); $wrap.hide(); $btn.prop('disabled', false).html(' Speichern'); $msg.css('color', '#56cf7e').text(d.message || 'Gespeichert!').show(); setTimeout(function () { $msg.fadeOut(); }, 2500); }, function (d) { $msg.css('color', '#f05252').text(d.message || 'Fehler').show(); $btn.prop('disabled', false).html(' Speichern'); }); }); /* ══════════════════════════════════════════════════════════ FEATURE: Zitieren (BBCode) ══════════════════════════════════════════════════════════ */ $(document).on('click', '.wbf-quote-btn', function () { if (WBF.logged_in !== 'yes') { $('#wbfAuthModal').addClass('active'); return; } var sourceId = $(this).data('source'); var author = $(this).data('author'); var $content = $('#' + sourceId); if (!$content.length) return; // Strip HTML tags to get plain text, skip nested blockquotes var rawText = $content.clone().find('blockquote, .wbf-bb-quote').remove().end().text().trim(); if (rawText.length > 600) rawText = rawText.substring(0, 600) + '…'; var quote = '[quote=' + author + ']\n' + rawText + '\n[/quote]\n\n'; var $ta = $('#wbfReplyContent'); var $replyBox = $('#wbfReplyBox'); if (!$ta.length) return; var el = $ta[0]; var start = el.selectionStart; var end = el.selectionEnd; var val = el.value; el.value = val.slice(0, start) + quote + val.slice(end); el.selectionStart = el.selectionEnd = start + quote.length; $ta.trigger('input').focus(); $('html, body').animate({ scrollTop: $replyBox.offset().top - 80 }, 350); }); /* ══════════════════════════════════════════════════════════ FEATURE: Bild-Lightbox ══════════════════════════════════════════════════════════ */ $(document).on('click', '.wbf-post__content img', function () { var $lb = $('
' + '' + '' + ($(this).attr('alt') || '') + '' + '
'); $('body').append($lb).css('overflow', 'hidden'); }); $(document).on('click', '.wbf-lightbox', function (e) { if ($(e.target).hasClass('wbf-lightbox') || $(e.target).hasClass('wbf-lightbox__close')) { $(this).remove(); $('body').css('overflow', ''); } }); $(document).on('keydown', function (e) { if (e.key === 'Escape') { $('.wbf-lightbox').remove(); $('body').css('overflow', ''); $('.wbf-emoji-picker').hide(); $('.wbf-tb-dropdown__panel').hide(); } }); /* ══════════════════════════════════════════════════════════ FEATURE: Thread-Inhalt (OP) inline bearbeiten ══════════════════════════════════════════════════════════ */ $(document).on('click', '.wbf-edit-thread-btn', function (e) { e.preventDefault(); var threadId = $(this).data('id'); $('#wbf-thread-content-' + threadId).hide(); $('#wbf-thread-edit-' + threadId).show().find('textarea').focus(); }); $(document).on('click', '.wbf-cancel-thread-btn', function () { var threadId = $(this).data('id'); $('#wbf-thread-content-' + threadId).show(); $('#wbf-thread-edit-' + threadId).hide(); }); $(document).on('click', '.wbf-save-thread-btn', function () { var $btn = $(this).prop('disabled', true).html(''); var threadId = $btn.data('id'); var $wrap = $('#wbf-thread-edit-' + threadId); var $msg = $wrap.find('.wbf-edit-msg'); wbfPost('wbf_edit_thread', { thread_id: threadId, title: $wrap.find('.wbf-edit-title-input').val(), content: $wrap.find('textarea').val() }, function (d) { $('#wbf-thread-content-' + threadId).html(d.content).show(); // Titel im DOM aktualisieren if (d.title) { $('.wbf-thread-title').first().text(d.title); } $wrap.hide(); $btn.prop('disabled', false).html(' Speichern'); $msg.css('color', '#56cf7e').text(d.message || 'Gespeichert!').show(); setTimeout(function () { $msg.fadeOut(); }, 2500); }, function (d) { $msg.css('color', '#f05252').text(d.message || 'Fehler').show(); $btn.prop('disabled', false).html(' Speichern'); }); }); /* ══════════════════════════════════════════════════════════ FEATURE: Live-Suche ══════════════════════════════════════════════════════════ */ var wbfSearchTimer = null; function wbfTimeAgo(dateStr) { var diff = Math.floor((Date.now() - new Date(dateStr).getTime()) / 1000); if (diff < 60) return 'Gerade eben'; if (diff < 3600) return Math.floor(diff/60) + ' Min. ago'; if (diff < 86400) return Math.floor(diff/3600) + ' Std. ago'; return Math.floor(diff/86400) + ' Tage ago'; } $(document).on('input', '#wbfSearchInput', function () { var q = $(this).val().trim(); var $dd = $('#wbfSearchDropdown'); clearTimeout(wbfSearchTimer); if (q.length < 2) { $dd.hide().empty(); return; } wbfSearchTimer = setTimeout(function () { $dd.html('
Suche…
').show(); wbfPost('wbf_search', { query: q }, function (d) { if (!d.results || !d.results.length) { $dd.html('
Keine Ergebnisse für „' + $('').text(q).html() + '“
'); return; } var html = ''; var shown = d.results.slice(0, 6); shown.forEach(function (r) { var isThread = r.result_type === 'thread'; var base3 = WBF.forum_url || window.location.href.split('?')[0]; var sep3 = base3.indexOf('?') !== -1 ? '&' : '?'; var url = base3 + sep3 + 'forum_thread=' + r.id; var preview = r.content ? r.content.replace(/<[^>]+>/g,'').substring(0,80) : ''; var typeLabel = isThread ? ' Thread' : ' Antwort'; html += '
' + '
' + $('').text(r.title.substring(0,55)).html() + '
' + '
' + typeLabel + ' ' + $('').text(r.cat_name).html() + '' + '' + $('').text(r.display_name).html() + '' + '
' + (preview ? '
' + $('').text(preview).html() + '…
' : '') + '
'; }); if (d.results.length > 6) { html += ''; } $dd.html(html).show(); }, function () { $dd.html('
Fehler bei der Suche.
'); }); }, 320); }); // Alle Ergebnisse anzeigen → zur Suchseite $(document).on('click', '.wbf-search-dd-footer', function () { var q = $(this).data('query'); window.location.href = window.location.pathname + '?forum_search=1&q=' + encodeURIComponent(q); }); // Enter-Taste → Suchseite $(document).on('keydown', '#wbfSearchInput', function (e) { if (e.key === 'Enter') { var q = $(this).val().trim(); if (q.length >= 2) { window.location.href = window.location.pathname + '?forum_search=1&q=' + encodeURIComponent(q); } } if (e.key === 'Escape') { $('#wbfSearchDropdown').hide(); } }); // Dropdown schließen bei Klick außerhalb $(document).on('click', function (e) { if (!$(e.target).closest('#wbfSearchForm').length) { $('#wbfSearchDropdown').hide(); } }); /* ══════════════════════════════════════════════════════════ FEATURE: Benachrichtigungen ══════════════════════════════════════════════════════════ */ var wbfNotifLoaded = false; function wbfLoadNotifications() { wbfPost('wbf_get_notifications', {}, function (d) { var $list = $('#wbfNotifList'); if (!d.notifications || !d.notifications.length) { $list.html('

Keine Benachrichtigungen
'); return; } var html = ''; d.notifications.forEach(function (n) { var isUnread = n.is_read == 0; var avatar = n.actor_avatar || ''; var base = WBF.forum_url || window.location.href.split('?')[0]; var sep = base.indexOf('?') !== -1 ? '&' : '?'; var actor = '' + $('').text(n.actor_name).html() + ''; // URL + Text je nach Typ var url, text, sub; if (n.type === 'message') { url = base + sep + 'forum_dm=1'; text = actor + ' hat dir eine Nachricht gesendet'; sub = ''; } else if (n.type === 'mention') { url = base + sep + 'forum_thread=' + n.thread_id; text = actor + ' hat dich erwähnt'; sub = n.thread_title || ''; } else if (n.type === 'like') { url = base + sep + 'forum_thread=' + n.thread_id; text = actor + ' hat deinen Beitrag geliket'; sub = n.thread_title || ''; } else { // reply (default) url = base + sep + 'forum_thread=' + n.thread_id; text = actor + ' hat in deinem Thread geantwortet'; sub = n.thread_title || ''; } html += '' + '
' + '
' + '
' + text + (sub ? '
' + $('').text(sub).html() + '' : '') + '
' + '
' + wbfTimeAgo(n.created_at) + '
' + '
' + (isUnread ? '
' : '') + '
'; }); $list.html(html); // Badge aktualisieren var unread = d.unread || 0; var $badge = $('#wbfNotifBadge'); if (unread > 0) { $badge.text(Math.min(unread,99)).show(); } else { $badge.hide(); } }); wbfNotifLoaded = true; } // Glocke klicken → Dropdown öffnen + Nachrichten laden $(document).on('click', '#wbfNotifBtn', function (e) { e.stopPropagation(); var $dd = $('#wbfNotifDropdown'); if ($dd.is(':visible')) { $dd.hide(); } else { $dd.show(); if (!wbfNotifLoaded) wbfLoadNotifications(); } }); // Alle als gelesen markieren $(document).on('click', '#wbfMarkAllRead', function (e) { e.stopPropagation(); wbfPost('wbf_mark_notifications_read', {}, function () { $('#wbfNotifBadge').hide(); $('#wbfNotifList .wbf-notif-item').removeClass('wbf-notif-item--unread'); $('#wbfNotifList .wbf-notif-dot').remove(); wbfNotifLoaded = false; // neu laden beim nächsten Öffnen }); }); // Benachrichtigung klicken → als gelesen markieren + navigieren $(document).on('click', '.wbf-notif-item', function (e) { e.preventDefault(); var href = $(this).attr('href'); wbfPost('wbf_mark_notifications_read', {}, function () { window.location.href = href; }); }); // Dropdown schließen bei Klick außerhalb $(document).on('click', function (e) { if (!$(e.target).closest('#wbfNotifWrap').length) { $('#wbfNotifDropdown').hide(); } }); // ── Unified Smart Polling ───────────────────────────────────────────────── // Benachrichtigungen + DM-Badge + Live-Konversation in einem einzigen Interval if (WBF.logged_in === 'yes') { var wbfLastMsgId = 0; function wbfPoll() { // 1. Benachrichtigungs-Badge wbfPost('wbf_get_notifications', {}, function(d) { var $badge = $('#wbfNotifBadge'); var unread = d.unread || 0; if (unread > 0) { $badge.text(Math.min(unread,99)).show(); } else { $badge.hide(); } }); // 2. DM-Badge + Live-Nachrichten wbfPost('wbf_get_inbox', {}, function(d) { var unread = parseInt(d.unread) || 0; var $badge = $('.wbf-dm-btn .wbf-notif-badge'); if (unread > 0) { $badge.text(Math.min(unread,99)).css('display',''); } else { $badge.css('display','none'); } // 3. Wenn Konversation offen: neue Nachrichten live nachladen var $conv = $('#wbfDmConversation'); if (!$conv.length || !wbfLastMsgId) return; var partnerId = parseInt($conv.data('partner')); if (!partnerId) return; wbfPost('wbf_get_new_messages', { partner_id: partnerId, since_id: wbfLastMsgId }, function(r) { if (!r.messages || !r.messages.length) return; var $msgs = $('#wbfDmMessages'); var wasAtBottom = $msgs[0].scrollHeight - $msgs[0].scrollTop - $msgs[0].clientHeight < 60; r.messages.forEach(function(m) { if ($('[data-msg-id="' + m.id + '"]').length) return; // kein Duplikat var isMine = parseInt(m.from_id) === parseInt(WBF.my_id); var cls = isMine ? 'wbf-dm-msg wbf-dm-msg--out' : 'wbf-dm-msg wbf-dm-msg--in'; var time = wbfTimeAgo(m.created_at); var delBtn = ''; var html = '
'; if (!isMine) { html += ''; } html += '
' + $('').text(m.content).html().replace(/\n/g,'
') + '
' + time + delBtn + '
'; $msgs.append(html); wbfLastMsgId = Math.max(wbfLastMsgId, parseInt(m.id)); }); if (wasAtBottom) $msgs[0].scrollTop = $msgs[0].scrollHeight; wbfPost('wbf_mark_messages_read', { partner_id: partnerId }); }); }); } // Nach dem Laden der Konversation: hoechste ID merken var origConvLoad = window.wbfConvLoaded; $(document).on('wbf:messages_loaded', function(e, msgs) { if (msgs && msgs.length) { wbfLastMsgId = Math.max.apply(null, msgs.map(function(m){ return parseInt(m.id)||0; })); } }); setTimeout(wbfPoll, 3000); setInterval(wbfPoll, 15000); } /* ══════════════════════════════════════════════════════════ FEATURE: Auto-Logout bei Inaktivität ══════════════════════════════════════════════════════════ */ if ( WBF.logged_in === 'yes' && WBF.auto_logout_minutes > 0 ) { var wbfIdleMs = WBF.auto_logout_minutes * 60 * 1000; var wbfWarnMs = 30 * 1000; // 30 Sek. Vorwarnung var wbfIdleTimer = null; var wbfWarnTimer = null; var wbfCountTimer = null; var wbfWarning = false; // ── Toast-Element ──────────────────────────────────────── var $wbfToast = $([ '
', '
', '', 'Sitzung läuft ab', '
', '

', 'Du wirst in 30 Sekunden', ' automatisch abgemeldet.', '

', '
', '', '', '
', '
' ].join('')).appendTo('body'); function wbfDoLogout() { clearTimeout(wbfIdleTimer); clearTimeout(wbfWarnTimer); clearInterval(wbfCountTimer); $wbfToast.hide(); wbfPost('wbf_logout', {}, function () { location.reload(); }); } function wbfShowWarning() { wbfWarning = true; var secs = 30; $('#wbfIdleCountdown').text(secs); $wbfToast.fadeIn(200); wbfCountTimer = setInterval(function () { secs--; $('#wbfIdleCountdown').text(secs); if (secs <= 0) { clearInterval(wbfCountTimer); wbfDoLogout(); } }, 1000); // Auto-logout after warning period wbfIdleTimer = setTimeout(wbfDoLogout, wbfWarnMs); } function wbfResetIdleTimer() { if (wbfWarning) return; // Nutzer hat aktiv Warnung bestätigt — nicht resetten clearTimeout(wbfIdleTimer); clearTimeout(wbfWarnTimer); // Warn 30 sec before timeout wbfWarnTimer = setTimeout(wbfShowWarning, wbfIdleMs - wbfWarnMs); } // "Bleiben" Button $(document).on('click', '#wbfIdleStay', function () { clearTimeout(wbfIdleTimer); clearInterval(wbfCountTimer); $wbfToast.fadeOut(200); wbfWarning = false; wbfResetIdleTimer(); }); // "Abmelden" Button $(document).on('click', '#wbfIdleLogout', function () { wbfDoLogout(); }); // Aktivitäts-Events überwachen var wbfActivityEvents = 'mousemove keydown mousedown touchstart scroll click'; $(document).on(wbfActivityEvents, function () { if (!wbfWarning) wbfResetIdleTimer(); }); // Start wbfResetIdleTimer(); } /* ── Login: Remember-Me ─────────────────────────────────── */ $(document).on('click', '.wbf-login-submit-btn', function () { var $btn = $(this).prop('disabled', true).html(''); wbfPost('wbf_login', { username: $(this).closest('.wbf-auth-box').find('.wbf-field-username').val(), password: $(this).closest('.wbf-auth-box').find('.wbf-field-password').val(), remember_me: $(this).closest('.wbf-auth-box').find('.wbf-field-remember').is(':checked') ? '1' : '' }, function () { location.reload(); }, function (d) { showMsg($btn.closest('.wbf-auth-box').find('.wbf-login-msg'), d.message || 'Fehler', false); $btn.prop('disabled', false).html(' Einloggen'); }); }); /* ══════════════════════════════════════════════════════════ FEATURE: Reaktionen ══════════════════════════════════════════════════════════ */ // Picker öffnen/schließen $(document).on('click', '.wbf-reaction-trigger', function (e) { e.stopPropagation(); var $picker = $(this).next('.wbf-reaction-picker'); var wasOpen = $picker.is(':visible'); $('.wbf-reaction-picker').hide(); if (!wasOpen) $picker.show(); }); // Reaktion wählen (aus Picker oder Summary) $(document).on('click', '.wbf-reaction-btn, .wbf-reaction-pill', function (e) { e.stopPropagation(); if (WBF.logged_in !== 'yes') { $('#wbfAuthModal').addClass('active'); return; } var $bar = $(this).closest('.wbf-reaction-bar'); var reaction = $(this).data('reaction'); wbfPost('wbf_set_reaction', { object_id: $bar.data('id'), object_type: $bar.data('type'), reaction: reaction }, function (d) { var $summary = $bar.find('.wbf-reaction-summary'); var $picker = $bar.find('.wbf-reaction-picker'); // Rebuild summary var order = ['👍','❤️','😂','😮','😢','😡']; var html = ''; order.forEach(function(e) { if (d.counts[e]) { var active = (d.mine === e) ? ' wbf-reaction-active' : ''; html += ''; } }); if (!$summary.length) { $bar.prepend('
' + html + '
'); } else { $summary.html(html || '').toggle(!!html); } // Update picker active states $picker.find('.wbf-reaction-btn').each(function() { $(this).toggleClass('wbf-reaction-active', $(this).data('reaction') === d.mine); }); $picker.hide(); }); }); // Close pickers on outside click $(document).on('click', function() { $('.wbf-reaction-picker').hide(); }); /* ══════════════════════════════════════════════════════════ FEATURE: @Erwähnungen Autocomplete im Reply-Textarea ══════════════════════════════════════════════════════════ */ var wbfMentionTimer = null; var wbfMentionActive = false; var $wbfMentionDrop = null; function wbfCloseMention() { if ($wbfMentionDrop) $wbfMentionDrop.remove(); $wbfMentionDrop = null; wbfMentionActive = false; } $(document).on('input', '#wbfReplyContent, #wbfThreadContent', function () { var $ta = $(this); var val = $ta.val(); var pos = $ta[0].selectionStart; var before = val.slice(0, pos); var match = before.match(/@([a-zA-Z0-9_]{0,30})$/); if (!match) { wbfCloseMention(); return; } var q = match[1]; wbfMentionActive = true; clearTimeout(wbfMentionTimer); wbfMentionTimer = setTimeout(function() { wbfPost('wbf_user_suggest', { q: q }, function(d) { if (!d.users || !d.users.length) { wbfCloseMention(); return; } if ($wbfMentionDrop) $wbfMentionDrop.remove(); var html = ''; d.users.forEach(function(u) { html += '
' + '' + '' + $('').text(u.display_name).html() + '' + '@' + $('').text(u.username).html() + '' + '
'; }); $wbfMentionDrop = $('
' + html + '
'); $ta.closest('.wbf-reply-form__input, .wbf-form-row').append($wbfMentionDrop); $wbfMentionDrop.show(); }); }, 200); }); $(document).on('click', '.wbf-mention-item', function(e) { e.stopPropagation(); var username = $(this).data('username'); var $ta = $('#wbfReplyContent:visible, #wbfThreadContent:visible').first(); if (!$ta.length) return; var val = $ta.val(), pos = $ta[0].selectionStart; var before = val.slice(0, pos); var after = val.slice(pos); var newBefore = before.replace(/@([a-zA-Z0-9_]*)$/, '@' + username + ' '); $ta.val(newBefore + after); $ta[0].selectionStart = $ta[0].selectionEnd = newBefore.length; wbfCloseMention(); $ta.focus(); }); $(document).on('click', function(e) { if (!$(e.target).closest('.wbf-mention-dropdown').length) wbfCloseMention(); }); /* ══════════════════════════════════════════════════════════ FEATURE: Private Nachrichten (DM) ══════════════════════════════════════════════════════════ */ // Helper: format messages in conversation function wbfRenderMessages(msgs, myId) { if (!msgs || !msgs.length) { return '

Noch keine Nachrichten.

'; } var html = ''; msgs.forEach(function(m) { var isMine = parseInt(m.from_id) === parseInt(myId); var cls = isMine ? 'wbf-dm-msg wbf-dm-msg--out' : 'wbf-dm-msg wbf-dm-msg--in'; var time = wbfTimeAgo(m.created_at); var delBtn = ''; if (!isMine) { html += '
' + '' + '
' + $('').text(m.content).html().replace(/\n/g,'
') + '
' + time + delBtn + '
'; } else { html += '
' + '
' + $('').text(m.content).html().replace(/\n/g,'
') + '
' + time + delBtn + '
'; } }); return html; } // Render inbox list function wbfRenderInbox(inbox, myId) { if (!inbox || !inbox.length) { return '
Keine Nachrichten.
'; } var html = ''; inbox.forEach(function(conv) { var href = window.location.pathname + '?forum_dm=inbox&with=' + conv.partner_id; var unread = parseInt(conv.unread_cnt) > 0; html += '' + '' + '
' + '' + $('').text(conv.partner_name).html() + '' + (unread ? '' + conv.unread_cnt + '' : '') + '
'; }); return html; } // Auto-load inbox if on DM page if ($('#wbfDmInbox').length && WBF.logged_in === 'yes') { wbfPost('wbf_get_inbox', {}, function(d) { $('#wbfDmInbox').html(wbfRenderInbox(d.inbox, WBF.my_id)); }); // Load conversation if partner given var $conv = $('#wbfDmConversation'); if ($conv.length) { var partnerId = $conv.data('partner'); wbfPost('wbf_get_conversation', { partner_id: partnerId }, function(d) { // Header var p = d.partner; if (p) { var backUrl = window.location.pathname + '?forum_dm=inbox'; $('#wbfDmHeader').html( '' + '' + '' + $('').text(p.display_name).html() + '' + '@' + $('').text(p.username).html() + '' ); } var html = wbfRenderMessages(d.messages, d.my_id); var $msgs = $('#wbfDmMessages').html(html); $msgs[0].scrollTop = $msgs[0].scrollHeight; $(document).trigger('wbf:messages_loaded', [d.messages]); // "Ältere laden" initialisieren — AJAX gibt total zurück if (d.total !== undefined) { $('#wbfDmLoadMore').data('offset', 0).data('partner', d.partner ? d.partner.id : 0); wbfUpdateLoadMoreBtn(d.total, d.messages.length); } }); } } // Send reply in open conversation $(document).on('click', '#wbfDmSendReply', function() { var toId = $(this).data('to'); var text = $('#wbfDmReplyText').val().trim(); if (!text) return; var $btn = $(this).prop('disabled', true); wbfPost('wbf_send_message', { to_id: toId, content: text }, function(d) { var delBtn = ''; var html = '
' + '
' + $('').text(d.content).html().replace(/\n/g,'
') + '
Gerade eben' + delBtn + '
'; var $msgs = $('#wbfDmMessages'); $msgs.append(html); $msgs[0].scrollTop = $msgs[0].scrollHeight; $('#wbfDmReplyText').val(''); $btn.prop('disabled', false); if (d.message_id) wbfLastMsgId = Math.max(wbfLastMsgId, parseInt(d.message_id)); }, function(e) { alert(e.message || 'Fehler'); $btn.prop('disabled', false); }); }); // Delete message $(document).on('click', '.wbf-dm-msg__del', function() { var msgId = $(this).data('id'); var $row = $(this).closest('[data-msg-id]'); if (!confirm('Nachricht löschen?')) return; wbfPost('wbf_delete_message', { message_id: msgId }, function() { $row.fadeOut(200, function() { $(this).remove(); }); }, function(e) { alert(e.message || 'Fehler beim Löschen.'); }); }); // Enter to send (Shift+Enter = newline) $(document).on('keydown', '#wbfDmReplyText', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); $('#wbfDmSendReply').trigger('click'); } }); // New DM button → open compose modal $(document).on('click', '#wbfNewDmBtn, #wbfNewDmBtn2', function() { $('#wbfDmRecipientInput').val(''); $('#wbfDmToId').val(''); $('#wbfDmComposeText').val(''); $('#wbfDmComposeMsg').hide(); $('#wbfDmComposeModal').addClass('active'); }); // Recipient autocomplete in compose modal var wbfDmSugTimer = null; $(document).on('input', '#wbfDmRecipientInput', function() { var q = $(this).val().trim(); clearTimeout(wbfDmSugTimer); if (!q) { $('#wbfDmSuggest').hide().empty(); return; } wbfDmSugTimer = setTimeout(function() { wbfPost('wbf_user_suggest', { q: q }, function(d) { var $s = $('#wbfDmSuggest'); if (!d.users || !d.users.length) { $s.hide().empty(); return; } var html = ''; d.users.forEach(function(u) { html += '
' + '' + $('').text(u.display_name).html() + '@' + $('').text(u.username).html() + '' + '
'; }); $s.html(html).show(); }); }, 200); }); $(document).on('click', '#wbfDmSuggest .wbf-tag-suggest-item', function() { var id = $(this).data('id'); var name = $(this).data('name'); $('#wbfDmToId').val(id); $('#wbfDmRecipientInput').val(name); $('#wbfDmSuggest').hide().empty(); }); // Send from compose modal $(document).on('click', '#wbfDmComposeSend', function() { var toId = $('#wbfDmToId').val(); var text = $('#wbfDmComposeText').val().trim(); var $btn = $(this).prop('disabled', true).html(''); if (!toId) { showMsg($('#wbfDmComposeMsg'), 'Bitte Empfänger wählen.', false); $btn.prop('disabled', false).html(' Senden'); return; } if (!text) { showMsg($('#wbfDmComposeMsg'), 'Nachricht leer.', false); $btn.prop('disabled', false).html(' Senden'); return; } wbfPost('wbf_send_message', { to_id: toId, content: text }, function() { showMsg($('#wbfDmComposeMsg'), '✔ Gesendet!', true); setTimeout(function() { $('#wbfDmComposeModal').removeClass('active'); window.location.href = window.location.pathname + '?forum_dm=inbox&with=' + toId; }, 800); }, function(e) { showMsg($('#wbfDmComposeMsg'), e.message || 'Fehler', false); $btn.prop('disabled', false).html(' Senden'); }); }); /* ══════════════════════════════════════════════════════════ FEATURE: Online-Nutzer (Notification polling erweitern) ══════════════════════════════════════════════════════════ */ /* ══════════════════════════════════════════════════════════ FEATURE: Passwort vergessen ══════════════════════════════════════════════════════════ */ // "Passwort vergessen?" → Panel wechseln $(document).on('click', '.wbf-forgot-link', function(e) { e.preventDefault(); $('.wbf-auth-tab').removeClass('active'); $('.wbf-auth-panel').removeClass('active'); $('[data-panel="forgot"]').addClass('active'); }); $(document).on('click', '.wbf-show-login', function(e) { e.preventDefault(); $('.wbf-auth-panel').removeClass('active'); $('[data-tab="login"]').addClass('active'); $('[data-panel="login"]').addClass('active'); }); // Reset-Link anfordern $(document).on('click', '.wbf-forgot-submit-btn', function() { var $btn = $(this).prop('disabled', true).html(''); wbfPost('wbf_forgot_password', { email: $(this).closest('.wbf-auth-box').find('.wbf-field-forgot-email').val() }, function(d) { showMsg($btn.closest('.wbf-auth-box').find('.wbf-forgot-msg'), d.message, true); $btn.prop('disabled', false).html(' Reset-Link senden'); }, function(d) { showMsg($btn.closest('.wbf-auth-box').find('.wbf-forgot-msg'), d.message || 'Fehler', false); $btn.prop('disabled', false).html(' Reset-Link senden'); }); }); // Passwort-Reset Formular (separate Seite via ?wbf_reset_token=...) $(document).on('click', '#wbfResetSubmit', function() { var $btn = $(this).prop('disabled', true).html(''); wbfPost('wbf_reset_password', { token: $('#wbfResetToken').val(), password: $('#wbfResetPass1').val(), password2: $('#wbfResetPass2').val() }, function(d) { showMsg($('#wbfResetMsg'), d.message, true); $btn.html(' Passwort geändert!'); setTimeout(function() { window.location.href = WBF.forum_url || window.location.pathname.split('?')[0]; }, 2000); }, function(d) { showMsg($('#wbfResetMsg'), d.message || 'Fehler', false); $btn.prop('disabled', false).html(' Passwort ändern'); }); }); /* ══════════════════════════════════════════════════════════ FEATURE: Ältere Nachrichten laden (DM) ══════════════════════════════════════════════════════════ */ // Wird nach dem ersten Laden der Konversation aufgerufen function wbfUpdateLoadMoreBtn(total, currentCount) { var $wrap = $('#wbfDmLoadMoreWrap'); var $btn = $('#wbfDmLoadMore'); if (total > currentCount) { var remaining = total - currentCount; $btn.html(' ' + remaining + ' ältere Nachrichten laden'); $wrap.show(); } else { $wrap.hide(); } } $(document).on('click', '#wbfDmLoadMore', function() { var $btn = $(this).prop('disabled', true).html(''); var partnerId = $(this).data('partner'); var offset = parseInt($(this).data('offset')) || 0; var loadCount = 30; var newOffset = offset + loadCount; wbfPost('wbf_load_more_messages', { partner_id: partnerId, offset: newOffset }, function(d) { if (!d.messages || !d.messages.length) { $('#wbfDmLoadMoreWrap').hide(); return; } // Ältere Nachrichten oben einfügen var html = wbfRenderMessages(d.messages, d.my_id); var $msgs = $('#wbfDmMessages'); var oldHeight = $msgs[0].scrollHeight; $msgs.prepend(html); // Scroll-Position halten (nicht nach oben springen) $msgs.scrollTop($msgs[0].scrollHeight - oldHeight); // Offset aktualisieren $('#wbfDmLoadMore').data('offset', newOffset).prop('disabled', false); // Button update var loaded = newOffset + d.messages.length; wbfUpdateLoadMoreBtn(d.total, loaded); }, function() { $btn.prop('disabled', false).html(' Ältere laden'); }); }); }(jQuery));