Änderungen von Dokument Solr Search
am 2025/12/16 11:14
Zusammenfassung
Details
- Seiteneigenschaften
-
- Dokument-Autor
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki.d herrman1 +XWiki.admin
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,7 +1,11 @@ 1 1 require(['jquery', 'xwiki-events-bridge'], function($) { 2 2 var enhanceSearchResultHighlights = function() { 3 - consthighlights = $(this).removeClass('hidden').prev('.search-result-highlights').addClass('preview');3 + var highlights = $(this).removeClass('hidden').parent().prev('.search-result-highlights').addClass('preview'); 4 4 5 + // Workaround for IE8 which doesn't support :first-of-type CSS selector. 6 + highlights.find('.search-result-highlight').first().addClass('first').parent('dd').addClass('first') 7 + .prev('dt').addClass('first'); 8 + 5 5 $(this).one('click', function(event) { 6 6 event.preventDefault(); 7 7 $(event.target).remove(); ... ... @@ -33,16 +33,10 @@ 33 33 } 34 34 }; 35 35 36 - var addFacetValueCheckbox = function() { 40 + var addFacetValueCheckbox = function(index) { 37 37 // Create an id unique to the facet value. 38 38 let facetContainer = $(this).parents('.search-facet').first(); 39 - // We need the ids of the target facet elements to stay stable through the change, in order to refocus the item 40 - // that was clicked and triggered the change. 41 - // We use the JQuery index, so that id indexes are reset across facetContainers. 42 - // This allows for stable indexes: when reloading the facets after changing the filter for the target facet X, 43 - // the ids of all the checkbox for the target facet X will keep the same index. 44 - // This property is lost if multiple facets are changed in the query at once. 45 - $(this).attr('id', facetContainer.attr('data-name') + '-' + facetContainer.find('a.itemName').index($(this))); 43 + $(this).attr('id', facetContainer.attr('data-name') + '-' + index.toString()); 46 46 // Initialize the checkbox. 47 47 let checkBox = $(document.createElement('input')).attr('type', 'checkbox'); 48 48 checkBox.attr('aria-labelledby', $(this).attr('id')); ... ... @@ -70,7 +70,7 @@ 70 70 updateExpandCollapseAllFacetsState(facetsContainer); 71 71 72 72 // Expand/Collapse toggle for each facet. 73 - facetsContainer.find('.facet-toggle').on('click', function(event) { 71 + facetsContainer.find('.facet-toggler').on('click', function(event) { 74 74 $(event.target).parents('.search-facet').toggleClass('expanded'); 75 75 updateExpandCollapseAllFacetsState(facetsContainer); 76 76 }); ... ... @@ -85,11 +85,6 @@ 85 85 var queryIndex = url.indexOf('?'); 86 86 return queryIndex < 0 ? '' : url.substr(queryIndex + 1); 87 87 }; 88 - 89 - let removeQueryString = function(url) { 90 - let queryIndex = url.indexOf('?'); 91 - return queryIndex < 0 ? url : url.substring(0, queryIndex); 92 - }; 93 93 94 94 var getSearchUIState = function() { 95 95 var expandedFacets = []; ... ... @@ -119,9 +119,7 @@ 119 119 120 120 var searchRequest = null; 121 121 122 - // changeTargetSelector is the CSS selector of the facet anchor that initiated this reload. ' 123 - // We expect the focus to go back to this place once the UI is reloaded. 124 - var pushSearchUIState = function(viewURL, changeTargetSelector) { 115 + var pushSearchUIState = function(viewURL) { 125 125 // If there is a request in progress, abort it to prevent its callback from being called. 126 126 searchRequest && searchRequest.abort(); 127 127 $('.search-ui').attr('aria-busy', true); ... ... @@ -134,7 +134,6 @@ 134 134 window.history.replaceState && window.history.replaceState(state, document.title); 135 135 // Make sure the browser address bar reflects the new state (and thus the new state can be bookmarked). 136 136 window.history.pushState && window.history.pushState(state, document.title, viewURL); 137 - document.querySelector(changeTargetSelector)?.focus(); 138 138 }); 139 139 }; 140 140 ... ... @@ -141,12 +141,12 @@ 141 141 var reloadSearchUI = function(event) { 142 142 event.preventDefault(); 143 143 var anchor = $(event.target).closest('a'); 144 - anchor.length && anchor.first().trigger('xwiki:search:update', anchor.attr('href'));134 + anchor.length && $(document).trigger('xwiki:search:update', anchor.attr('href')); 145 145 }; 146 146 147 147 // Others (e.g. a custom facet) can trigger a search UI update by firing this event. 148 148 $(document).on('xwiki:search:update', function(event, viewURL) { 149 - pushSearchUIState(viewURL , `[data-facetvalue='${CSS.escape(event.target.dataset.facetvalue)}']`);139 + pushSearchUIState(viewURL); 150 150 }); 151 151 152 152 $(window).on('popstate', function(event) { ... ... @@ -186,41 +186,10 @@ 186 186 }); 187 187 188 188 var enhanceSearchUI = function() { 189 - // Enhance search options 190 - document.querySelectorAll('input.options-item').forEach(function (option){ 191 - option.addEventListener('change', function() { 192 - let queryFieldName = this.getAttribute('data-query-name'); 193 - let queryField = document.querySelector('input[name="' + queryFieldName + '"]'); 194 - queryField.value = this.checked ? 'true' : 'false'; 195 - // We want to build the URL the same way it's done in the velocimacro #extendQueryString 196 - // We retrieve the search parameters of the latest request 197 - let params = new URLSearchParams(window.location.search); 198 - let formParams = new URLSearchParams(new FormData(this.form)); 199 - // We replace the existing parameters with their value from the form 200 - for (let param of formParams.keys()) { 201 - if (params.has(param)) params.delete(param); 202 - for (let paramValue of formParams.getAll(param)) { 203 - params.append(param,paramValue); 204 - } 205 - } 206 - pushSearchUIState(window.location.pathname + '?' + params.toString(), 207 - 'input[data-query-name="' + queryFieldName + '"]'); 208 - }); 209 - }); 210 - // Enhance search result sorting 211 - document.querySelectorAll('.search-results-sort select#sort-by-input, ' + 212 - '.search-results-sort input#sort-order-input').forEach(function (sortInput){ 213 - sortInput.addEventListener('change', function() { 214 - let baseURL = removeQueryString(this.form.getAttribute('action')); 215 - pushSearchUIState(baseURL + "?" + 216 - new URLSearchParams(new FormData(this.form)).toString(), 217 - 'input[data-query-name="' + this.getAttribute('name') + '"]'); 218 - }); 219 - }); 220 - 221 221 $('.search-result-highlightAll').each(enhanceSearchResultHighlights); 222 222 $('.search-facets').each(enhanceSearchFacets); 223 223 $([ 182 + '.search-results-sort a.sort-item', 224 224 '.search-options a.options-item', 225 225 '.pagination a', 226 226 '.controlPagination a',
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -1,7 +1,7 @@ 1 1 #template('colorThemeInit.vm') 2 2 3 3 /* Hide the 'Created by', 'Modified by' and 'Tags' document sections. */ 4 -.xdocLastModification, #xdocFooter { 4 +.xdocLastModification, .skin-colibri #document-info, #xdocFooter { 5 5 display: none; 6 6 } 7 7 #document-title > h1 { ... ... @@ -9,99 +9,86 @@ 9 9 margin-bottom: 0; 10 10 } 11 11 12 -/** 13 - * Layout for the search bar 14 - */ 15 -.search-bar { 16 - margin: .5em 0; 17 -} 18 - 19 -@media (min-width: 768px) { 20 - .search-bar { 21 - max-width: 50%; 22 - } 23 -} 24 - 25 25 /** 26 - * Layout for searchcontrols (sort + options)13 + * Search form 27 27 */ 28 28 29 -.search-results-controls { 30 - display: flex; 31 - flex-wrap: wrap; 32 - gap: 1em; 33 - 34 - & label { 35 - /* Reset the styles of the labels. */ 36 - margin: 0; 37 - font-weight: unset; 38 - } 16 +.skin-colibri .search-form { 17 + /* There is no space after the title in Colibri. */ 18 + margin-top: 1.5em; 39 39 } 40 40 41 -.search-results-sort, 42 -.search-options, .search-options > ul, .search-options > ul > li, 43 -.search-options > ul > li > label { 44 - display: flex; 45 - gap: .4em; 46 - align-items: center; 21 +.skin-colibri .search-form input[type="search"] { 22 + /* Colibri doesn't have the grid system. */ 23 + width: 50%; 47 47 } 48 48 49 49 /** 50 50 * Sort 51 51 */ 52 -/* This select should be especially lightweight on the UI. We're removing the default border and shadow. */ 53 -#sort-by-input { 54 - cursor: pointer; 55 55 56 - &:hover, &:focus { 57 - cursor: pointer; 58 - } 59 -} 60 - 61 -/* This checkbox input should be styled as a switch between ascending and descending states. */ 62 -.search-results-sort #sort-order-input { 63 - /* Hide the default checkbox. We rely on the style of the icon in its label to make it work. */ 64 - appearance: none; 30 +ul.search-results-sort { 31 + color: $theme.textSecondaryColor; 32 + font-size: .9em; 33 + padding: 5px 0 2px 0; 65 65 margin: 0; 66 66 } 67 - 68 -#sort-by-input, .search-results-sort label:has(>#sort-order-input) { 69 - /* We want most of the styles from "form-control", but not the shadow that comes from bootstrap. */ 70 - box-shadow: none; 71 - & :hover,& :focus,& :focus-within { 72 - border-color: var(--input-border-focus); 73 - } 36 +.search-results-sort li { 37 + display: inline; 38 + list-style-type: none; 39 + padding-left: 1.5em; 74 74 } 75 - 76 -/* Flip the second icon so that it's the arrow going up and down. */ 77 -.search-results-sort label #sort-order-input + * + * { 78 - transform: scaleY(-1); 41 +.search-results-sort li:first-of-type { 42 + padding: 0; 79 79 } 80 - 81 -/* When the box is checked, we want to hide the first icon. 82 -When the box is not checked, we want to hide the second icon. */ 83 -.search-results-sort label #sort-order-input:checked + *, 84 -.search-results-sort label #sort-order-input:not(:checked) + * + * { 85 - display: none; 44 +a.sort-item { 45 + color: inherit; 46 + text-decoration: none; 86 86 } 48 +a.sort-item:hover { 49 + color: $theme.linkColor; 50 + text-decoration: underline; 51 +} 52 +a.sort-item.active, a.sort-item.active:hover { 53 + font-weight: bold; 54 + color: $theme.textColor; 55 + text-decoration: none; 56 +} 57 +.sort-item-order { 58 + margin-left: .3em; 59 +} 87 87 88 88 /** 89 89 * Options 90 90 */ 91 91 92 -.search-options ul { 65 +ul.search-options { 66 + color: $theme.textSecondaryColor; 67 + font-size: .9em; 68 + padding: 5px 0 2px 0; 93 93 margin: 0; 70 +} 71 +.search-options li { 72 + display: inline; 73 + list-style-type: none; 74 + padding-left: 1.5em; 75 +} 76 +.search-options li:first-of-type { 94 94 padding: 0; 95 - 96 - & input[type="checkbox"] { 97 - position: unset; 98 - margin: 0; 99 - } 100 - 101 - & label { 102 - margin-right: 1em; 103 - } 104 104 } 79 +a.options-item { 80 + color: inherit; 81 + text-decoration: none; 82 +} 83 +a.options-item:hover { 84 + color: $theme.linkColor; 85 + text-decoration: underline; 86 +} 87 +a.options-item.active, a.options-item.active:hover{ 88 + font-weight: bold; 89 + color: $theme.textColor; 90 + text-decoration: none; 91 +} 105 105 106 106 /** 107 107 * Search Results ... ... @@ -111,6 +111,12 @@ 111 111 margin-top: 1em; 112 112 } 113 113 101 +/* Colibri skin doesn't have the grid system. */ 102 +.skin-colibri .search-results-left { 103 + margin: 0.5em 20em 0.5em 0; 104 + padding: 0.5em 0.5em 0.5em 0; 105 +} 106 + 114 114 .search-results { 115 115 padding: .3em 0 .8em 0; 116 116 } ... ... @@ -174,8 +174,6 @@ 174 174 175 175 dl.search-result-highlights > dt { 176 176 margin-top: .3em; 177 - color: var(--text-muted); 178 - font-weight: var(--font-weight-semibold); 179 179 } 180 180 181 181 blockquote.search-result-highlight { ... ... @@ -196,6 +196,11 @@ 196 196 font-weight: bold; 197 197 } 198 198 190 +dl.search-result-highlights > dt { 191 + color: $theme.textSecondaryColor; 192 + font-weight: normal; 193 +} 194 + 199 199 dl.search-result-highlights.preview dt, 200 200 dl.search-result-highlights.preview dd > * { 201 201 display: none; ... ... @@ -202,10 +202,17 @@ 202 202 } 203 203 204 204 dl.search-result-highlights.preview dt:first-of-type, 205 -dl.search-result-highlights.preview dd:first-of-type blockquote:first-of-type { 201 +dl.search-result-highlights.preview dd:first-of-type blockquote:first-of-type, 202 +/* Workaround for IE8 which doesn't support :first-of-type CSS selector. */ 203 +dl.search-result-highlights.preview dt.first, 204 +dl.search-result-highlights.preview dd.first blockquote.first { 206 206 display: block; 207 207 } 208 208 208 +a.search-result-highlightAll:after { 209 + content: ' \bb'; 210 +} 211 + 209 209 .search-result-debug { 210 210 white-space: pre; 211 211 } ... ... @@ -214,23 +214,40 @@ 214 214 * Facets 215 215 */ 216 216 217 -.search-facets-header{ 218 - border-bottom: 1px solid var(--xwiki-border-color); 220 +.search-facets { 221 + background-color: $theme.backgroundSecondaryColor; 222 + box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); 223 + /* Leave space for the bottom shadow. */ 224 + margin-bottom: 1em; 225 + border-radius: 7px; 219 219 } 227 +/* Colibri skin doesn't have the grid system. */ 228 +.skin-colibri .search-facets { 229 + float: right; 230 + max-width: 19.5em; 231 + width: 19.5em; 232 +} 220 220 221 -.search-facets-header strong { 222 - font-size: 1.25em; 234 +.search-facets-header, 235 +.search-facets-actions, 236 +.search-facet { 237 + border-bottom: 1px solid $theme.borderColor; 238 + border-top: 1px solid $theme.pageContentBackgroundColor; 239 + position: relative; 223 223 } 224 224 225 225 .search-facets-header, 226 226 .search-facets-actions { 227 - padding: .5em 0;244 + padding: 0.5em 1em; 228 228 } 229 - 230 230 .search-facet { 231 - padding: . 2em0;247 + padding: 0.5em .8em; 232 232 } 233 233 250 +.search-facets-header { 251 + border-top: none; 252 +} 253 + 234 234 .search-facets-header > p, 235 235 .search-facets-actions > p { 236 236 /* The wiki syntax generates paragraphs which have bottom margin. */ ... ... @@ -241,6 +241,16 @@ 241 241 font-size: .8em; 242 242 } 243 243 264 +.search-facets-actions a { 265 + color: $theme.textSecondaryColor; 266 + text-decoration: none; 267 +} 268 + 269 +.search-facets-actions a:hover { 270 + color: $theme.linkColor; 271 + text-decoration: underline; 272 +} 273 + 244 244 .search-facets-action-collapseAll, 245 245 .search-facets-action-expandAll { 246 246 float: right; ... ... @@ -252,37 +252,35 @@ 252 252 margin: 0; 253 253 } 254 254 255 -.search-facet-header, .search-facet-body { 256 - padding-left: .5em; 257 - border: 1px solid var(--xwiki-border-color); 258 - border-radius: var(--border-radius-small); 285 +.search-facet:last-of-type { 286 + border-bottom: none; 259 259 } 260 260 261 261 .search-facet-header { 262 - background-color: var(--xwiki-background-secondary-color); 263 -} 264 - 265 -.search-facet-header label { 266 266 color: $theme.titleColor; 267 267 cursor: pointer; 292 + line-height: 1.4em; 293 + margin: 0 .2em; 268 268 display: flex; 269 269 justify-content: space-between; 270 - align-items:center;296 + position: relative; 271 271 } 272 272 273 -.search-facet- body {274 - o pacity:0;275 - visibility: hidden; /* This makes sure the element is removed from the accessibility tree. */299 +.search-facet:last-of-type .search-facet-header:after { 300 + border: medium none; 301 +} 276 276 277 - position: absolute; 278 - transform: translateY(-10px); /* Start the animation slightly above */ 279 - padding-top: .5em; 280 - 281 - border-top-width: 0; 282 - border-top-left-radius: 0; 283 - border-top-right-radius: 0; 303 +.search-facet.expanded:last-of-type .search-facet-header:after { 304 + border-bottom: 1px dotted $theme.pageContentBackgroundColor; 305 + border-top: 1px dotted $theme.borderColor; 284 284 } 285 285 308 +.search-facet-body { 309 + overflow: hidden; /* required for effect */ 310 + display: none; 311 + margin-top: .5em; 312 +} 313 + 286 286 .search-facet-body ul, 287 287 .search-facet-body ol { 288 288 font-size: .9em; ... ... @@ -291,55 +291,37 @@ 291 291 .search-facet-body li { 292 292 display: flex; 293 293 flex-wrap: wrap; 294 - padding: . 3em .5em;322 + padding: .1em .2em; 295 295 } 296 296 297 -.search-facet .search-facet-header .facet-toggle, button.facet-value-toggle {325 +.search-facet .search-facet-header .facet-toggler, button.facet-value-toggler { 298 298 background: transparent; 299 299 transition: background-color .2s ease-in-out; 300 300 } 301 301 302 -.search-facet .search-facet-header .facet-toggle:active, button.facet-value-toggle:active { 330 +.search-facet .search-facet-header .facet-toggler:active, button.facet-value-toggler:active { 303 303 box-shadow: unset; 304 304 } 305 305 306 -.search-facet .search-facet-header .facet-toggle > span, button.facet-value-toggle > span, 307 -.search-facet .search-facet-header .facet-toggle > img, button.facet-value-toggle > img { 334 +.search-facet .search-facet-header .facet-toggler > span, button.facet-value-toggler > span, 335 +.search-facet .search-facet-header .facet-toggler > img, button.facet-value-toggler > img { 308 308 transform: rotate(90deg); 309 309 } 310 310 311 -.search-facet.expanded .search-facet-header .facet-toggle > span, .expanded > button.facet-value-toggle > span, 312 -.search-facet.expanded .search-facet-header .facet-toggle > img, .expanded > button.facet-value-toggle > img { 339 +.search-facet.expanded .search-facet-header .facet-toggler > span, .expanded > button.facet-value-toggler > span, 340 +.search-facet.expanded .search-facet-header .facet-toggler > img, .expanded > button.facet-value-toggler > img { 313 313 transform: rotate(0deg); 314 314 } 315 315 316 -@media (prefers-reduced-motion : no-preference) {317 - .search-facet .search-facet-header .facet-toggle > span, button.facet-value-toggle > span, 318 - .search-facet .search-facet-header .facet-toggle > img, button.facet-value-toggle > img { 344 +@media not (prefers-reduced-motion) { 345 + .search-facet .search-facet-header .facet-toggler > span, button.facet-value-toggler > span, 346 + .search-facet .search-facet-header .facet-toggler > img, button.facet-value-toggler > img { 319 319 transition: transform 0.2s ease; 320 320 } 321 - 322 - .search-facet-body { 323 - transition: opacity 0.3s ease, transform 0.3s ease; 324 - } 325 325 } 326 326 327 -.search-facet.expanded { 328 - & .search-facet-header { 329 - border-bottom-width: 0; 330 - border-bottom-left-radius: 0; 331 - border-bottom-right-radius: 0; 332 - 333 - & label { 334 - font-weight: var(--font-weight-semibold); 335 - } 336 - } 337 - & .search-facet-body { 338 - opacity: 1; 339 - position: unset; /* This element should be positioned normally when shown. */ 340 - visibility: visible; 341 - transform: translateY(0); 342 - } 351 +.search-facet.expanded .search-facet-body { 352 + display: block; 343 343 } 344 344 345 345 .search-facet-body ul, .search-facet-body ul.users { ... ... @@ -350,6 +350,10 @@ 350 350 margin: .5em 0; 351 351 } 352 352 363 +.search-facet-body li:hover { 364 + background-color: $theme.highlightColor; 365 +} 366 + 353 353 .search-facet-body input[type="checkbox"] { 354 354 margin: .2em 0; 355 355 } ... ... @@ -374,8 +374,7 @@ 374 374 } 375 375 376 376 .search-facet-body .itemName, 377 -.search-facet-body .itemNameempty, 378 -.search-facet-body .facet-value-toggle, 391 +.search-facet-body .facet-value-toggler, 379 379 .search-facet-body .more { 380 380 /* Remove link styling */ 381 381 color: $theme.textColor; ... ... @@ -393,11 +393,8 @@ 393 393 } 394 394 395 395 .search-facet-body .itemCount { 396 - padding: .1em .5em;409 + padding: .1em 0; 397 397 margin-left: auto; 398 - background-color: var(--nav-link-hover-bg); 399 - /* We want those item count blocks to be pill shaped. */ 400 - border-radius: 1em / 50%; 401 401 } 402 402 403 403 @media (max-width: 768px) { ... ... @@ -417,6 +417,17 @@ 417 417 } 418 418 419 419 /** 430 + * Fix the breadcrumb in Colibri skin. 431 + */ 432 +.skin-colibri .breadcrumb > li { 433 + display: inline; 434 +} 435 +.skin-colibri .breadcrumb > li + li:before { 436 + color: $theme.textSecondaryColor; 437 + content: ' \00BB '; 438 +} 439 + 440 +/** 420 420 * Miscellaneous 421 421 */ 422 422 ... ... @@ -425,3 +425,13 @@ 425 425 padding-left: 0; 426 426 } 427 427 449 +.paginationFilter .resultsNo, 450 +.paginationFilter .controlPagination, 451 +.paginationFilter .pagination { 452 + line-height: 22px; 453 +} 454 + 455 +.iconRSS { 456 + background: url("$xwiki.getSkinFile('icons/silk/feed.png')") no-repeat scroll 0 0 transparent; 457 + padding-left: 20px; 458 +}
Community

Wir benutzen Slack, um miteinander zu kommunizieren. Melde Dich an und werde Teil unserer Maker-Community!
Frage? FAQ!
Du hast eine Frage, die sich nicht direkt im Wiki findet?
Natürlich kannst Du die Frage jederzeit gerne in der Slack Community stellen. Bevor Du das machst, schau doch bitte einmal auf unserer Homepage bei den Häufig gestellten Fragen vorbei. Wir versuchen diese Fragen stets aktuell zu halten, eventuell hilft Dir das ja schon weiter.
Offene Werkstatt
Ohne Anmeldung einfach vorbei kommen. Am besten bringst Du direkt den ausgefüllten Haftungsauschluss mit.
Jeden Donnerstag ab 19 Uhr
Während der offenen Werkstatt kannst Du einfach vorbei kommen und an Deinem Projekt arbeiten. Bitte beachte aber, dass zur Verwendung der Maschinen eine Einweisung erforderlich ist, die Du gegebenfalls vorher absolvieren musst. Wenn ein Mitglied mit entsprechender Einweisung vor Ort ist und Zeit hat, helfen wir natürlich gerne aus. Dies können wir aber nicht garantieren, da Rundgänge Priorität haben.
Sprich Dich idealerweise schon vor der offenen Werkstatt mit einem Mitglied in unserem Slack ab. So kannst Du sicherstellen, dass Du auf jeden Fall arbeiten kannst.
Übrigens: Du kannst Dich mit einem Mitglied gerne auch außerhalb der offenen Werkstattzeiten zum Arbeiten verabreden!
Führungen und Rundgänge
Im Rahmen der offenen Werkstatt bieten wir euch auch gerne einen Rundgang durch unsere Werkstatt. Hier könnt ihr den Verein und unser Konzept kennenlernen sowie die Maschinen und Möglichkeiten der Werkstatt gezeigt bekommen.
Jeden Donnerstag wird eine Führung angeboten:
- Um 19:15 Uhr (bitte um 19:00 Uhr da sein)
Der Rundgang dauert ca. 45 Minuten und ihr habt natürlich auch die Möglichkeit, eure Fragen loszuwerden.
Bitte beachtet folgendes: Die Werkstatt beinhaltet gefährliche Maschinen. Bringt daher bitte nach Möglichkeit den ausgefüllten und unterschrieben Haftungsauschluss schon mit. Dieser kann aber auch vor Ort ausgefüllt werden, das verzögert allerdings die Abläufe.