Merge pull request #916 from dalf/pref_infinite_scroll2
Convert the infinite_scroll plugin as a preference (second version)
This commit is contained in:
		
						commit
						8230603f48
					
				| @ -1,9 +0,0 @@ | |||||||
| from flask_babel import gettext |  | ||||||
| 
 |  | ||||||
| name = gettext('Infinite scroll') |  | ||||||
| description = gettext('Automatically load next page when scrolling to bottom of current page') |  | ||||||
| default_on = False |  | ||||||
| preference_section = 'ui' |  | ||||||
| 
 |  | ||||||
| js_dependencies = ('plugins/js/infinite_scroll.js',) |  | ||||||
| css_dependencies = ('plugins/css/infinite_scroll.css',) |  | ||||||
| @ -394,6 +394,17 @@ class Preferences: | |||||||
|                     'False': False |                     'False': False | ||||||
|                 } |                 } | ||||||
|             ), |             ), | ||||||
|  |             'infinite_scroll': MapSetting( | ||||||
|  |                 settings['ui']['infinite_scroll'], | ||||||
|  |                 locked=is_locked('infinite_scroll'), | ||||||
|  |                 map={ | ||||||
|  |                     '': settings['ui']['infinite_scroll'], | ||||||
|  |                     '0': False, | ||||||
|  |                     '1': True, | ||||||
|  |                     'True': True, | ||||||
|  |                     'False': False | ||||||
|  |                 } | ||||||
|  |             ), | ||||||
|             # fmt: on |             # fmt: on | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -169,7 +169,6 @@ outgoing: | |||||||
| #   - 'Ahmia blacklist'  # activation depends on outgoing.using_tor_proxy | #   - 'Ahmia blacklist'  # activation depends on outgoing.using_tor_proxy | ||||||
| #   # these plugins are disabled if nothing is configured .. | #   # these plugins are disabled if nothing is configured .. | ||||||
| #   - 'Hostname replace'  # see hostname_replace configuration below | #   - 'Hostname replace'  # see hostname_replace configuration below | ||||||
| #   - 'Infinite scroll' |  | ||||||
| #   - 'Open Access DOI rewrite' | #   - 'Open Access DOI rewrite' | ||||||
| #   - 'Vim-like hotkeys' | #   - 'Vim-like hotkeys' | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -186,6 +186,7 @@ SCHEMA = { | |||||||
|         'results_on_new_tab': SettingsValue(bool, False), |         'results_on_new_tab': SettingsValue(bool, False), | ||||||
|         'advanced_search': SettingsValue(bool, False), |         'advanced_search': SettingsValue(bool, False), | ||||||
|         'query_in_title': SettingsValue(bool, False), |         'query_in_title': SettingsValue(bool, False), | ||||||
|  |         'infinite_scroll': SettingsValue(bool, False), | ||||||
|     }, |     }, | ||||||
|     'preferences': { |     'preferences': { | ||||||
|         'lock': SettingsValue(list, []), |         'lock': SettingsValue(list, []), | ||||||
|  | |||||||
| @ -1,40 +0,0 @@ | |||||||
| function hasScrollbar() { |  | ||||||
|     var root = document.compatMode=='BackCompat'? document.body : document.documentElement; |  | ||||||
|     return root.scrollHeight>root.clientHeight; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function loadNextPage() { |  | ||||||
|     var formData = $('#pagination form:last').serialize(); |  | ||||||
|     if (formData) { |  | ||||||
|         $('#pagination').html('<div class="loading-spinner"></div>'); |  | ||||||
|         $.ajax({ |  | ||||||
|             type: "POST", |  | ||||||
|             url: $('#search_form').prop('action'), |  | ||||||
|             data: formData, |  | ||||||
|             dataType: 'html', |  | ||||||
|             success: function(data) { |  | ||||||
|                 var body = $(data); |  | ||||||
|                 $('#pagination').remove(); |  | ||||||
|                 $('#main_results').append('<hr/>'); |  | ||||||
|                 $('#main_results').append(body.find('.result')); |  | ||||||
|                 $('#main_results').append(body.find('#pagination')); |  | ||||||
|                 if(!hasScrollbar()) { |  | ||||||
|                     loadNextPage(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| $(document).ready(function() { |  | ||||||
|     var win = $(window); |  | ||||||
|     if(!hasScrollbar()) { |  | ||||||
|         loadNextPage(); |  | ||||||
|     } |  | ||||||
|     win.scroll(function() { |  | ||||||
|         $("#pagination button").css("visibility", "hidden"); |  | ||||||
|         if ($(document).height() - win.height() - win.scrollTop() < 150) { |  | ||||||
|             loadNextPage(); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| }); |  | ||||||
| @ -29,7 +29,8 @@ | |||||||
|     this.verticalMargin = verticalMargin; |     this.verticalMargin = verticalMargin; | ||||||
|     this.horizontalMargin = horizontalMargin; |     this.horizontalMargin = horizontalMargin; | ||||||
|     this.maxHeight = maxHeight; |     this.maxHeight = maxHeight; | ||||||
|     this.isAlignDone = true; |     this.trottleCallToAlign = null; | ||||||
|  |     this.alignAfterThrotteling = false; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -72,12 +73,12 @@ | |||||||
|         // not loaded image : make it square as _getHeigth said it
 |         // not loaded image : make it square as _getHeigth said it
 | ||||||
|         imgWidth = height; |         imgWidth = height; | ||||||
|       } |       } | ||||||
|       img.style.width = imgWidth + 'px'; |       img.setAttribute('width', Math.round(imgWidth)); | ||||||
|       img.style.height = height + 'px'; |       img.setAttribute('height', Math.round(height)); | ||||||
|       img.style.marginLeft = this.horizontalMargin + 'px'; |       img.style.marginLeft = Math.round(this.horizontalMargin) + 'px'; | ||||||
|       img.style.marginTop = this.horizontalMargin + 'px'; |       img.style.marginTop = Math.round(this.horizontalMargin) + 'px'; | ||||||
|       img.style.marginRight = this.verticalMargin - 7 + 'px'; // -4 is the negative margin of the inline element
 |       img.style.marginRight = Math.round(this.verticalMargin - 7) + 'px'; // -4 is the negative margin of the inline element
 | ||||||
|       img.style.marginBottom = this.verticalMargin - 7 + 'px'; |       img.style.marginBottom = Math.round(this.verticalMargin - 7) + 'px'; | ||||||
|       resultNode = img.parentNode.parentNode; |       resultNode = img.parentNode.parentNode; | ||||||
|       if (!resultNode.classList.contains('js')) { |       if (!resultNode.classList.contains('js')) { | ||||||
|         resultNode.classList.add('js'); |         resultNode.classList.add('js'); | ||||||
| @ -112,6 +113,23 @@ | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   ImageLayout.prototype.throttleAlign = function () { | ||||||
|  |     var obj = this; | ||||||
|  |     if (obj.trottleCallToAlign) { | ||||||
|  |       obj.alignAfterThrotteling = true; | ||||||
|  |     } else { | ||||||
|  |       obj.alignAfterThrotteling = false; | ||||||
|  |       obj.align(); | ||||||
|  |       obj.trottleCallToAlign = setTimeout(function () { | ||||||
|  |         if (obj.alignAfterThrotteling) { | ||||||
|  |           obj.align(); | ||||||
|  |         } | ||||||
|  |         obj.alignAfterThrotteling = false; | ||||||
|  |         obj.trottleCallToAlign = null; | ||||||
|  |       }, 20); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   ImageLayout.prototype.align = function () { |   ImageLayout.prototype.align = function () { | ||||||
|     var i; |     var i; | ||||||
|     var results_selectorNode = d.querySelectorAll(this.results_selector); |     var results_selectorNode = d.querySelectorAll(this.results_selector); | ||||||
| @ -141,9 +159,9 @@ | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   ImageLayout.prototype.watch = function () { |   ImageLayout.prototype._monitorImages = function () { | ||||||
|     var i, img; |     var i, img; | ||||||
|     var obj = this; |     var objthrottleAlign = this.throttleAlign.bind(this); | ||||||
|     var results_nodes = d.querySelectorAll(this.results_selector); |     var results_nodes = d.querySelectorAll(this.results_selector); | ||||||
|     var results_length = results_nodes.length; |     var results_length = results_nodes.length; | ||||||
| 
 | 
 | ||||||
| @ -152,34 +170,53 @@ | |||||||
|       event.originalTarget.src = w.searxng.static_path + w.searxng.theme.img_load_error; |       event.originalTarget.src = w.searxng.static_path + w.searxng.theme.img_load_error; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     function throttleAlign () { |  | ||||||
|       if (obj.isAlignDone) { |  | ||||||
|         obj.isAlignDone = false; |  | ||||||
|         setTimeout(function () { |  | ||||||
|           obj.align(); |  | ||||||
|           obj.isAlignDone = true; |  | ||||||
|         }, 100); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
 |  | ||||||
|     w.addEventListener('pageshow', throttleAlign); |  | ||||||
|     // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/load_event
 |  | ||||||
|     w.addEventListener('load', throttleAlign); |  | ||||||
|     // https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event
 |  | ||||||
|     w.addEventListener('resize', throttleAlign); |  | ||||||
| 
 |  | ||||||
|     for (i = 0; i < results_length; i++) { |     for (i = 0; i < results_length; i++) { | ||||||
|       img = results_nodes[i].querySelector(this.img_selector); |       img = results_nodes[i].querySelector(this.img_selector); | ||||||
|       if (img !== null && img !== undefined) { |       if (img !== null && img !== undefined && !img.classList.contains('aligned')) { | ||||||
|         img.addEventListener('load', throttleAlign); |         img.addEventListener('load', objthrottleAlign); | ||||||
|         // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror
 |         // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror
 | ||||||
|         img.addEventListener('error', throttleAlign); |         img.addEventListener('error', objthrottleAlign); | ||||||
|  |         img.addEventListener('timeout', objthrottleAlign); | ||||||
|         if (w.searxng.theme.img_load_error) { |         if (w.searxng.theme.img_load_error) { | ||||||
|           img.addEventListener('error', img_load_error, {once: true}); |           img.addEventListener('error', img_load_error, {once: true}); | ||||||
|         } |         } | ||||||
|  |         img.classList.add('aligned'); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ImageLayout.prototype.watch = function () { | ||||||
|  |     var objthrottleAlign = this.throttleAlign.bind(this); | ||||||
|  | 
 | ||||||
|  |     // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
 | ||||||
|  |     w.addEventListener('pageshow', objthrottleAlign); | ||||||
|  |     // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/load_event
 | ||||||
|  |     w.addEventListener('load', objthrottleAlign); | ||||||
|  |     // https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event
 | ||||||
|  |     w.addEventListener('resize', objthrottleAlign); | ||||||
|  | 
 | ||||||
|  |     this._monitorImages(); | ||||||
|  | 
 | ||||||
|  |     var obj = this; | ||||||
|  | 
 | ||||||
|  |     let observer = new MutationObserver(entries => { | ||||||
|  |       let newElement = false; | ||||||
|  |       for (let i = 0; i < entries.length; i++) { | ||||||
|  |         if (entries[i].addedNodes.length > 0 && entries[i].addedNodes[0].classList.contains('result')) { | ||||||
|  |           newElement = true; | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       if (newElement) { | ||||||
|  |         obj._monitorImages(); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     observer.observe(d.querySelector(this.container_selector), { | ||||||
|  |       childList: true, | ||||||
|  |       subtree: true, | ||||||
|  |       attributes: false, | ||||||
|  |       characterData: false, | ||||||
|  |     }) | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   w.searxng.ImageLayout = ImageLayout; |   w.searxng.ImageLayout = ImageLayout; | ||||||
|  | |||||||
| @ -382,6 +382,29 @@ | |||||||
| .col-stat { | .col-stat { | ||||||
|   width: 10rem; |   width: 10rem; | ||||||
| } | } | ||||||
|  | @keyframes rotate-forever { | ||||||
|  |   0% { | ||||||
|  |     transform: rotate(0deg); | ||||||
|  |   } | ||||||
|  |   100% { | ||||||
|  |     transform: rotate(360deg); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .loading-spinner { | ||||||
|  |   animation-duration: 0.75s; | ||||||
|  |   animation-iteration-count: infinite; | ||||||
|  |   animation-name: rotate-forever; | ||||||
|  |   animation-timing-function: linear; | ||||||
|  |   height: 30px; | ||||||
|  |   width: 30px; | ||||||
|  |   border: 8px solid #666; | ||||||
|  |   border-right-color: transparent; | ||||||
|  |   border-radius: 50% !important; | ||||||
|  |   margin: 0 auto; | ||||||
|  | } | ||||||
|  | html.infinite_scroll #pagination button { | ||||||
|  |   visibility: hidden; | ||||||
|  | } | ||||||
| /* | /* | ||||||
|    this file is generated automatically by searxng_extra/update/update_pygments.py |    this file is generated automatically by searxng_extra/update/update_pygments.py | ||||||
|    using pygments version 2.11.2 |    using pygments version 2.11.2 | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								searx/static/themes/oscar/css/logicodev-dark.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								searx/static/themes/oscar/css/logicodev-dark.min.css
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -382,6 +382,29 @@ | |||||||
| .col-stat { | .col-stat { | ||||||
|   width: 10rem; |   width: 10rem; | ||||||
| } | } | ||||||
|  | @keyframes rotate-forever { | ||||||
|  |   0% { | ||||||
|  |     transform: rotate(0deg); | ||||||
|  |   } | ||||||
|  |   100% { | ||||||
|  |     transform: rotate(360deg); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .loading-spinner { | ||||||
|  |   animation-duration: 0.75s; | ||||||
|  |   animation-iteration-count: infinite; | ||||||
|  |   animation-name: rotate-forever; | ||||||
|  |   animation-timing-function: linear; | ||||||
|  |   height: 30px; | ||||||
|  |   width: 30px; | ||||||
|  |   border: 8px solid #666; | ||||||
|  |   border-right-color: transparent; | ||||||
|  |   border-radius: 50% !important; | ||||||
|  |   margin: 0 auto; | ||||||
|  | } | ||||||
|  | html.infinite_scroll #pagination button { | ||||||
|  |   visibility: hidden; | ||||||
|  | } | ||||||
| /* | /* | ||||||
|    this file is generated automatically by searxng_extra/update/update_pygments.py |    this file is generated automatically by searxng_extra/update/update_pygments.py | ||||||
|    using pygments version 2.11.2 |    using pygments version 2.11.2 | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								searx/static/themes/oscar/css/logicodev.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								searx/static/themes/oscar/css/logicodev.min.css
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -382,6 +382,29 @@ | |||||||
| .col-stat { | .col-stat { | ||||||
|   width: 10rem; |   width: 10rem; | ||||||
| } | } | ||||||
|  | @keyframes rotate-forever { | ||||||
|  |   0% { | ||||||
|  |     transform: rotate(0deg); | ||||||
|  |   } | ||||||
|  |   100% { | ||||||
|  |     transform: rotate(360deg); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .loading-spinner { | ||||||
|  |   animation-duration: 0.75s; | ||||||
|  |   animation-iteration-count: infinite; | ||||||
|  |   animation-name: rotate-forever; | ||||||
|  |   animation-timing-function: linear; | ||||||
|  |   height: 30px; | ||||||
|  |   width: 30px; | ||||||
|  |   border: 8px solid #666; | ||||||
|  |   border-right-color: transparent; | ||||||
|  |   border-radius: 50% !important; | ||||||
|  |   margin: 0 auto; | ||||||
|  | } | ||||||
|  | html.infinite_scroll #pagination button { | ||||||
|  |   visibility: hidden; | ||||||
|  | } | ||||||
| /* | /* | ||||||
|    this file is generated automatically by searxng_extra/update/update_pygments.py |    this file is generated automatically by searxng_extra/update/update_pygments.py | ||||||
|    using pygments version 2.11.2 |    using pygments version 2.11.2 | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								searx/static/themes/oscar/css/pointhi.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								searx/static/themes/oscar/css/pointhi.min.css
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -78,7 +78,7 @@ module.exports = function(grunt) { | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     jshint: { |     jshint: { | ||||||
|       files: ['gruntfile.js', 'src/js/*.js', '../__common__/js/image_layout.js'], |       files: ['gruntfile.js', 'src/js/*.js'],  // files in __common__ are linted by es lint in simple theme
 | ||||||
|       options: { |       options: { | ||||||
|         reporterOutput: "", |         reporterOutput: "", | ||||||
|         esversion: 6, |         esversion: 6, | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ window.searxng = (function(d) { | |||||||
| 
 | 
 | ||||||
|     return { |     return { | ||||||
|         autocompleter: script.getAttribute('data-autocompleter') === 'true', |         autocompleter: script.getAttribute('data-autocompleter') === 'true', | ||||||
|  |         infinite_scroll: script.getAttribute('data-infinite-scroll') === 'true', | ||||||
|         method: script.getAttribute('data-method'), |         method: script.getAttribute('data-method'), | ||||||
|         translations: JSON.parse(script.getAttribute('data-translations')) |         translations: JSON.parse(script.getAttribute('data-translations')) | ||||||
|     }; |     }; | ||||||
| @ -189,6 +190,56 @@ $(document).ready(function(){ | |||||||
|  * SPDX-License-Identifier: AGPL-3.0-or-later |  * SPDX-License-Identifier: AGPL-3.0-or-later | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | $(document).ready(function() { | ||||||
|  |     function hasScrollbar() { | ||||||
|  |         var root = document.compatMode=='BackCompat'? document.body : document.documentElement; | ||||||
|  |         return root.scrollHeight>root.clientHeight; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function loadNextPage() { | ||||||
|  |         var formData = $('#pagination form:last').serialize(); | ||||||
|  |         if (formData) { | ||||||
|  |             $('#pagination').html('<div class="loading-spinner"></div>'); | ||||||
|  |             $.ajax({ | ||||||
|  |                 type: "POST", | ||||||
|  |                 url: $('#search_form').prop('action'), | ||||||
|  |                 data: formData, | ||||||
|  |                 dataType: 'html', | ||||||
|  |                 success: function(data) { | ||||||
|  |                     var body = $(data); | ||||||
|  |                     $('#pagination').remove(); | ||||||
|  |                     $('#main_results').append('<hr/>'); | ||||||
|  |                     $('#main_results').append(body.find('.result')); | ||||||
|  |                     $('#main_results').append(body.find('#pagination')); | ||||||
|  |                     if(!hasScrollbar()) { | ||||||
|  |                         loadNextPage(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (searxng.infinite_scroll) { | ||||||
|  |         var win = $(window); | ||||||
|  |         $("html").addClass('infinite_scroll'); | ||||||
|  |         if(!hasScrollbar()) { | ||||||
|  |             loadNextPage(); | ||||||
|  |         } | ||||||
|  |         win.on('scroll', function() { | ||||||
|  |             if ($(document).height() - win.height() - win.scrollTop() < 150) { | ||||||
|  |                 loadNextPage(); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | }); | ||||||
|  | ;/** | ||||||
|  |  * @license | ||||||
|  |  * (C) Copyright Contributors to the SearXNG project. | ||||||
|  |  * (C) Copyright Contributors to the searx project (2014 - 2021). | ||||||
|  |  * SPDX-License-Identifier: AGPL-3.0-or-later | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| window.addEventListener('load', function() { | window.addEventListener('load', function() { | ||||||
|     // Hide infobox toggle if shrunk size already fits all content.
 |     // Hide infobox toggle if shrunk size already fits all content.
 | ||||||
|     $('.infobox').each(function() { |     $('.infobox').each(function() { | ||||||
| @ -348,7 +399,8 @@ $(document).ready(function(){ | |||||||
|     this.verticalMargin = verticalMargin; |     this.verticalMargin = verticalMargin; | ||||||
|     this.horizontalMargin = horizontalMargin; |     this.horizontalMargin = horizontalMargin; | ||||||
|     this.maxHeight = maxHeight; |     this.maxHeight = maxHeight; | ||||||
|     this.isAlignDone = true; |     this.trottleCallToAlign = null; | ||||||
|  |     this.alignAfterThrotteling = false; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -391,12 +443,12 @@ $(document).ready(function(){ | |||||||
|         // not loaded image : make it square as _getHeigth said it
 |         // not loaded image : make it square as _getHeigth said it
 | ||||||
|         imgWidth = height; |         imgWidth = height; | ||||||
|       } |       } | ||||||
|       img.style.width = imgWidth + 'px'; |       img.setAttribute('width', Math.round(imgWidth)); | ||||||
|       img.style.height = height + 'px'; |       img.setAttribute('height', Math.round(height)); | ||||||
|       img.style.marginLeft = this.horizontalMargin + 'px'; |       img.style.marginLeft = Math.round(this.horizontalMargin) + 'px'; | ||||||
|       img.style.marginTop = this.horizontalMargin + 'px'; |       img.style.marginTop = Math.round(this.horizontalMargin) + 'px'; | ||||||
|       img.style.marginRight = this.verticalMargin - 7 + 'px'; // -4 is the negative margin of the inline element
 |       img.style.marginRight = Math.round(this.verticalMargin - 7) + 'px'; // -4 is the negative margin of the inline element
 | ||||||
|       img.style.marginBottom = this.verticalMargin - 7 + 'px'; |       img.style.marginBottom = Math.round(this.verticalMargin - 7) + 'px'; | ||||||
|       resultNode = img.parentNode.parentNode; |       resultNode = img.parentNode.parentNode; | ||||||
|       if (!resultNode.classList.contains('js')) { |       if (!resultNode.classList.contains('js')) { | ||||||
|         resultNode.classList.add('js'); |         resultNode.classList.add('js'); | ||||||
| @ -431,6 +483,23 @@ $(document).ready(function(){ | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   ImageLayout.prototype.throttleAlign = function () { | ||||||
|  |     var obj = this; | ||||||
|  |     if (obj.trottleCallToAlign) { | ||||||
|  |       obj.alignAfterThrotteling = true; | ||||||
|  |     } else { | ||||||
|  |       obj.alignAfterThrotteling = false; | ||||||
|  |       obj.align(); | ||||||
|  |       obj.trottleCallToAlign = setTimeout(function () { | ||||||
|  |         if (obj.alignAfterThrotteling) { | ||||||
|  |           obj.align(); | ||||||
|  |         } | ||||||
|  |         obj.alignAfterThrotteling = false; | ||||||
|  |         obj.trottleCallToAlign = null; | ||||||
|  |       }, 20); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   ImageLayout.prototype.align = function () { |   ImageLayout.prototype.align = function () { | ||||||
|     var i; |     var i; | ||||||
|     var results_selectorNode = d.querySelectorAll(this.results_selector); |     var results_selectorNode = d.querySelectorAll(this.results_selector); | ||||||
| @ -460,9 +529,9 @@ $(document).ready(function(){ | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   ImageLayout.prototype.watch = function () { |   ImageLayout.prototype._monitorImages = function () { | ||||||
|     var i, img; |     var i, img; | ||||||
|     var obj = this; |     var objthrottleAlign = this.throttleAlign.bind(this); | ||||||
|     var results_nodes = d.querySelectorAll(this.results_selector); |     var results_nodes = d.querySelectorAll(this.results_selector); | ||||||
|     var results_length = results_nodes.length; |     var results_length = results_nodes.length; | ||||||
| 
 | 
 | ||||||
| @ -471,34 +540,53 @@ $(document).ready(function(){ | |||||||
|       event.originalTarget.src = w.searxng.static_path + w.searxng.theme.img_load_error; |       event.originalTarget.src = w.searxng.static_path + w.searxng.theme.img_load_error; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     function throttleAlign () { |  | ||||||
|       if (obj.isAlignDone) { |  | ||||||
|         obj.isAlignDone = false; |  | ||||||
|         setTimeout(function () { |  | ||||||
|           obj.align(); |  | ||||||
|           obj.isAlignDone = true; |  | ||||||
|         }, 100); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
 |  | ||||||
|     w.addEventListener('pageshow', throttleAlign); |  | ||||||
|     // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/load_event
 |  | ||||||
|     w.addEventListener('load', throttleAlign); |  | ||||||
|     // https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event
 |  | ||||||
|     w.addEventListener('resize', throttleAlign); |  | ||||||
| 
 |  | ||||||
|     for (i = 0; i < results_length; i++) { |     for (i = 0; i < results_length; i++) { | ||||||
|       img = results_nodes[i].querySelector(this.img_selector); |       img = results_nodes[i].querySelector(this.img_selector); | ||||||
|       if (img !== null && img !== undefined) { |       if (img !== null && img !== undefined && !img.classList.contains('aligned')) { | ||||||
|         img.addEventListener('load', throttleAlign); |         img.addEventListener('load', objthrottleAlign); | ||||||
|         // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror
 |         // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror
 | ||||||
|         img.addEventListener('error', throttleAlign); |         img.addEventListener('error', objthrottleAlign); | ||||||
|  |         img.addEventListener('timeout', objthrottleAlign); | ||||||
|         if (w.searxng.theme.img_load_error) { |         if (w.searxng.theme.img_load_error) { | ||||||
|           img.addEventListener('error', img_load_error, {once: true}); |           img.addEventListener('error', img_load_error, {once: true}); | ||||||
|         } |         } | ||||||
|  |         img.classList.add('aligned'); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ImageLayout.prototype.watch = function () { | ||||||
|  |     var objthrottleAlign = this.throttleAlign.bind(this); | ||||||
|  | 
 | ||||||
|  |     // https://developer.mozilla.org/en-US/docs/Web/API/Window/pageshow_event
 | ||||||
|  |     w.addEventListener('pageshow', objthrottleAlign); | ||||||
|  |     // https://developer.mozilla.org/en-US/docs/Web/API/FileReader/load_event
 | ||||||
|  |     w.addEventListener('load', objthrottleAlign); | ||||||
|  |     // https://developer.mozilla.org/en-US/docs/Web/API/Window/resize_event
 | ||||||
|  |     w.addEventListener('resize', objthrottleAlign); | ||||||
|  | 
 | ||||||
|  |     this._monitorImages(); | ||||||
|  | 
 | ||||||
|  |     var obj = this; | ||||||
|  | 
 | ||||||
|  |     let observer = new MutationObserver(entries => { | ||||||
|  |       let newElement = false; | ||||||
|  |       for (let i = 0; i < entries.length; i++) { | ||||||
|  |         if (entries[i].addedNodes.length > 0 && entries[i].addedNodes[0].classList.contains('result')) { | ||||||
|  |           newElement = true; | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       if (newElement) { | ||||||
|  |         obj._monitorImages(); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     observer.observe(d.querySelector(this.container_selector), { | ||||||
|  |       childList: true, | ||||||
|  |       subtree: true, | ||||||
|  |       attributes: false, | ||||||
|  |       characterData: false, | ||||||
|  |     }) | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   w.searxng.ImageLayout = ImageLayout; |   w.searxng.ImageLayout = ImageLayout; | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								searx/static/themes/oscar/js/searxng.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								searx/static/themes/oscar/js/searxng.min.js
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -19,6 +19,7 @@ window.searxng = (function(d) { | |||||||
| 
 | 
 | ||||||
|     return { |     return { | ||||||
|         autocompleter: script.getAttribute('data-autocompleter') === 'true', |         autocompleter: script.getAttribute('data-autocompleter') === 'true', | ||||||
|  |         infinite_scroll: script.getAttribute('data-infinite-scroll') === 'true', | ||||||
|         method: script.getAttribute('data-method'), |         method: script.getAttribute('data-method'), | ||||||
|         translations: JSON.parse(script.getAttribute('data-translations')) |         translations: JSON.parse(script.getAttribute('data-translations')) | ||||||
|     }; |     }; | ||||||
|  | |||||||
							
								
								
									
										50
									
								
								searx/static/themes/oscar/src/js/infinite_scroll.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								searx/static/themes/oscar/src/js/infinite_scroll.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | |||||||
|  | /** | ||||||
|  |  * @license | ||||||
|  |  * (C) Copyright Contributors to the SearXNG project. | ||||||
|  |  * (C) Copyright Contributors to the searx project (2014 - 2021). | ||||||
|  |  * SPDX-License-Identifier: AGPL-3.0-or-later | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | $(document).ready(function() { | ||||||
|  |     function hasScrollbar() { | ||||||
|  |         var root = document.compatMode=='BackCompat'? document.body : document.documentElement; | ||||||
|  |         return root.scrollHeight>root.clientHeight; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function loadNextPage() { | ||||||
|  |         var formData = $('#pagination form:last').serialize(); | ||||||
|  |         if (formData) { | ||||||
|  |             $('#pagination').html('<div class="loading-spinner"></div>'); | ||||||
|  |             $.ajax({ | ||||||
|  |                 type: "POST", | ||||||
|  |                 url: $('#search_form').prop('action'), | ||||||
|  |                 data: formData, | ||||||
|  |                 dataType: 'html', | ||||||
|  |                 success: function(data) { | ||||||
|  |                     var body = $(data); | ||||||
|  |                     $('#pagination').remove(); | ||||||
|  |                     $('#main_results').append('<hr/>'); | ||||||
|  |                     $('#main_results').append(body.find('.result')); | ||||||
|  |                     $('#main_results').append(body.find('#pagination')); | ||||||
|  |                     if(!hasScrollbar()) { | ||||||
|  |                         loadNextPage(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (searxng.infinite_scroll) { | ||||||
|  |         var win = $(window); | ||||||
|  |         $("html").addClass('infinite_scroll'); | ||||||
|  |         if(!hasScrollbar()) { | ||||||
|  |             loadNextPage(); | ||||||
|  |         } | ||||||
|  |         win.on('scroll', function() { | ||||||
|  |             if ($(document).height() - win.height() - win.scrollTop() < 150) { | ||||||
|  |                 loadNextPage(); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | }); | ||||||
| @ -2,6 +2,7 @@ | |||||||
|     0%   { transform: rotate(0deg) } |     0%   { transform: rotate(0deg) } | ||||||
|     100% { transform: rotate(360deg) } |     100% { transform: rotate(360deg) } | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .loading-spinner { | .loading-spinner { | ||||||
|     animation-duration: 0.75s; |     animation-duration: 0.75s; | ||||||
|     animation-iteration-count: infinite; |     animation-iteration-count: infinite; | ||||||
| @ -14,6 +15,7 @@ | |||||||
|     border-radius: 50% !important; |     border-radius: 50% !important; | ||||||
|     margin: 0 auto; |     margin: 0 auto; | ||||||
| } | } | ||||||
| #pagination button { | 
 | ||||||
|  | html.infinite_scroll #pagination button { | ||||||
| 	visibility: hidden; | 	visibility: hidden; | ||||||
| } | } | ||||||
| @ -4,6 +4,7 @@ | |||||||
| @import "../../../../__common__/less/result_templates.less"; | @import "../../../../__common__/less/result_templates.less"; | ||||||
| @import "../../less/result_templates.less"; | @import "../../less/result_templates.less"; | ||||||
| @import "../../less/preferences.less"; | @import "../../less/preferences.less"; | ||||||
|  | @import "../infinite_scroll.less"; | ||||||
| @import "../../generated/pygments-logicodev.less"; | @import "../../generated/pygments-logicodev.less"; | ||||||
| 
 | 
 | ||||||
| @stacked-bar-chart: rgb(213, 216, 215, 1); | @stacked-bar-chart: rgb(213, 216, 215, 1); | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ | |||||||
| @import "../../../../__common__/less/result_templates.less"; | @import "../../../../__common__/less/result_templates.less"; | ||||||
| @import "../../less/result_templates.less"; | @import "../../less/result_templates.less"; | ||||||
| @import "../../less/preferences.less"; | @import "../../less/preferences.less"; | ||||||
|  | @import "../infinite_scroll.less"; | ||||||
| @import "../../generated/pygments-logicodev.less"; | @import "../../generated/pygments-logicodev.less"; | ||||||
| 
 | 
 | ||||||
| @import "navbar.less"; | @import "navbar.less"; | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ | |||||||
| @import "../../../../__common__/less/result_templates.less"; | @import "../../../../__common__/less/result_templates.less"; | ||||||
| @import "../../less/result_templates.less"; | @import "../../less/result_templates.less"; | ||||||
| @import "../../less/preferences.less"; | @import "../../less/preferences.less"; | ||||||
|  | @import "../infinite_scroll.less"; | ||||||
| @import "../../generated/pygments-pointhi.less"; | @import "../../generated/pygments-pointhi.less"; | ||||||
| 
 | 
 | ||||||
| @import "footer.less"; | @import "footer.less"; | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								searx/static/themes/simple/css/searxng-rtl.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								searx/static/themes/simple/css/searxng-rtl.min.css
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								searx/static/themes/simple/css/searxng.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								searx/static/themes/simple/css/searxng.min.css
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								searx/static/themes/simple/js/searxng.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								searx/static/themes/simple/js/searxng.min.js
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -59,17 +59,12 @@ window.searxng = (function (w, d) { | |||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   searxng.http = function (method, url) { |   searxng.http = function (method, url, data = null) { | ||||||
|     var req = new XMLHttpRequest(), |     return new Promise(function (resolve, reject) { | ||||||
|       resolve = function () {}, |  | ||||||
|       reject = function () {}, |  | ||||||
|       promise = { |  | ||||||
|         then: function (callback) { resolve = callback; return promise; }, |  | ||||||
|         catch: function (callback) { reject = callback; return promise; } |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       try { |       try { | ||||||
|  |         var req = new XMLHttpRequest(); | ||||||
|         req.open(method, url, true); |         req.open(method, url, true); | ||||||
|  |         req.timeout = 20000; | ||||||
| 
 | 
 | ||||||
|         // On load
 |         // On load
 | ||||||
|         req.onload = function () { |         req.onload = function () { | ||||||
| @ -89,13 +84,20 @@ window.searxng = (function (w, d) { | |||||||
|           reject(Error("Transaction is aborted")); |           reject(Error("Transaction is aborted")); | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|  |         req.ontimeout = function () { | ||||||
|  |           reject(Error("Timeout")); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         // Make the request
 |         // Make the request
 | ||||||
|  |         if (data) { | ||||||
|  |           req.send(data) | ||||||
|  |         } else { | ||||||
|           req.send(); |           req.send(); | ||||||
|  |         } | ||||||
|       } catch (ex) { |       } catch (ex) { | ||||||
|         reject(ex); |         reject(ex); | ||||||
|       } |       } | ||||||
| 
 |     }); | ||||||
|     return promise; |  | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   searxng.loadStyle = function (src) { |   searxng.loadStyle = function (src) { | ||||||
| @ -148,5 +150,16 @@ window.searxng = (function (w, d) { | |||||||
|     this.parentNode.classList.add('invisible'); |     this.parentNode.classList.add('invisible'); | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  |   function getEndpoint () { | ||||||
|  |     for (var className of d.getElementsByTagName('body')[0].classList.values()) { | ||||||
|  |       if (className.endsWith('_endpoint')) { | ||||||
|  |         return className.split('_')[0]; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return ''; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   searxng.endpoint = getEndpoint(); | ||||||
|  | 
 | ||||||
|   return searxng; |   return searxng; | ||||||
| })(window, document); | })(window, document); | ||||||
|  | |||||||
							
								
								
									
										88
									
								
								searx/static/themes/simple/src/js/main/infinite_scroll.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								searx/static/themes/simple/src/js/main/infinite_scroll.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | |||||||
|  | // SPDX-License-Identifier: AGPL-3.0-or-later
 | ||||||
|  | 
 | ||||||
|  | /* global searxng */ | ||||||
|  | 
 | ||||||
|  | searxng.ready(function () { | ||||||
|  |   'use strict'; | ||||||
|  | 
 | ||||||
|  |   searxng.infinite_scroll_supported = ( | ||||||
|  |     'IntersectionObserver' in window && | ||||||
|  |     'IntersectionObserverEntry' in window && | ||||||
|  |     'intersectionRatio' in window.IntersectionObserverEntry.prototype); | ||||||
|  | 
 | ||||||
|  |   if (searxng.endpoint !== 'results') { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!searxng.infinite_scroll_supported) { | ||||||
|  |     console.log('IntersectionObserver not supported'); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   let d = document; | ||||||
|  |   var onlyImages = d.getElementById('results').classList.contains('only_template_images'); | ||||||
|  | 
 | ||||||
|  |   function newLoadSpinner () { | ||||||
|  |     var loader = d.createElement('div'); | ||||||
|  |     loader.classList.add('loader'); | ||||||
|  |     return loader; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function replaceChildrenWith (element, children) { | ||||||
|  |     element.textContent = ''; | ||||||
|  |     children.forEach(child => element.appendChild(child)); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function loadNextPage (callback) { | ||||||
|  |     var form = d.querySelector('#pagination form.next_page'); | ||||||
|  |     if (!form) { | ||||||
|  |       return | ||||||
|  |     } | ||||||
|  |     replaceChildrenWith(d.querySelector('#pagination'), [ newLoadSpinner() ]); | ||||||
|  |     var formData = new FormData(form); | ||||||
|  |     searxng.http('POST', d.querySelector('#search').getAttribute('action'), formData).then( | ||||||
|  |       function (response) { | ||||||
|  |         var nextPageDoc = new DOMParser().parseFromString(response, 'text/html'); | ||||||
|  |         var articleList = nextPageDoc.querySelectorAll('#urls article'); | ||||||
|  |         var paginationElement = nextPageDoc.querySelector('#pagination'); | ||||||
|  |         d.querySelector('#pagination').remove(); | ||||||
|  |         if (articleList.length > 0 && !onlyImages) { | ||||||
|  |           // do not add <hr> element when there are only images
 | ||||||
|  |           d.querySelector('#urls').appendChild(d.createElement('hr')); | ||||||
|  |         } | ||||||
|  |         articleList.forEach(articleElement => { | ||||||
|  |           d.querySelector('#urls').appendChild(articleElement); | ||||||
|  |         }); | ||||||
|  |         if (paginationElement) { | ||||||
|  |           d.querySelector('#results').appendChild(paginationElement); | ||||||
|  |           callback(); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     ).catch( | ||||||
|  |       function (err) { | ||||||
|  |         console.log(err); | ||||||
|  |         var e = d.createElement('div'); | ||||||
|  |         e.textContent = searxng.translations.error_loading_next_page; | ||||||
|  |         e.classList.add('dialog-error'); | ||||||
|  |         e.setAttribute('role', 'alert'); | ||||||
|  |         replaceChildrenWith(d.querySelector('#pagination'), [ e ]); | ||||||
|  |       } | ||||||
|  |     ) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (searxng.infinite_scroll && searxng.infinite_scroll_supported) { | ||||||
|  |     const intersectionObserveOptions = { | ||||||
|  |       rootMargin: "20rem", | ||||||
|  |     }; | ||||||
|  |     const observedSelector = 'article.result:last-child'; | ||||||
|  |     const observer = new IntersectionObserver(entries => { | ||||||
|  |       const paginationEntry = entries[0]; | ||||||
|  |       if (paginationEntry.isIntersecting) { | ||||||
|  |         observer.unobserve(paginationEntry.target); | ||||||
|  |         loadNextPage(() => observer.observe(d.querySelector(observedSelector), intersectionObserveOptions)); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     observer.observe(d.querySelector(observedSelector), intersectionObserveOptions); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | }); | ||||||
| @ -2,6 +2,10 @@ | |||||||
| (function (w, d, searxng) { | (function (w, d, searxng) { | ||||||
|   'use strict'; |   'use strict'; | ||||||
| 
 | 
 | ||||||
|  |   if (searxng.endpoint !== 'preferences') { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   searxng.ready(function () { |   searxng.ready(function () { | ||||||
|     let engine_descriptions = null; |     let engine_descriptions = null; | ||||||
|     function load_engine_descriptions () { |     function load_engine_descriptions () { | ||||||
| @ -19,10 +23,8 @@ | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (d.querySelector('body[class="preferences_endpoint"]')) { |  | ||||||
|     for (const el of d.querySelectorAll('[data-engine-name]')) { |     for (const el of d.querySelectorAll('[data-engine-name]')) { | ||||||
|       searxng.on(el, 'mouseenter', load_engine_descriptions); |       searxng.on(el, 'mouseenter', load_engine_descriptions); | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|   }); |   }); | ||||||
| })(window, document, window.searxng); | })(window, document, window.searxng); | ||||||
|  | |||||||
| @ -2,6 +2,10 @@ | |||||||
| (function (w, d, searxng) { | (function (w, d, searxng) { | ||||||
|   'use strict'; |   'use strict'; | ||||||
| 
 | 
 | ||||||
|  |   if (searxng.endpoint !== 'results') { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   searxng.ready(function () { |   searxng.ready(function () { | ||||||
|     searxng.image_thumbnail_layout = new searxng.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 14, 6, 200); |     searxng.image_thumbnail_layout = new searxng.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 14, 6, 200); | ||||||
|     searxng.image_thumbnail_layout.watch(); |     searxng.image_thumbnail_layout.watch(); | ||||||
|  | |||||||
| @ -771,15 +771,19 @@ article[data-vim-selected].category-social { | |||||||
|   margin: 1rem @results-tablet-offset 0 @results-tablet-offset; |   margin: 1rem @results-tablet-offset 0 @results-tablet-offset; | ||||||
|   display: grid; |   display: grid; | ||||||
|   grid-template-columns: 100%; |   grid-template-columns: 100%; | ||||||
|   grid-template-rows: min-content min-content 1fr min-content min-content; |   grid-template-rows: min-content min-content min-content 1fr min-content; | ||||||
|   gap: 0; |   gap: 0; | ||||||
|   grid-template-areas: |   grid-template-areas: | ||||||
|     "corrections" |     "corrections" | ||||||
|     "urls" |  | ||||||
|     "answers" |     "answers" | ||||||
|     "sidebar" |     "sidebar" | ||||||
|  |     "urls" | ||||||
|     "pagination"; |     "pagination"; | ||||||
| 
 | 
 | ||||||
|  |   #sidebar { | ||||||
|  |     display: none; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   #urls { |   #urls { | ||||||
|     width: inherit; |     width: inherit; | ||||||
|     margin: 0; |     margin: 0; | ||||||
|  | |||||||
| @ -100,6 +100,7 @@ | |||||||
|     <script src="{{ url_for('static', filename='js/searxng.min.js') }}" |     <script src="{{ url_for('static', filename='js/searxng.min.js') }}" | ||||||
|             data-method="{{ method or 'POST' }}" |             data-method="{{ method or 'POST' }}" | ||||||
|             data-autocompleter="{% if autocomplete %}true{% else %}false{% endif %}" |             data-autocompleter="{% if autocomplete %}true{% else %}false{% endif %}" | ||||||
|  |             data-infinite-scroll="{% if infinite_scroll %}true{% else %}false{% endif %}" | ||||||
|             data-translations="{{ translations }}"></script> |             data-translations="{{ translations }}"></script> | ||||||
|     {% for script in scripts %} |     {% for script in scripts %} | ||||||
|     {{""}}<script src="{{ url_for('static', filename=script) }}"></script> |     {{""}}<script src="{{ url_for('static', filename=script) }}"></script> | ||||||
|  | |||||||
| @ -248,6 +248,17 @@ | |||||||
|                         {{ preferences_item_footer(info, label, rtl) }} |                         {{ preferences_item_footer(info, label, rtl) }} | ||||||
|                         {% endif %} |                         {% endif %} | ||||||
| 
 | 
 | ||||||
|  |                         {% if 'infinite_scroll' not in locked_preferences %} | ||||||
|  |                         {% set label = _('Infinite scroll') %} | ||||||
|  |                         {% set info = _('Automatically load next page when scrolling to bottom of current page') %} | ||||||
|  |                         {{ preferences_item_header(info, label, rtl, 'infinite_scroll') }} | ||||||
|  |                             <select class="form-control {{ custom_select_class(rtl) }}" name="infinite_scroll" id="infinite_scroll"> | ||||||
|  |                                 <option value="1" {% if infinite_scroll %}selected="selected"{% endif %}>{{ _('On') }}</option> | ||||||
|  |                                 <option value="0" {% if not infinite_scroll %}selected="selected"{% endif %}>{{ _('Off')}}</option> | ||||||
|  |                             </select> | ||||||
|  |                         {{ preferences_item_footer(info, label, rtl) }} | ||||||
|  |                         {% endif %} | ||||||
|  | 
 | ||||||
|                         {{ plugin_of_category('ui' )}} |                         {{ plugin_of_category('ui' )}} | ||||||
|                     </div> |                     </div> | ||||||
|                 </fieldset> |                 </fieldset> | ||||||
|  | |||||||
| @ -23,7 +23,7 @@ | |||||||
|           data-method="{{ method or 'POST' }}" |           data-method="{{ method or 'POST' }}" | ||||||
|           data-autocompleter="{% if autocomplete %}true{% else %}false{% endif %}" |           data-autocompleter="{% if autocomplete %}true{% else %}false{% endif %}" | ||||||
|           data-search-on-category-select="{{ 'true' if 'plugins/js/search_on_category_select.js' in scripts else 'false'}}" |           data-search-on-category-select="{{ 'true' if 'plugins/js/search_on_category_select.js' in scripts else 'false'}}" | ||||||
|           data-infinite-scroll="{{ 'true' if 'plugins/js/infinite_scroll.js' in scripts else 'false' }}" |           data-infinite-scroll="{% if infinite_scroll %}true{% else %}false{% endif %}" | ||||||
|           data-hotkeys="{{ 'true' if 'plugins/js/vim_hotkeys.js' in scripts else 'false' }}" |           data-hotkeys="{{ 'true' if 'plugins/js/vim_hotkeys.js' in scripts else 'false' }}" | ||||||
|           data-static-path="{{ url_for('static', filename='themes/simple') }}/" |           data-static-path="{{ url_for('static', filename='themes/simple') }}/" | ||||||
|           data-translations="{{ translations }}"></script> |           data-translations="{{ translations }}"></script> | ||||||
|  | |||||||
| @ -226,6 +226,18 @@ | |||||||
|       <div class="description">{{_('Open result links on new browser tabs') }}</div> |       <div class="description">{{_('Open result links on new browser tabs') }}</div> | ||||||
|     </fieldset> |     </fieldset> | ||||||
|     {% endif %} |     {% endif %} | ||||||
|  |     {% if 'infinite_scroll' not in locked_preferences %} | ||||||
|  |     <fieldset> | ||||||
|  |       <legend>{{ _('Infinite scroll') }}</legend> | ||||||
|  |       <p class="value"> | ||||||
|  |         <select name='infinite_scroll'> | ||||||
|  |           <option value="1" {% if infinite_scroll %}selected="selected"{% endif %}>{{ _('On') }}</option> | ||||||
|  |           <option value="0" {% if not infinite_scroll %}selected="selected"{% endif %}>{{ _('Off')}}</option> | ||||||
|  |         </select> | ||||||
|  |       </p> | ||||||
|  |       <div class="description">{{ _('Automatically load next page when scrolling to bottom of current page') }}</div> | ||||||
|  |     </fieldset> | ||||||
|  |     {% endif %} | ||||||
|     {{ plugin_preferences('ui') }} |     {{ plugin_preferences('ui') }} | ||||||
|   {{ tab_footer() }} |   {{ tab_footer() }} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -431,6 +431,8 @@ def get_translations(): | |||||||
|         'no_item_found': gettext('No item found'), |         'no_item_found': gettext('No item found'), | ||||||
|         # /preferences: the source of the engine description (wikipedata, wikidata, website) |         # /preferences: the source of the engine description (wikipedata, wikidata, website) | ||||||
|         'Source': gettext('Source'), |         'Source': gettext('Source'), | ||||||
|  |         # infinite scroll | ||||||
|  |         'error_loading_next_page': gettext('Error loading the next page'), | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -463,6 +465,7 @@ def render(template_name: str, override_theme: str = None, **kwargs): | |||||||
|     kwargs['preferences'] = request.preferences |     kwargs['preferences'] = request.preferences | ||||||
|     kwargs['method'] = request.preferences.get_value('method') |     kwargs['method'] = request.preferences.get_value('method') | ||||||
|     kwargs['autocomplete'] = request.preferences.get_value('autocomplete') |     kwargs['autocomplete'] = request.preferences.get_value('autocomplete') | ||||||
|  |     kwargs['infinite_scroll'] = request.preferences.get_value('infinite_scroll') | ||||||
|     kwargs['results_on_new_tab'] = request.preferences.get_value('results_on_new_tab') |     kwargs['results_on_new_tab'] = request.preferences.get_value('results_on_new_tab') | ||||||
|     kwargs['advanced_search'] = request.preferences.get_value('advanced_search') |     kwargs['advanced_search'] = request.preferences.get_value('advanced_search') | ||||||
|     kwargs['query_in_title'] = request.preferences.get_value('query_in_title') |     kwargs['query_in_title'] = request.preferences.get_value('query_in_title') | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user