Skip to content

Commit 2a85175

Browse files
authored
Merge pull request #195 from FriendsOfREDAXO/media_live_search
Media live Search 5.3.0
2 parents 1a4c7d1 + 4ca45cf commit 2a85175

9 files changed

Lines changed: 1150 additions & 7 deletions

File tree

assets/media-live-search.css

Lines changed: 611 additions & 0 deletions
Large diffs are not rendered by default.

assets/media-live-search.js

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
/**
2+
* Quick Navigation Media Live Search
3+
* Erweitert das bestehende Mediapool-Suchfeld um Live-Suche
4+
*/
5+
6+
$(document).on('rex:ready', function() {
7+
initQuickNavigationMediaLiveSearch();
8+
});
9+
10+
function initQuickNavigationMediaLiveSearch() {
11+
// Prüfen ob Live-Search vom User aktiviert ist
12+
if (typeof rex !== 'undefined' && rex.QUICKNAV_MEDIA_LIVESEARCH_ENABLED === false) {
13+
return;
14+
}
15+
16+
// Prüfen ob wir im Mediapool sind
17+
var isMediapool = $('body').hasClass('rex-page-mediapool') ||
18+
$('[data-page="mediapool"]').length > 0 ||
19+
window.location.href.indexOf('page=mediapool') !== -1;
20+
21+
if (!isMediapool) {
22+
return;
23+
}
24+
25+
var searchInput = $('#be_search-media-name');
26+
var searchResults = null;
27+
var searchTimer = null;
28+
var currentRequest = null;
29+
30+
if (searchInput.length === 0) {
31+
return;
32+
}
33+
34+
// Container für Live-Suche Ergebnisse relativ zum bestehenden Suchfeld erstellen
35+
var resultsContainer = $('<div class="qn-media-live-search-results"></div>');
36+
var searchForm = searchInput.closest('.form-group, .input-group, form');
37+
searchForm.css('position', 'relative');
38+
searchForm.append(resultsContainer);
39+
40+
// Event Handler für Live-Suche (zusätzlich zur normalen Suchfunktion)
41+
searchInput.on('input.quicknav', function() {
42+
var searchTerm = $(this).val().trim();
43+
44+
// Timer zurücksetzen
45+
if (searchTimer) {
46+
clearTimeout(searchTimer);
47+
}
48+
49+
// Laufende Requests abbrechen
50+
if (currentRequest) {
51+
currentRequest.abort();
52+
currentRequest = null;
53+
}
54+
55+
if (searchTerm.length === 0) {
56+
resultsContainer.hide();
57+
return;
58+
}
59+
60+
if (searchTerm.length < 2) {
61+
return; // Erst ab 2 Zeichen Live-Suche
62+
}
63+
64+
// Kurz warten vor der Suche (Debouncing)
65+
searchTimer = setTimeout(function() {
66+
performQuickNavMediaSearch(searchTerm, resultsContainer);
67+
}, 300);
68+
});
69+
70+
// Klick außerhalb schließt die Ergebnisse
71+
$(document).on('click.quicknav', function(e) {
72+
if (!$(e.target).closest('.qn-media-live-search-results, #be_search-media-name').length) {
73+
resultsContainer.hide();
74+
}
75+
});
76+
77+
// ESC schließt die Ergebnisse
78+
searchInput.on('keydown.quicknav', function(e) {
79+
if (e.keyCode === 27) { // ESC
80+
resultsContainer.hide();
81+
}
82+
});
83+
84+
function performQuickNavMediaSearch(searchTerm, container) {
85+
// Loading anzeigen
86+
container.html('<div class="qn-live-search-loading"><i class="fa fa-spinner fa-spin"></i> Suche läuft...</div>')
87+
.show();
88+
89+
// Parameter aus der aktuellen Seite holen
90+
var categoryId = $('#rex_file_category').val() || 0;
91+
var openerInputField = $('input[name="opener_input_field"]').val() || '';
92+
var types = $('input[name="args[types]"]').val() || '';
93+
94+
// AJAX Request zur Quick Navigation API
95+
currentRequest = $.ajax({
96+
url: window.location.pathname + window.location.search,
97+
method: 'GET',
98+
data: {
99+
'rex-api-call': 'quicknavigation_media_search',
100+
'term': searchTerm,
101+
'category_id': categoryId,
102+
'opener_input_field': openerInputField,
103+
'types': types
104+
},
105+
dataType: 'json',
106+
success: function(response) {
107+
currentRequest = null;
108+
109+
if (response.success) {
110+
displayQuickNavSearchResults(response.results, container);
111+
} else {
112+
container.html('<div class="qn-live-search-no-results">Fehler: ' + (response.error || 'Unbekannter Fehler') + '</div>');
113+
}
114+
},
115+
error: function(xhr, status, error) {
116+
currentRequest = null;
117+
118+
if (status !== 'abort') {
119+
container.html('<div class="qn-live-search-no-results">Fehler beim Laden der Suchergebnisse</div>');
120+
}
121+
}
122+
});
123+
}
124+
}
125+
126+
function displayQuickNavSearchResults(results, container) {
127+
if (results.length === 0) {
128+
container.html('<div class="qn-live-search-no-results">Keine Ergebnisse gefunden</div>');
129+
container.show();
130+
return;
131+
}
132+
133+
var html = '';
134+
135+
$.each(results, function(index, item) {
136+
var thumbnail = '';
137+
138+
if (item.thumbnail.type === 'image') {
139+
thumbnail = '<img src="' + item.thumbnail.src + '" alt="' + item.thumbnail.alt + '" loading="lazy">';
140+
} else if (item.thumbnail.type === 'icon') {
141+
thumbnail = '<i class="' + item.thumbnail.icon + '" title="' + item.thumbnail.title + '"></i>';
142+
} else if (item.thumbnail.type === 'error') {
143+
thumbnail = '<i class="' + item.thumbnail.icon + '" title="' + item.thumbnail.title + '" style="color: #dc3545;"></i>';
144+
}
145+
146+
var detailUrl = '';
147+
if (item.actions.edit) {
148+
detailUrl = item.actions.edit.url;
149+
}
150+
151+
if (item.actions.select) {
152+
// Widget-Modus: Buttons untereinander anzeigen
153+
html += '<div class="qn-live-search-item">' +
154+
'<div class="qn-live-search-item-content">' +
155+
'<div class="qn-live-search-thumb">' + thumbnail + '</div>' +
156+
'<div class="qn-live-search-info">' +
157+
'<div class="qn-live-search-title">' + item.title + '</div>' +
158+
'<div class="qn-live-search-filename">' + item.filename + '</div>' +
159+
'<div class="qn-live-search-meta">' + item.size + ' • ' + item.updatedate + '</div>' +
160+
'</div>' +
161+
'</div>' +
162+
'<div class="qn-live-search-actions">';
163+
164+
// Übernehmen-Button
165+
html += '<button type="button" class="btn btn-xs btn-select" onclick="';
166+
167+
if (item.actions.select.type === 'media') {
168+
html += 'selectMedia(\'' + item.actions.select.filename + '\', \'' + item.actions.select.title + '\'); $(this).closest(\'.qn-media-live-search-results\').hide(); return false;';
169+
} else if (item.actions.select.type === 'medialist') {
170+
html += 'selectMedialist(\'' + item.actions.select.filename + '\', this); $(this).closest(\'.qn-media-live-search-results\').hide(); return false;';
171+
}
172+
173+
html += '">' + item.actions.select.label + '</button>';
174+
175+
// Details-Button
176+
if (detailUrl) {
177+
html += '<a href="' + detailUrl + '" class="btn btn-xs btn-default">Details</a>';
178+
}
179+
180+
html += '</div></div>';
181+
182+
} else if (detailUrl) {
183+
// Normaler Modus: Komplettes Element als Link zur Detailansicht
184+
html += '<a href="' + detailUrl + '" class="qn-live-search-item" style="color: inherit; text-decoration: none;">' +
185+
'<div class="qn-live-search-item-content">' +
186+
'<div class="qn-live-search-thumb">' + thumbnail + '</div>' +
187+
'<div class="qn-live-search-info">' +
188+
'<div class="qn-live-search-title">' + item.title + '</div>' +
189+
'<div class="qn-live-search-filename">' + item.filename + '</div>' +
190+
'<div class="qn-live-search-meta">' + item.size + ' • ' + item.updatedate + '</div>' +
191+
'</div>' +
192+
'</div>' +
193+
'</a>';
194+
} else {
195+
// Fallback ohne Link
196+
html += '<div class="qn-live-search-item">' +
197+
'<div class="qn-live-search-item-content">' +
198+
'<div class="qn-live-search-thumb">' + thumbnail + '</div>' +
199+
'<div class="qn-live-search-info">' +
200+
'<div class="qn-live-search-title">' + item.title + '</div>' +
201+
'<div class="qn-live-search-filename">' + item.filename + '</div>' +
202+
'<div class="qn-live-search-meta">' + item.size + ' • ' + item.updatedate + '</div>' +
203+
'</div>' +
204+
'</div>' +
205+
'</div>';
206+
}
207+
});
208+
209+
container.html(html).show();
210+
}

