Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
611 changes: 611 additions & 0 deletions assets/media-live-search.css

Large diffs are not rendered by default.

210 changes: 210 additions & 0 deletions assets/media-live-search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/**
* Quick Navigation Media Live Search
* Erweitert das bestehende Mediapool-Suchfeld um Live-Suche
*/

$(document).on('rex:ready', function() {
initQuickNavigationMediaLiveSearch();
});

function initQuickNavigationMediaLiveSearch() {
// Prüfen ob Live-Search vom User aktiviert ist
if (typeof rex !== 'undefined' && rex.QUICKNAV_MEDIA_LIVESEARCH_ENABLED === false) {
return;
}

// Prüfen ob wir im Mediapool sind
var isMediapool = $('body').hasClass('rex-page-mediapool') ||
$('[data-page="mediapool"]').length > 0 ||
window.location.href.indexOf('page=mediapool') !== -1;

if (!isMediapool) {
return;
}

var searchInput = $('#be_search-media-name');
var searchResults = null;
var searchTimer = null;
var currentRequest = null;

if (searchInput.length === 0) {
return;
}

// Container für Live-Suche Ergebnisse relativ zum bestehenden Suchfeld erstellen
var resultsContainer = $('<div class="qn-media-live-search-results"></div>');
var searchForm = searchInput.closest('.form-group, .input-group, form');
searchForm.css('position', 'relative');
searchForm.append(resultsContainer);

// Event Handler für Live-Suche (zusätzlich zur normalen Suchfunktion)
searchInput.on('input.quicknav', function() {
var searchTerm = $(this).val().trim();

// Timer zurücksetzen
if (searchTimer) {
clearTimeout(searchTimer);
}

// Laufende Requests abbrechen
if (currentRequest) {
currentRequest.abort();
currentRequest = null;
}

if (searchTerm.length === 0) {
resultsContainer.hide();
return;
}

if (searchTerm.length < 2) {
return; // Erst ab 2 Zeichen Live-Suche
}

// Kurz warten vor der Suche (Debouncing)
searchTimer = setTimeout(function() {
performQuickNavMediaSearch(searchTerm, resultsContainer);
}, 300);
});

// Klick außerhalb schließt die Ergebnisse
$(document).on('click.quicknav', function(e) {
if (!$(e.target).closest('.qn-media-live-search-results, #be_search-media-name').length) {
resultsContainer.hide();
}
});

// ESC schließt die Ergebnisse
searchInput.on('keydown.quicknav', function(e) {
if (e.keyCode === 27) { // ESC
resultsContainer.hide();
}
});

function performQuickNavMediaSearch(searchTerm, container) {
// Loading anzeigen
container.html('<div class="qn-live-search-loading"><i class="fa fa-spinner fa-spin"></i> Suche läuft...</div>')
.show();

// Parameter aus der aktuellen Seite holen
var categoryId = $('#rex_file_category').val() || 0;
var openerInputField = $('input[name="opener_input_field"]').val() || '';
var types = $('input[name="args[types]"]').val() || '';

// AJAX Request zur Quick Navigation API
currentRequest = $.ajax({
url: window.location.pathname + window.location.search,
method: 'GET',
data: {
'rex-api-call': 'quicknavigation_media_search',
'term': searchTerm,
'category_id': categoryId,
'opener_input_field': openerInputField,
'types': types
},
dataType: 'json',
success: function(response) {
currentRequest = null;

if (response.success) {
displayQuickNavSearchResults(response.results, container);
} else {
container.html('<div class="qn-live-search-no-results">Fehler: ' + (response.error || 'Unbekannter Fehler') + '</div>');
}
},
error: function(xhr, status, error) {
currentRequest = null;

if (status !== 'abort') {
container.html('<div class="qn-live-search-no-results">Fehler beim Laden der Suchergebnisse</div>');
}
}
});
}
}

