diff --git a/searx/static/themes/simple/js/searx_src/searx_imageresult.js b/searx/static/themes/__common__/js/image_layout.js similarity index 53% rename from searx/static/themes/simple/js/searx_src/searx_imageresult.js rename to searx/static/themes/__common__/js/image_layout.js index 7bbfc1454..ea54cf515 100644 --- a/searx/static/themes/simple/js/searx_src/searx_imageresult.js +++ b/searx/static/themes/__common__/js/image_layout.js @@ -3,21 +3,21 @@ * Google Image Layout v0.0.1 * Description, by Anh Trinh. * Heavily modified for searx -* http://trinhtrunganh.com +* https://ptgamr.github.io/2014-09-12-google-image-layout/ +* https://ptgamr.github.io/google-image-layout/src/google-image-layout.js * * @license Free to use under the MIT License. * */ -(function(w, d) { - 'use strict'; - - function ImageLayout(container_selector, results_selector, img_selector, maxHeight) { + +(function (w, d) { + function ImageLayout(container_selector, results_selector, img_selector, margin, maxHeight) { this.container_selector = container_selector; this.results_selector = results_selector; this.img_selector = img_selector; - this.margin = 10; + this.margin = margin; this.maxHeight = maxHeight; - this._alignAllDone = true; + this.isAlignDone = true; } /** @@ -31,12 +31,11 @@ * * @return {[type]} the height */ - ImageLayout.prototype._getHeigth = function(images, width) { - var r = 0, - img; + ImageLayout.prototype._getHeigth = function (images, width) { + var i, img; + var r = 0; - width -= images.length * this.margin; - for (var i = 0; i < images.length; i++) { + for (i = 0; i < images.length; i++) { img = images[i]; if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { r += img.naturalWidth / img.naturalHeight; @@ -46,12 +45,14 @@ } } - return width / r; //have to round down because Firefox will automatically roundup value with number of decimals > 3 + return (width - images.length * this.margin) / r; //have to round down because Firefox will automatically roundup value with number of decimals > 3 }; - ImageLayout.prototype._setSize = function(images, height) { - var img, imgWidth, imagesLength = images.length; - for (var i = 0; i < imagesLength; i++) { + ImageLayout.prototype._setSize = function (images, height) { + var i, img, imgWidth; + var imagesLength = images.length, resultNode; + + for (i = 0; i < imagesLength; i++) { img = images[i]; if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { imgWidth = height * img.naturalWidth / img.naturalHeight; @@ -65,38 +66,52 @@ img.style.marginTop = '3px'; img.style.marginRight = this.margin - 7 + 'px'; // -4 is the negative margin of the inline element img.style.marginBottom = this.margin - 7 + 'px'; + resultNode = img.parentNode.parentNode; + if (!resultNode.classList.contains('js')) { + resultNode.classList.add('js'); + } } }; - ImageLayout.prototype._alignImgs = function(imgGroup) { - var slice, h, - containerWidth = d.querySelector(this.container_selector).clientWidth; + ImageLayout.prototype._alignImgs = function (imgGroup) { + var isSearching, slice, i, h; + var containerElement = d.querySelector(this.container_selector); + var containerCompStyles = window.getComputedStyle(containerElement); + var containerPaddingLeft = parseInt(containerCompStyles.getPropertyValue('padding-left'), 10); + var containerPaddingRight = parseInt(containerCompStyles.getPropertyValue('padding-right'), 10); + var containerWidth = containerElement.clientWidth - containerPaddingLeft - containerPaddingRight; - w: while (imgGroup.length > 0) { - for (var i = 1; i <= imgGroup.length; i++) { + while (imgGroup.length > 0) { + isSearching = true; + for (i = 1; i <= imgGroup.length && isSearching; i++) { slice = imgGroup.slice(0, i); h = this._getHeigth(slice, containerWidth); if (h < this.maxHeight) { this._setSize(slice, h); + // continue with the remaining images imgGroup = imgGroup.slice(i); - continue w; + isSearching = false; } } - this._setSize(slice, Math.min(this.maxHeight, h)); - break; + if (isSearching) { + this._setSize(slice, Math.min(this.maxHeight, h)); + break; + } } }; - ImageLayout.prototype.align = function(results_selector) { - var results_selectorNode = d.querySelectorAll(this.results_selector), - results_length = results_selectorNode.length, - previous = null, - current = null, - imgGroup = []; - for (var i = 0; i < results_length; i++) { + ImageLayout.prototype.align = function () { + var i; + var results_selectorNode = d.querySelectorAll(this.results_selector); + var results_length = results_selectorNode.length; + var previous = null; + var current = null; + var imgGroup = []; + + for (i = 0; i < results_length; i++) { current = results_selectorNode[i]; if (current.previousElementSibling !== previous && imgGroup.length > 0) { - // the current image is not conected to previous one + // the current image is not connected to previous one // so the current image is the start of a new group of images. // so call _alignImgs to align the current group this._alignImgs(imgGroup); @@ -114,32 +129,29 @@ } }; - ImageLayout.prototype.watch = function() { - var i, img, imgGroup, imgNodeLength, - obj = this, - results_nodes = d.querySelectorAll(this.results_selector), - results_length = results_nodes.length; + ImageLayout.prototype.watch = function () { + var i, img; + var obj = this; + var results_nodes = d.querySelectorAll(this.results_selector); + var results_length = results_nodes.length; - function align(e) { - obj.align(); - } - - function throttleAlign(e) { - if (obj._alignAllDone) { - obj._alignAllDone = false; - setTimeout(function() { + function throttleAlign() { + if (obj.isAlignDone) { + obj.isAlignDone = false; + setTimeout(function () { obj.align(); - obj._alignAllDone = true; + obj.isAlignDone = true; }, 100); } } + w.addEventListener('pageshow', throttleAlign); + w.addEventListener('load', throttleAlign); w.addEventListener('resize', throttleAlign); - w.addEventListener('pageshow', align); for (i = 0; i < results_length; i++) { img = results_nodes[i].querySelector(this.img_selector); - if (typeof img !== 'undefined') { + if (img !== null && img !== undefined) { img.addEventListener('load', throttleAlign); img.addEventListener('error', throttleAlign); } @@ -148,4 +160,4 @@ w.searx.ImageLayout = ImageLayout; -})(window, document); +}(window, document)); diff --git a/searx/static/themes/oscar/css/logicodev-dark.css b/searx/static/themes/oscar/css/logicodev-dark.css index cfd6f7f23..9bacb3c13 100644 --- a/searx/static/themes/oscar/css/logicodev-dark.css +++ b/searx/static/themes/oscar/css/logicodev-dark.css @@ -202,14 +202,39 @@ input[type=checkbox]:not(:checked) + .label_hide_if_checked + .label_hide_if_not } .result-images { float: left !important; - width: 24%; - margin: 0.5%; + margin: 0; + padding: 0; } .result-images a { display: block; width: 100%; background-size: cover; } +.result-images a .img-thumbnail { + border: none !important; + padding: 0; +} +.result-images a:hover, +.result-images a:focus { + outline: 0; +} +.result-images a:hover .img-thumbnail, +.result-images a:focus .img-thumbnail { + box-shadow: 5px 5px 15px 0px black; +} +.result-images.js a .img-thumbnail { + max-height: inherit; + min-height: inherit; +} +.result-images:not(.js) { + width: 25%; + padding: 3px 13px 13px 3px; +} +.result-images:not(.js) a .img-thumbnail { + margin: 0; + max-height: 128px; + min-height: 128px; +} .img-thumbnail { margin: 5px; max-height: 128px; diff --git a/searx/static/themes/oscar/css/logicodev-dark.min.css b/searx/static/themes/oscar/css/logicodev-dark.min.css index 58e477082..a70a109f4 100644 Binary files a/searx/static/themes/oscar/css/logicodev-dark.min.css and b/searx/static/themes/oscar/css/logicodev-dark.min.css differ diff --git a/searx/static/themes/oscar/css/logicodev-dark.min.css.map b/searx/static/themes/oscar/css/logicodev-dark.min.css.map index 549274f3b..4cd2eb8c5 100644 Binary files a/searx/static/themes/oscar/css/logicodev-dark.min.css.map and b/searx/static/themes/oscar/css/logicodev-dark.min.css.map differ diff --git a/searx/static/themes/oscar/css/logicodev.css b/searx/static/themes/oscar/css/logicodev.css index d5c2a237a..6e5bddce3 100644 --- a/searx/static/themes/oscar/css/logicodev.css +++ b/searx/static/themes/oscar/css/logicodev.css @@ -175,14 +175,39 @@ input[type=checkbox]:not(:checked) + .label_hide_if_checked + .label_hide_if_not } .result-images { float: left !important; - width: 24%; - margin: 0.5%; + margin: 0; + padding: 0; } .result-images a { display: block; width: 100%; background-size: cover; } +.result-images a .img-thumbnail { + border: none !important; + padding: 0; +} +.result-images a:hover, +.result-images a:focus { + outline: 0; +} +.result-images a:hover .img-thumbnail, +.result-images a:focus .img-thumbnail { + box-shadow: 5px 5px 15px 0px black; +} +.result-images.js a .img-thumbnail { + max-height: inherit; + min-height: inherit; +} +.result-images:not(.js) { + width: 25%; + padding: 3px 13px 13px 3px; +} +.result-images:not(.js) a .img-thumbnail { + margin: 0; + max-height: 128px; + min-height: 128px; +} .img-thumbnail { margin: 5px; max-height: 128px; diff --git a/searx/static/themes/oscar/css/logicodev.min.css b/searx/static/themes/oscar/css/logicodev.min.css index 1a5d9f380..12ddfe00e 100644 Binary files a/searx/static/themes/oscar/css/logicodev.min.css and b/searx/static/themes/oscar/css/logicodev.min.css differ diff --git a/searx/static/themes/oscar/css/logicodev.min.css.map b/searx/static/themes/oscar/css/logicodev.min.css.map index 407ff7d41..3e15ed5ec 100644 Binary files a/searx/static/themes/oscar/css/logicodev.min.css.map and b/searx/static/themes/oscar/css/logicodev.min.css.map differ diff --git a/searx/static/themes/oscar/gruntfile.js b/searx/static/themes/oscar/gruntfile.js index 7c1f55249..1973b09c4 100644 --- a/searx/static/themes/oscar/gruntfile.js +++ b/searx/static/themes/oscar/gruntfile.js @@ -60,7 +60,7 @@ module.exports = function(grunt) { separator: ';' }, dist: { - src: ['src/js/*.js'], + src: ['src/js/*.js', '../__common__/js/image_layout.js'], dest: 'js/searx.js' } }, @@ -76,7 +76,7 @@ module.exports = function(grunt) { } }, jshint: { - files: ['gruntfile.js', 'js/searx_src/*.js'], + files: ['gruntfile.js', 'js/searx_src/*.js', '../__common__/js/image_layout.js'], options: { reporterOutput: "", // options here to override JSHint defaults diff --git a/searx/static/themes/oscar/js/searx.js b/searx/static/themes/oscar/js/searx.js index 163009481..c377e4534 100644 --- a/searx/static/themes/oscar/js/searx.js +++ b/searx/static/themes/oscar/js/searx.js @@ -17,6 +17,9 @@ window.searx = (function(d) { 'use strict'; + // + d.getElementsByTagName("html")[0].className = "js"; + // add data- properties var script = d.currentScript || (function() { var scripts = d.getElementsByTagName('script'); @@ -199,6 +202,12 @@ $(document).ready(function(){ tabs.children().attr("aria-selected", "false"); $(a.target).parent().attr("aria-selected", "true"); }); + + /** + * Layout images according to their sizes + */ + searx.image_thumbnail_layout = new searx.ImageLayout('#main_results', '#main_results .result-images', 'img.img-thumbnail', 15, 200); + searx.image_thumbnail_layout.watch(); }); ;window.addEventListener('load', function() { // Hide infobox toggle if shrunk size already fits all content. @@ -383,3 +392,166 @@ $(document).ready(function(){ }); }); +;/** +* +* Google Image Layout v0.0.1 +* Description, by Anh Trinh. +* Heavily modified for searx +* https://ptgamr.github.io/2014-09-12-google-image-layout/ +* https://ptgamr.github.io/google-image-layout/src/google-image-layout.js +* +* @license Free to use under the MIT License. +* +*/ + +(function (w, d) { + function ImageLayout(container_selector, results_selector, img_selector, margin, maxHeight) { + this.container_selector = container_selector; + this.results_selector = results_selector; + this.img_selector = img_selector; + this.margin = margin; + this.maxHeight = maxHeight; + this.isAlignDone = true; + } + + /** + * Get the height that make all images fit the container + * + * width = w1 + w2 + w3 + ... = r1*h + r2*h + r3*h + ... + * + * @param {[type]} images the images to be calculated + * @param {[type]} width the container witdth + * @param {[type]} margin the margin between each image + * + * @return {[type]} the height + */ + ImageLayout.prototype._getHeigth = function (images, width) { + var i, img; + var r = 0; + + for (i = 0; i < images.length; i++) { + img = images[i]; + if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { + r += img.naturalWidth / img.naturalHeight; + } else { + // assume that not loaded images are square + r += 1; + } + } + + return (width - images.length * this.margin) / r; //have to round down because Firefox will automatically roundup value with number of decimals > 3 + }; + + ImageLayout.prototype._setSize = function (images, height) { + var i, img, imgWidth; + var imagesLength = images.length, resultNode; + + for (i = 0; i < imagesLength; i++) { + img = images[i]; + if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { + imgWidth = height * img.naturalWidth / img.naturalHeight; + } else { + // not loaded image : make it square as _getHeigth said it + imgWidth = height; + } + img.style.width = imgWidth + 'px'; + img.style.height = height + 'px'; + img.style.marginLeft = '3px'; + img.style.marginTop = '3px'; + img.style.marginRight = this.margin - 7 + 'px'; // -4 is the negative margin of the inline element + img.style.marginBottom = this.margin - 7 + 'px'; + resultNode = img.parentNode.parentNode; + if (!resultNode.classList.contains('js')) { + resultNode.classList.add('js'); + } + } + }; + + ImageLayout.prototype._alignImgs = function (imgGroup) { + var isSearching, slice, i, h; + var containerElement = d.querySelector(this.container_selector); + var containerCompStyles = window.getComputedStyle(containerElement); + var containerPaddingLeft = parseInt(containerCompStyles.getPropertyValue('padding-left'), 10); + var containerPaddingRight = parseInt(containerCompStyles.getPropertyValue('padding-right'), 10); + var containerWidth = containerElement.clientWidth - containerPaddingLeft - containerPaddingRight; + + while (imgGroup.length > 0) { + isSearching = true; + for (i = 1; i <= imgGroup.length && isSearching; i++) { + slice = imgGroup.slice(0, i); + h = this._getHeigth(slice, containerWidth); + if (h < this.maxHeight) { + this._setSize(slice, h); + // continue with the remaining images + imgGroup = imgGroup.slice(i); + isSearching = false; + } + } + if (isSearching) { + this._setSize(slice, Math.min(this.maxHeight, h)); + break; + } + } + }; + + ImageLayout.prototype.align = function () { + var i; + var results_selectorNode = d.querySelectorAll(this.results_selector); + var results_length = results_selectorNode.length; + var previous = null; + var current = null; + var imgGroup = []; + + for (i = 0; i < results_length; i++) { + current = results_selectorNode[i]; + if (current.previousElementSibling !== previous && imgGroup.length > 0) { + // the current image is not connected to previous one + // so the current image is the start of a new group of images. + // so call _alignImgs to align the current group + this._alignImgs(imgGroup); + // and start a new empty group of images + imgGroup = []; + } + // add the current image to the group (only the img tag) + imgGroup.push(current.querySelector(this.img_selector)); + // update the previous variable + previous = current; + } + // align the remaining images + if (imgGroup.length > 0) { + this._alignImgs(imgGroup); + } + }; + + ImageLayout.prototype.watch = function () { + var i, img; + var obj = this; + var results_nodes = d.querySelectorAll(this.results_selector); + var results_length = results_nodes.length; + + function throttleAlign() { + if (obj.isAlignDone) { + obj.isAlignDone = false; + setTimeout(function () { + obj.align(); + obj.isAlignDone = true; + }, 100); + } + } + + w.addEventListener('pageshow', throttleAlign); + w.addEventListener('load', throttleAlign); + w.addEventListener('resize', throttleAlign); + + for (i = 0; i < results_length; i++) { + img = results_nodes[i].querySelector(this.img_selector); + if (img !== null && img !== undefined) { + img.addEventListener('load', throttleAlign); + img.addEventListener('error', throttleAlign); + } + } + }; + + w.searx.ImageLayout = ImageLayout; + +}(window, document)); diff --git a/searx/static/themes/oscar/js/searx.min.js b/searx/static/themes/oscar/js/searx.min.js index b3317e0c5..8b17d4f61 100644 Binary files a/searx/static/themes/oscar/js/searx.min.js and b/searx/static/themes/oscar/js/searx.min.js differ diff --git a/searx/static/themes/oscar/js/searx.min.js.map b/searx/static/themes/oscar/js/searx.min.js.map index 13e949a74..506dde42f 100644 Binary files a/searx/static/themes/oscar/js/searx.min.js.map and b/searx/static/themes/oscar/js/searx.min.js.map differ diff --git a/searx/static/themes/oscar/src/js/01_init.js b/searx/static/themes/oscar/src/js/01_init.js index dd8de4ddb..e361d87ca 100644 --- a/searx/static/themes/oscar/src/js/01_init.js +++ b/searx/static/themes/oscar/src/js/01_init.js @@ -17,6 +17,9 @@ window.searx = (function(d) { 'use strict'; + // + d.getElementsByTagName("html")[0].className = "js"; + // add data- properties var script = d.currentScript || (function() { var scripts = d.getElementsByTagName('script'); diff --git a/searx/static/themes/oscar/src/js/element_modifiers.js b/searx/static/themes/oscar/src/js/element_modifiers.js index a113df9a3..087f7d479 100644 --- a/searx/static/themes/oscar/src/js/element_modifiers.js +++ b/searx/static/themes/oscar/src/js/element_modifiers.js @@ -108,4 +108,10 @@ $(document).ready(function(){ tabs.children().attr("aria-selected", "false"); $(a.target).parent().attr("aria-selected", "true"); }); + + /** + * Layout images according to their sizes + */ + searx.image_thumbnail_layout = new searx.ImageLayout('#main_results', '#main_results .result-images', 'img.img-thumbnail', 15, 200); + searx.image_thumbnail_layout.watch(); }); diff --git a/searx/static/themes/oscar/src/less/logicodev/results.less b/searx/static/themes/oscar/src/less/logicodev/results.less index ce62cd34d..67ee296a1 100644 --- a/searx/static/themes/oscar/src/less/logicodev/results.less +++ b/searx/static/themes/oscar/src/less/logicodev/results.less @@ -77,12 +77,39 @@ // image formating of results .result-images { float: left !important; - width: 24%; - margin: .5%; + margin: 0; + padding: 0; a { display: block; width: 100%; background-size: cover; + .img-thumbnail { + border: none !important; + padding: 0; + } + &:hover, &:focus { + outline: 0; + .img-thumbnail { + box-shadow: 5px 5px 15px 0px black; + } + } + } +} + +.result-images.js a .img-thumbnail { + max-height: inherit; + min-height: inherit; +} + +.result-images:not(.js) { + width: 25%; + padding: 3px 13px 13px 3px; + a { + .img-thumbnail { + margin: 0; + max-height: 128px; + min-height: 128px; + } } } diff --git a/searx/static/themes/simple/css/searx-rtl.css b/searx/static/themes/simple/css/searx-rtl.css index 385fc7d5e..6b9b47d85 100644 --- a/searx/static/themes/simple/css/searx-rtl.css +++ b/searx/static/themes/simple/css/searx-rtl.css @@ -1,4 +1,4 @@ -/*! searx | 16-03-2021 | */ +/*! searx | 23-03-2021 | */ /* * searx, A privacy-respecting, hackable metasearch engine * diff --git a/searx/static/themes/simple/css/searx-rtl.min.css b/searx/static/themes/simple/css/searx-rtl.min.css index 1cb4a4aa2..3b5d7f753 100644 Binary files a/searx/static/themes/simple/css/searx-rtl.min.css and b/searx/static/themes/simple/css/searx-rtl.min.css differ diff --git a/searx/static/themes/simple/css/searx.css b/searx/static/themes/simple/css/searx.css index 206c5f903..484fdc82d 100644 --- a/searx/static/themes/simple/css/searx.css +++ b/searx/static/themes/simple/css/searx.css @@ -1,4 +1,4 @@ -/*! searx | 16-03-2021 | */ +/*! searx | 23-03-2021 | */ /* * searx, A privacy-respecting, hackable metasearch engine * diff --git a/searx/static/themes/simple/css/searx.min.css b/searx/static/themes/simple/css/searx.min.css index b2eb4f528..2757ba434 100644 Binary files a/searx/static/themes/simple/css/searx.min.css and b/searx/static/themes/simple/css/searx.min.css differ diff --git a/searx/static/themes/simple/gruntfile.js b/searx/static/themes/simple/gruntfile.js index c8f2ed3c6..0c322f37f 100644 --- a/searx/static/themes/simple/gruntfile.js +++ b/searx/static/themes/simple/gruntfile.js @@ -11,7 +11,7 @@ module.exports = function(grunt) { } }, jshint: { - files: ['js/searx_src/*.js', 'js/searx_header/*.js'], + files: ['js/searx_src/*.js', 'js/searx_header/*.js', '../__common__/js/*.js'], options: { reporterOutput: "", proto: true, @@ -30,7 +30,7 @@ module.exports = function(grunt) { }, files: { 'js/searx.head.js': ['js/searx_head/*.js'], - 'js/searx.js': ['js/searx_src/*.js'] + 'js/searx.js': ['js/searx_src/*.js', '../__common__/js/*.js'] } } }, diff --git a/searx/static/themes/simple/js/searx.head.min.js b/searx/static/themes/simple/js/searx.head.min.js index 5c87d749b..dd85086ee 100644 Binary files a/searx/static/themes/simple/js/searx.head.min.js and b/searx/static/themes/simple/js/searx.head.min.js differ diff --git a/searx/static/themes/simple/js/searx.js b/searx/static/themes/simple/js/searx.js index 1abe81e4d..88c1823bc 100644 --- a/searx/static/themes/simple/js/searx.js +++ b/searx/static/themes/simple/js/searx.js @@ -698,157 +698,6 @@ module.exports = AutoComplete; },{}]},{},[1])(1) }); -;/** -* -* Google Image Layout v0.0.1 -* Description, by Anh Trinh. -* Heavily modified for searx -* http://trinhtrunganh.com -* -* @license Free to use under the MIT License. -* -*/ -(function(w, d) { - 'use strict'; - - function ImageLayout(container_selector, results_selector, img_selector, maxHeight) { - this.container_selector = container_selector; - this.results_selector = results_selector; - this.img_selector = img_selector; - this.margin = 10; - this.maxHeight = maxHeight; - this._alignAllDone = true; - } - - /** - * Get the height that make all images fit the container - * - * width = w1 + w2 + w3 + ... = r1*h + r2*h + r3*h + ... - * - * @param {[type]} images the images to be calculated - * @param {[type]} width the container witdth - * @param {[type]} margin the margin between each image - * - * @return {[type]} the height - */ - ImageLayout.prototype._getHeigth = function(images, width) { - var r = 0, - img; - - width -= images.length * this.margin; - for (var i = 0; i < images.length; i++) { - img = images[i]; - if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { - r += img.naturalWidth / img.naturalHeight; - } else { - // assume that not loaded images are square - r += 1; - } - } - - return width / r; //have to round down because Firefox will automatically roundup value with number of decimals > 3 - }; - - ImageLayout.prototype._setSize = function(images, height) { - var img, imgWidth, imagesLength = images.length; - for (var i = 0; i < imagesLength; i++) { - img = images[i]; - if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { - imgWidth = height * img.naturalWidth / img.naturalHeight; - } else { - // not loaded image : make it square as _getHeigth said it - imgWidth = height; - } - img.style.width = imgWidth + 'px'; - img.style.height = height + 'px'; - img.style.marginLeft = '3px'; - img.style.marginTop = '3px'; - img.style.marginRight = this.margin - 7 + 'px'; // -4 is the negative margin of the inline element - img.style.marginBottom = this.margin - 7 + 'px'; - } - }; - - ImageLayout.prototype._alignImgs = function(imgGroup) { - var slice, h, - containerWidth = d.querySelector(this.container_selector).clientWidth; - - w: while (imgGroup.length > 0) { - for (var i = 1; i <= imgGroup.length; i++) { - slice = imgGroup.slice(0, i); - h = this._getHeigth(slice, containerWidth); - if (h < this.maxHeight) { - this._setSize(slice, h); - imgGroup = imgGroup.slice(i); - continue w; - } - } - this._setSize(slice, Math.min(this.maxHeight, h)); - break; - } - }; - - ImageLayout.prototype.align = function(results_selector) { - var results_selectorNode = d.querySelectorAll(this.results_selector), - results_length = results_selectorNode.length, - previous = null, - current = null, - imgGroup = []; - for (var i = 0; i < results_length; i++) { - current = results_selectorNode[i]; - if (current.previousElementSibling !== previous && imgGroup.length > 0) { - // the current image is not conected to previous one - // so the current image is the start of a new group of images. - // so call _alignImgs to align the current group - this._alignImgs(imgGroup); - // and start a new empty group of images - imgGroup = []; - } - // add the current image to the group (only the img tag) - imgGroup.push(current.querySelector(this.img_selector)); - // update the previous variable - previous = current; - } - // align the remaining images - if (imgGroup.length > 0) { - this._alignImgs(imgGroup); - } - }; - - ImageLayout.prototype.watch = function() { - var i, img, imgGroup, imgNodeLength, - obj = this, - results_nodes = d.querySelectorAll(this.results_selector), - results_length = results_nodes.length; - - function align(e) { - obj.align(); - } - - function throttleAlign(e) { - if (obj._alignAllDone) { - obj._alignAllDone = false; - setTimeout(function() { - obj.align(); - obj._alignAllDone = true; - }, 100); - } - } - - w.addEventListener('resize', throttleAlign); - w.addEventListener('pageshow', align); - - for (i = 0; i < results_length; i++) { - img = results_nodes[i].querySelector(this.img_selector); - if (typeof img !== 'undefined') { - img.addEventListener('load', throttleAlign); - img.addEventListener('error', throttleAlign); - } - } - }; - - w.searx.ImageLayout = ImageLayout; - -})(window, document); ;searx.ready(function() { searx.on('.result', 'click', function() { @@ -1411,7 +1260,7 @@ module.exports = AutoComplete; 'use strict'; searx.ready(function() { - searx.image_thumbnail_layout = new searx.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 200); + searx.image_thumbnail_layout = new searx.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 10, 200); searx.image_thumbnail_layout.watch(); searx.on('.btn-collapse', 'click', function(event) { @@ -1575,3 +1424,166 @@ module.exports = AutoComplete; }); })(window, document, window.searx); +;/** +* +* Google Image Layout v0.0.1 +* Description, by Anh Trinh. +* Heavily modified for searx +* https://ptgamr.github.io/2014-09-12-google-image-layout/ +* https://ptgamr.github.io/google-image-layout/src/google-image-layout.js +* +* @license Free to use under the MIT License. +* +*/ + +(function (w, d) { + function ImageLayout(container_selector, results_selector, img_selector, margin, maxHeight) { + this.container_selector = container_selector; + this.results_selector = results_selector; + this.img_selector = img_selector; + this.margin = margin; + this.maxHeight = maxHeight; + this.isAlignDone = true; + } + + /** + * Get the height that make all images fit the container + * + * width = w1 + w2 + w3 + ... = r1*h + r2*h + r3*h + ... + * + * @param {[type]} images the images to be calculated + * @param {[type]} width the container witdth + * @param {[type]} margin the margin between each image + * + * @return {[type]} the height + */ + ImageLayout.prototype._getHeigth = function (images, width) { + var i, img; + var r = 0; + + for (i = 0; i < images.length; i++) { + img = images[i]; + if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { + r += img.naturalWidth / img.naturalHeight; + } else { + // assume that not loaded images are square + r += 1; + } + } + + return (width - images.length * this.margin) / r; //have to round down because Firefox will automatically roundup value with number of decimals > 3 + }; + + ImageLayout.prototype._setSize = function (images, height) { + var i, img, imgWidth; + var imagesLength = images.length, resultNode; + + for (i = 0; i < imagesLength; i++) { + img = images[i]; + if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { + imgWidth = height * img.naturalWidth / img.naturalHeight; + } else { + // not loaded image : make it square as _getHeigth said it + imgWidth = height; + } + img.style.width = imgWidth + 'px'; + img.style.height = height + 'px'; + img.style.marginLeft = '3px'; + img.style.marginTop = '3px'; + img.style.marginRight = this.margin - 7 + 'px'; // -4 is the negative margin of the inline element + img.style.marginBottom = this.margin - 7 + 'px'; + resultNode = img.parentNode.parentNode; + if (!resultNode.classList.contains('js')) { + resultNode.classList.add('js'); + } + } + }; + + ImageLayout.prototype._alignImgs = function (imgGroup) { + var isSearching, slice, i, h; + var containerElement = d.querySelector(this.container_selector); + var containerCompStyles = window.getComputedStyle(containerElement); + var containerPaddingLeft = parseInt(containerCompStyles.getPropertyValue('padding-left'), 10); + var containerPaddingRight = parseInt(containerCompStyles.getPropertyValue('padding-right'), 10); + var containerWidth = containerElement.clientWidth - containerPaddingLeft - containerPaddingRight; + + while (imgGroup.length > 0) { + isSearching = true; + for (i = 1; i <= imgGroup.length && isSearching; i++) { + slice = imgGroup.slice(0, i); + h = this._getHeigth(slice, containerWidth); + if (h < this.maxHeight) { + this._setSize(slice, h); + // continue with the remaining images + imgGroup = imgGroup.slice(i); + isSearching = false; + } + } + if (isSearching) { + this._setSize(slice, Math.min(this.maxHeight, h)); + break; + } + } + }; + + ImageLayout.prototype.align = function () { + var i; + var results_selectorNode = d.querySelectorAll(this.results_selector); + var results_length = results_selectorNode.length; + var previous = null; + var current = null; + var imgGroup = []; + + for (i = 0; i < results_length; i++) { + current = results_selectorNode[i]; + if (current.previousElementSibling !== previous && imgGroup.length > 0) { + // the current image is not connected to previous one + // so the current image is the start of a new group of images. + // so call _alignImgs to align the current group + this._alignImgs(imgGroup); + // and start a new empty group of images + imgGroup = []; + } + // add the current image to the group (only the img tag) + imgGroup.push(current.querySelector(this.img_selector)); + // update the previous variable + previous = current; + } + // align the remaining images + if (imgGroup.length > 0) { + this._alignImgs(imgGroup); + } + }; + + ImageLayout.prototype.watch = function () { + var i, img; + var obj = this; + var results_nodes = d.querySelectorAll(this.results_selector); + var results_length = results_nodes.length; + + function throttleAlign() { + if (obj.isAlignDone) { + obj.isAlignDone = false; + setTimeout(function () { + obj.align(); + obj.isAlignDone = true; + }, 100); + } + } + + w.addEventListener('pageshow', throttleAlign); + w.addEventListener('load', throttleAlign); + w.addEventListener('resize', throttleAlign); + + for (i = 0; i < results_length; i++) { + img = results_nodes[i].querySelector(this.img_selector); + if (img !== null && img !== undefined) { + img.addEventListener('load', throttleAlign); + img.addEventListener('error', throttleAlign); + } + } + }; + + w.searx.ImageLayout = ImageLayout; + +}(window, document)); diff --git a/searx/static/themes/simple/js/searx.min.js b/searx/static/themes/simple/js/searx.min.js index 3b2b9d762..17daac2a4 100644 Binary files a/searx/static/themes/simple/js/searx.min.js and b/searx/static/themes/simple/js/searx.min.js differ diff --git a/searx/static/themes/simple/js/searx.min.js.map b/searx/static/themes/simple/js/searx.min.js.map index efce15142..6541da7b5 100644 Binary files a/searx/static/themes/simple/js/searx.min.js.map and b/searx/static/themes/simple/js/searx.min.js.map differ diff --git a/searx/static/themes/simple/js/searx_src/searx_results.js b/searx/static/themes/simple/js/searx_src/searx_results.js index b13da8391..fe00efc90 100644 --- a/searx/static/themes/simple/js/searx_src/searx_results.js +++ b/searx/static/themes/simple/js/searx_src/searx_results.js @@ -18,7 +18,7 @@ 'use strict'; searx.ready(function() { - searx.image_thumbnail_layout = new searx.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 200); + searx.image_thumbnail_layout = new searx.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 10, 200); searx.image_thumbnail_layout.watch(); searx.on('.btn-collapse', 'click', function(event) { diff --git a/searx/templates/oscar/base.html b/searx/templates/oscar/base.html index b5c6ed258..6134bd725 100644 --- a/searx/templates/oscar/base.html +++ b/searx/templates/oscar/base.html @@ -1,6 +1,6 @@ {% from 'oscar/macros.html' import icon %} - +