boot.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace FriendsOfRedaxo\QuickNavigation;
1313

1414
use FriendsOfRedaxo\QuickNavigation\ApiFunction\MenuRender;
15+
use FriendsOfRedaxo\QuickNavigation\ApiFunction\MediaSearch;
1516
use FriendsOfRedaxo\QuickNavigation\Button\ArticleHistoryButton;
1617
use FriendsOfRedaxo\QuickNavigation\Button\ButtonRegistry;
1718
use FriendsOfRedaxo\QuickNavigation\Button\ArticleNavigationButton;
@@ -38,8 +39,16 @@
3839
if (rex::isBackend() && rex::getUser() && rex_backend_login::hasSession() && rex_be_controller::getCurrentPage() != '2factor_auth_verify') {
3940
if (rex::getUser()->hasPerm('quick_navigation[]')) {
4041
rex_api_function::register('quicknavigation_api', MenuRender::class);
42+
rex_api_function::register('quicknavigation_media_search', 'rex_api_quicknavigation_media_search');
4143
rex_view::addCssFile(rex_addon::get('quick_navigation')->getAssetsUrl('quick-navigation.css'));
44+
rex_view::addCssFile(rex_addon::get('quick_navigation')->getAssetsUrl('media-live-search.css'));
4245
rex_view::addJsFile(rex_addon::get('quick_navigation')->getAssetsUrl('quick-navigation.js'));
46+
rex_view::addJsFile(rex_addon::get('quick_navigation')->getAssetsUrl('media-live-search.js'));
47+
48+
// Media Live-Search Einstellung für aktuellen User
49+
$userId = rex::getUser()->getId();
50+
$mediaLiveSearchEnabled = rex_addon::get('quick_navigation')->getConfig('quick_navigation_media_livesearch' . $userId, 1); // Default: aktiviert
51+
rex_view::setJsProperty('QUICKNAV_MEDIA_LIVESEARCH_ENABLED', (bool) $mediaLiveSearchEnabled);
4352

4453
$userId = rex::getUser()->getId();
4554
if (rex_addon::get('quick_navigation')->getConfig('quick_navigation_artdirections' . $userId) != '1') {

lang/de_de.lang

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,10 @@ quick_navigation_yform_add = Datensatz hinzufügen in:
2828
quick_navigation_media_sort_alpha = Nach Dateinamen sortieren (A-Z)
2929
quick_navigation_media_sort_date = Nach Datum sortieren (neueste zuerst)
3030
quick_navigation_media_sort_title = Nach Titel sortieren (A-Z)
31+
32+
# Media Live-Search
33+
quick_navigation_media_livesearch = Medienpool Live-Suche aktivieren?
34+
quick_navigation_media_live_search_placeholder = Live-Suche...
35+
36+
# Live Search
37+
quick_navigation_media_live_search_placeholder = Live-Suche...

lang/en_gb.lang

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,12 @@ quick_navigation_favorite_article_add = Add article to:
2323
quick_navigation_favorite_category_add = Add category to:
2424
quick_navigation_yform = YForm
2525
quick_navigation_yform_add = Add dataset to:
26+
27+
# Media sorting
28+
quick_navigation_media_sort_alpha = Sort by filename (A-Z)
29+
quick_navigation_media_sort_date = Sort by date (newest first)
30+
quick_navigation_media_sort_title = Sort by title (A-Z)
31+
32+
# Media Live-Search
33+
quick_navigation_media_livesearch = Enable media live search?
34+
quick_navigation_media_live_search_placeholder = Live search...

0 commit comments

Comments
 (0)