function displayQuickNavSearchResults(results, container) {
if (results.length === 0) {
container.html('<div class="qn-live-search-no-results">Keine Ergebnisse gefunden</div>');
container.show();
return;
}

var html = '';

$.each(results, function(index, item) {
var thumbnail = '';

if (item.thumbnail.type === 'image') {
thumbnail = '<img src="' + item.thumbnail.src + '" alt="' + item.thumbnail.alt + '" loading="lazy">';
} else if (item.thumbnail.type === 'icon') {
thumbnail = '<i class="' + item.thumbnail.icon + '" title="' + item.thumbnail.title + '"></i>';
} else if (item.thumbnail.type === 'error') {
thumbnail = '<i class="' + item.thumbnail.icon + '" title="' + item.thumbnail.title + '" style="color: #dc3545;"></i>';
}

var detailUrl = '';
if (item.actions.edit) {
detailUrl = item.actions.edit.url;
}

if (item.actions.select) {
// Widget-Modus: Buttons untereinander anzeigen
html += '<div class="qn-live-search-item">' +
'<div class="qn-live-search-item-content">' +
'<div class="qn-live-search-thumb">' + thumbnail + '</div>' +
'<div class="qn-live-search-info">' +
'<div class="qn-live-search-title">' + item.title + '</div>' +
'<div class="qn-live-search-filename">' + item.filename + '</div>' +
'<div class="qn-live-search-meta">' + item.size + ' • ' + item.updatedate + '</div>' +
'</div>' +
'</div>' +
'<div class="qn-live-search-actions">';

// Übernehmen-Button
html += '<button type="button" class="btn btn-xs btn-select" onclick="';

if (item.actions.select.type === 'media') {
html += 'selectMedia(\'' + item.actions.select.filename + '\', \'' + item.actions.select.title + '\'); $(this).closest(\'.qn-media-live-search-results\').hide(); return false;';
} else if (item.actions.select.type === 'medialist') {
html += 'selectMedialist(\'' + item.actions.select.filename + '\', this); $(this).closest(\'.qn-media-live-search-results\').hide(); return false;';
}

html += '">' + item.actions.select.label + '</button>';

// Details-Button
if (detailUrl) {
html += '<a href="' + detailUrl + '" class="btn btn-xs btn-default">Details</a>';
}

html += '</div></div>';

} else if (detailUrl) {
// Normaler Modus: Komplettes Element als Link zur Detailansicht
html += '<a href="' + detailUrl + '" class="qn-live-search-item" style="color: inherit; text-decoration: none;">' +
'<div class="qn-live-search-item-content">' +
'<div class="qn-live-search-thumb">' + thumbnail + '</div>' +
'<div class="qn-live-search-info">' +
'<div class="qn-live-search-title">' + item.title + '</div>' +
'<div class="qn-live-search-filename">' + item.filename + '</div>' +
'<div class="qn-live-search-meta">' + item.size + ' • ' + item.updatedate + '</div>' +
'</div>' +
'</div>' +
'</a>';
} else {
// Fallback ohne Link
html += '<div class="qn-live-search-item">' +
'<div class="qn-live-search-item-content">' +
'<div class="qn-live-search-thumb">' + thumbnail + '</div>' +
'<div class="qn-live-search-info">' +
'<div class="qn-live-search-title">' + item.title + '</div>' +
'<div class="qn-live-search-filename">' + item.filename + '</div>' +
'<div class="qn-live-search-meta">' + item.size + ' • ' + item.updatedate + '</div>' +
'</div>' +
'</div>' +
'</div>';
}
});

container.html(html).show();
}
9 changes: 9 additions & 0 deletions boot.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace FriendsOfRedaxo\QuickNavigation;

use FriendsOfRedaxo\QuickNavigation\ApiFunction\MenuRender;
use FriendsOfRedaxo\QuickNavigation\ApiFunction\MediaSearch;
use FriendsOfRedaxo\QuickNavigation\Button\ArticleHistoryButton;
use FriendsOfRedaxo\QuickNavigation\Button\ButtonRegistry;
use FriendsOfRedaxo\QuickNavigation\Button\ArticleNavigationButton;
Expand All @@ -38,8 +39,16 @@
if (rex::isBackend() && rex::getUser() && rex_backend_login::hasSession() && rex_be_controller::getCurrentPage() != '2factor_auth_verify') {
if (rex::getUser()->hasPerm('quick_navigation[]')) {
rex_api_function::register('quicknavigation_api', MenuRender::class);
rex_api_function::register('quicknavigation_media_search', 'rex_api_quicknavigation_media_search');
rex_view::addCssFile(rex_addon::get('quick_navigation')->getAssetsUrl('quick-navigation.css'));
rex_view::addCssFile(rex_addon::get('quick_navigation')->getAssetsUrl('media-live-search.css'));
rex_view::addJsFile(rex_addon::get('quick_navigation')->getAssetsUrl('quick-navigation.js'));
rex_view::addJsFile(rex_addon::get('quick_navigation')->getAssetsUrl('media-live-search.js'));

// Media Live-Search Einstellung für aktuellen User
$userId = rex::getUser()->getId();
$mediaLiveSearchEnabled = rex_addon::get('quick_navigation')->getConfig('quick_navigation_media_livesearch' . $userId, 1); // Default: aktiviert
rex_view::setJsProperty('QUICKNAV_MEDIA_LIVESEARCH_ENABLED', (bool) $mediaLiveSearchEnabled);

$userId = rex::getUser()->getId();
if (rex_addon::get('quick_navigation')->getConfig('quick_navigation_artdirections' . $userId) != '1') {
Expand Down
7 changes: 7 additions & 0 deletions lang/de_de.lang
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,10 @@ quick_navigation_yform_add = Datensatz hinzufügen in:
quick_navigation_media_sort_alpha = Nach Dateinamen sortieren (A-Z)
quick_navigation_media_sort_date = Nach Datum sortieren (neueste zuerst)
quick_navigation_media_sort_title = Nach Titel sortieren (A-Z)

# Media Live-Search
quick_navigation_media_livesearch = Medienpool Live-Suche aktivieren?
quick_navigation_media_live_search_placeholder = Live-Suche...

# Live Search
quick_navigation_media_live_search_placeholder = Live-Suche...
9 changes: 9 additions & 0 deletions lang/en_gb.lang
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ quick_navigation_favorite_article_add = Add article to:
quick_navigation_favorite_category_add = Add category to:
quick_navigation_yform = YForm
quick_navigation_yform_add = Add dataset to:

# Media sorting
quick_navigation_media_sort_alpha = Sort by filename (A-Z)
quick_navigation_media_sort_date = Sort by date (newest first)
quick_navigation_media_sort_title = Sort by title (A-Z)

# Media Live-Search
quick_navigation_media_livesearch = Enable media live search?
quick_navigation_media_live_search_placeholder = Live search...
Loading