[enh] add simple theme (WIP)
10
.gitattributes
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
searx/static/css/bootstrap.min.css -diff
|
||||
searx/static/js/bootstrap.min.js -diff
|
||||
searx/static/themes/oscar/css/logicodev.min.css -diff
|
||||
searx/static/themes/oscar/css/leaflet.min.css -diff
|
||||
searx/static/themes/oscar/css/pointhi.min.css -diff
|
||||
searx/static/themes/oscar/js/searx.min.js -diff
|
||||
searx/static/themes/simple/css/searx.min.css -diff
|
||||
searx/static/themes/simple/css/searx-rtl.min.css -diff
|
||||
searx/static/themes/simple/js/searx.min.js -diff
|
||||
searx/static/themes/simple/js/searx.min.js.map -diff
|
@ -13,10 +13,11 @@ python:
|
||||
before_install:
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
- npm install less grunt-cli
|
||||
- npm install less less-plugin-clean-css grunt-cli
|
||||
- ( cd searx/static/themes/oscar;npm install; cd - )
|
||||
- ( cd searx/static/themes/simple;npm install; cd - )
|
||||
- mkdir -p ~/drivers; export PATH=~/drivers:$PATH;
|
||||
- GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v0.11.1/geckodriver-v0.11.1-linux64.tar.gz";
|
||||
- GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v0.14.0/geckodriver-v0.14.0-linux64.tar.gz";
|
||||
- FILE=`mktemp`; wget "$GECKODRIVER_URL" -qO $FILE && tar xz -C ~/drivers -f $FILE geckodriver; rm $FILE; chmod 777 ~/drivers/geckodriver;
|
||||
install:
|
||||
- ./manage.sh update_dev_packages
|
||||
|
10
manage.sh
@ -22,7 +22,7 @@ check_geckodriver() {
|
||||
if [ -z $NOTFOUND ]; then
|
||||
return
|
||||
fi
|
||||
GECKODRIVER_VERSION="v0.11.1"
|
||||
GECKODRIVER_VERSION="v0.14.0"
|
||||
PLATFORM=`python -c "import platform; print platform.system().lower(), platform.architecture()[0]"`
|
||||
case $PLATFORM in
|
||||
"linux 32bit" | "linux2 32bit") ARCH="linux32";;
|
||||
@ -49,7 +49,7 @@ pep8_check() {
|
||||
# ignored rules:
|
||||
# E402 module level import not at top of file
|
||||
# W503 line break before binary operator
|
||||
pep8 --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests"
|
||||
pep8 --exclude=searx/static --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests"
|
||||
}
|
||||
|
||||
unit_tests() {
|
||||
@ -79,7 +79,8 @@ tests() {
|
||||
}
|
||||
|
||||
build_style() {
|
||||
lessc -x "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
|
||||
# lessc -x "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
|
||||
lessc --clean-css="--s1 --advanced --compatibility=ie9" "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
|
||||
}
|
||||
|
||||
styles() {
|
||||
@ -92,10 +93,13 @@ styles() {
|
||||
build_style themes/oscar/less/pointhi/oscar.less themes/oscar/css/pointhi.min.css
|
||||
build_style themes/oscar/less/logicodev/oscar.less themes/oscar/css/logicodev.min.css
|
||||
build_style themes/pix-art/less/style.less themes/pix-art/css/style.css
|
||||
build_style themes/simple/less/style.less themes/simple/css/searx.min.css
|
||||
build_style themes/simple/less/style-rtl.less themes/simple/css/searx-rtl.min.css
|
||||
}
|
||||
|
||||
grunt_build() {
|
||||
grunt --gruntfile "$SEARX_DIR/static/themes/oscar/gruntfile.js"
|
||||
grunt --gruntfile "$SEARX_DIR/static/themes/simple/gruntfile.js"
|
||||
}
|
||||
|
||||
locales() {
|
||||
|
@ -7,6 +7,7 @@ regex = re.compile(r'10\.\d{4,9}/[^\s]+')
|
||||
name = gettext('DOAI rewrite')
|
||||
description = gettext('Avoid paywalls by redirecting to open-access versions of publications when available')
|
||||
default_on = False
|
||||
preference_section = 'privacy'
|
||||
|
||||
|
||||
def extract_doi(url):
|
||||
|
@ -31,6 +31,7 @@ if sys.version_info[0] == 3:
|
||||
name = "HTTPS rewrite"
|
||||
description = gettext('Rewrite HTTP links to HTTPS if possible')
|
||||
default_on = True
|
||||
preference_section = 'privacy'
|
||||
|
||||
if 'SEARX_HTTPS_REWRITE_PATH' in environ:
|
||||
rules_path = environ['SEARX_rules_path']
|
||||
|
@ -3,6 +3,7 @@ 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',)
|
||||
|
@ -19,5 +19,6 @@ name = gettext('Search on category select')
|
||||
description = gettext('Perform search immediately if a category selected. '
|
||||
'Disable to select multiple categories. (JavaScript required)')
|
||||
default_on = True
|
||||
preference_section = 'ui'
|
||||
|
||||
js_dependencies = ('plugins/js/search_on_category_select.js',)
|
||||
|
@ -26,6 +26,7 @@ regexes = {re.compile(r'utm_[^&]+&?'),
|
||||
name = gettext('Tracker URL remover')
|
||||
description = gettext('Remove trackers arguments from the returned URL')
|
||||
default_on = True
|
||||
preference_section = 'privacy'
|
||||
|
||||
|
||||
def on_result(request, search, result):
|
||||
|
1
searx/static/themes/simple/.jshintignore
Normal file
@ -0,0 +1 @@
|
||||
js/searx_src/autocomplete.js
|
2049
searx/static/themes/simple/css/searx-rtl.css
Normal file
BIN
searx/static/themes/simple/css/searx-rtl.min.css
vendored
Normal file
2045
searx/static/themes/simple/css/searx.css
Normal file
BIN
searx/static/themes/simple/css/searx.min.css
vendored
Normal file
134
searx/static/themes/simple/fonts/ion.css
Normal file
@ -0,0 +1,134 @@
|
||||
/* Generated by grunt-webfont */
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family:"ion";
|
||||
src:url("../fonts/ion.eot?94af7082ea096aefe3a7b6642834716e");
|
||||
src:url("../fonts/ion.eot?#iefix") format("embedded-opentype"),
|
||||
url("../fonts/ion.woff2?94af7082ea096aefe3a7b6642834716e") format("woff2"),
|
||||
url("../fonts/ion.woff?94af7082ea096aefe3a7b6642834716e") format("woff"),
|
||||
url("../fonts/ion.ttf?94af7082ea096aefe3a7b6642834716e") format("truetype"),
|
||||
url("../fonts/ion.svg?94af7082ea096aefe3a7b6642834716e#ion") format("svg");
|
||||
font-weight:normal;
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
.ion-icon {
|
||||
|
||||
font-family:"ion";
|
||||
|
||||
display:inline-block;
|
||||
vertical-align:middle;
|
||||
line-height:1;
|
||||
font-weight:normal;
|
||||
font-style:normal;
|
||||
speak:none;
|
||||
text-decoration:inherit;
|
||||
text-transform:none;
|
||||
text-rendering:auto;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
-moz-osx-font-smoothing:grayscale;
|
||||
}
|
||||
|
||||
|
||||
/* Icons */
|
||||
|
||||
|
||||
.ion-navicon-round:before {
|
||||
content:"\f101";
|
||||
}
|
||||
|
||||
|
||||
.ion-search:before {
|
||||
content:"\f102";
|
||||
}
|
||||
|
||||
|
||||
.ion-play:before {
|
||||
content:"\f103";
|
||||
}
|
||||
|
||||
|
||||
.ion-link:before {
|
||||
content:"\f104";
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-up:before {
|
||||
content:"\f105";
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-left:before {
|
||||
content:"\f106";
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-right:before {
|
||||
content:"\f107";
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-down-a:before {
|
||||
content:"\f108";
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-up-a:before {
|
||||
content:"\f109";
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-swap:before {
|
||||
content:"\f10a";
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-dropdown:before {
|
||||
content:"\f10b";
|
||||
}
|
||||
|
||||
|
||||
.ion-globe:before {
|
||||
content:"\f10c";
|
||||
}
|
||||
|
||||
|
||||
.ion-time:before {
|
||||
content:"\f10d";
|
||||
}
|
||||
|
||||
|
||||
.ion-location:before {
|
||||
content:"\f10e";
|
||||
}
|
||||
|
||||
|
||||
.ion-warning:before {
|
||||
content:"\f10f";
|
||||
}
|
||||
|
||||
|
||||
.ion-error:before {
|
||||
content:"\f110";
|
||||
}
|
||||
|
||||
|
||||
.ion-film-outline:before {
|
||||
content:"\f111";
|
||||
}
|
||||
|
||||
|
||||
.ion-music-note:before {
|
||||
content:"\f112";
|
||||
}
|
||||
|
||||
|
||||
.ion-more-vertical:before {
|
||||
content:"\f113";
|
||||
}
|
||||
|
||||
|
||||
.ion-magnet:before {
|
||||
content:"\f114";
|
||||
}
|
BIN
searx/static/themes/simple/fonts/ion.eot
Normal file
261
searx/static/themes/simple/fonts/ion.html
Normal file
@ -0,0 +1,261 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ion</title>
|
||||
<style>
|
||||
body {
|
||||
margin:0;
|
||||
padding:10px 20px;
|
||||
background:#fff;
|
||||
color:#222;
|
||||
}
|
||||
h1, div, footer {
|
||||
font-family:"Helvetica Neue", Arial, sans-serif;
|
||||
}
|
||||
h1 {
|
||||
margin:0 0 20px;
|
||||
font-size:32px;
|
||||
font-weight:normal;
|
||||
}
|
||||
h1 small {
|
||||
font-size: 0.8em;
|
||||
padding-left: 2em;
|
||||
}
|
||||
.icons {
|
||||
margin-bottom:40px;
|
||||
-webkit-column-count:5;
|
||||
-moz-column-count:5;
|
||||
column-count:5;
|
||||
-webkit-column-gap:20px;
|
||||
-moz-column-gap:20px;
|
||||
column-gap:20px;
|
||||
}
|
||||
.icons__item,
|
||||
.icons__item i {
|
||||
line-height:2em;
|
||||
cursor:pointer;
|
||||
overflow:hidden;
|
||||
}
|
||||
.icons__item:hover {
|
||||
color:#3c90be;
|
||||
}
|
||||
.icons__item i {
|
||||
display:inline-block;
|
||||
width:32px;
|
||||
text-align:center;
|
||||
}
|
||||
.icons__item:hover i {
|
||||
-webkit-transform:scale(1.5);
|
||||
transform:scale(1.5);
|
||||
}
|
||||
footer {
|
||||
margin-top:40px;
|
||||
font-size:14px;
|
||||
color:#999;
|
||||
}
|
||||
|
||||
/* Generated by grunt-webfont */
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family:"ion";
|
||||
src:url("ion.eot?94af7082ea096aefe3a7b6642834716e");
|
||||
src:url("ion.eot?#iefix") format("embedded-opentype"),
|
||||
url("ion.woff2?94af7082ea096aefe3a7b6642834716e") format("woff2"),
|
||||
url("ion.woff?94af7082ea096aefe3a7b6642834716e") format("woff"),
|
||||
url("ion.ttf?94af7082ea096aefe3a7b6642834716e") format("truetype"),
|
||||
url("ion.svg?94af7082ea096aefe3a7b6642834716e#ion") format("svg");
|
||||
font-weight:normal;
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
.ion-icon {
|
||||
|
||||
font-family:"ion";
|
||||
|
||||
display:inline-block;
|
||||
vertical-align:middle;
|
||||
line-height:1;
|
||||
font-weight:normal;
|
||||
font-style:normal;
|
||||
speak:none;
|
||||
text-decoration:inherit;
|
||||
text-transform:none;
|
||||
text-rendering:auto;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
-moz-osx-font-smoothing:grayscale;
|
||||
}
|
||||
|
||||
|
||||
/* Icons */
|
||||
|
||||
|
||||
.ion-navicon-round:before {
|
||||
content:"\f101";
|
||||
}
|
||||
|
||||
|
||||
.ion-search:before {
|
||||
content:"\f102";
|
||||
}
|
||||
|
||||
|
||||
.ion-play:before {
|
||||
content:"\f103";
|
||||
}
|
||||
|
||||
|
||||
.ion-link:before {
|
||||
content:"\f104";
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-up:before {
|
||||
content:"\f105";
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-left:before {
|
||||
content:"\f106";
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-right:before {
|
||||
content:"\f107";
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-down-a:before {
|
||||
content:"\f108";
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-up-a:before {
|
||||
content:"\f109";
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-swap:before {
|
||||
content:"\f10a";
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-dropdown:before {
|
||||
content:"\f10b";
|
||||
}
|
||||
|
||||
|
||||
.ion-globe:before {
|
||||
content:"\f10c";
|
||||
}
|
||||
|
||||
|
||||
.ion-time:before {
|
||||
content:"\f10d";
|
||||
}
|
||||
|
||||
|
||||
.ion-location:before {
|
||||
content:"\f10e";
|
||||
}
|
||||
|
||||
|
||||
.ion-warning:before {
|
||||
content:"\f10f";
|
||||
}
|
||||
|
||||
|
||||
.ion-error:before {
|
||||
content:"\f110";
|
||||
}
|
||||
|
||||
|
||||
.ion-film-outline:before {
|
||||
content:"\f111";
|
||||
}
|
||||
|
||||
|
||||
.ion-music-note:before {
|
||||
content:"\f112";
|
||||
}
|
||||
|
||||
|
||||
.ion-more-vertical:before {
|
||||
content:"\f113";
|
||||
}
|
||||
|
||||
|
||||
.ion-magnet:before {
|
||||
content:"\f114";
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>ion</h1>
|
||||
|
||||
<div class="icons" id="icons">
|
||||
|
||||
<div class="icons__item" data-name="navicon-round"><i class="ion-icon ion-navicon-round"></i> ion-navicon-round</div>
|
||||
|
||||
<div class="icons__item" data-name="search"><i class="ion-icon ion-search"></i> ion-search</div>
|
||||
|
||||
<div class="icons__item" data-name="play"><i class="ion-icon ion-play"></i> ion-play</div>
|
||||
|
||||
<div class="icons__item" data-name="link"><i class="ion-icon ion-link"></i> ion-link</div>
|
||||
|
||||
<div class="icons__item" data-name="chevron-up"><i class="ion-icon ion-chevron-up"></i> ion-chevron-up</div>
|
||||
|
||||
<div class="icons__item" data-name="chevron-left"><i class="ion-icon ion-chevron-left"></i> ion-chevron-left</div>
|
||||
|
||||
<div class="icons__item" data-name="chevron-right"><i class="ion-icon ion-chevron-right"></i> ion-chevron-right</div>
|
||||
|
||||
<div class="icons__item" data-name="arrow-down-a"><i class="ion-icon ion-arrow-down-a"></i> ion-arrow-down-a</div>
|
||||
|
||||
<div class="icons__item" data-name="arrow-up-a"><i class="ion-icon ion-arrow-up-a"></i> ion-arrow-up-a</div>
|
||||
|
||||
<div class="icons__item" data-name="arrow-swap"><i class="ion-icon ion-arrow-swap"></i> ion-arrow-swap</div>
|
||||
|
||||
<div class="icons__item" data-name="arrow-dropdown"><i class="ion-icon ion-arrow-dropdown"></i> ion-arrow-dropdown</div>
|
||||
|
||||
<div class="icons__item" data-name="globe"><i class="ion-icon ion-globe"></i> ion-globe</div>
|
||||
|
||||
<div class="icons__item" data-name="time"><i class="ion-icon ion-time"></i> ion-time</div>
|
||||
|
||||
<div class="icons__item" data-name="location"><i class="ion-icon ion-location"></i> ion-location</div>
|
||||
|
||||
<div class="icons__item" data-name="warning"><i class="ion-icon ion-warning"></i> ion-warning</div>
|
||||
|
||||
<div class="icons__item" data-name="error"><i class="ion-icon ion-error"></i> ion-error</div>
|
||||
|
||||
<div class="icons__item" data-name="film-outline"><i class="ion-icon ion-film-outline"></i> ion-film-outline</div>
|
||||
|
||||
<div class="icons__item" data-name="music-note"><i class="ion-icon ion-music-note"></i> ion-music-note</div>
|
||||
|
||||
<div class="icons__item" data-name="more-vertical"><i class="ion-icon ion-more-vertical"></i> ion-more-vertical</div>
|
||||
|
||||
<div class="icons__item" data-name="magnet"><i class="ion-icon ion-magnet"></i> ion-magnet</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<h1>Usage</h1>
|
||||
<pre><code><i class="ion-icon ion-<span id="name">name</span>"></i></code></pre>
|
||||
|
||||
|
||||
<footer>Generated by <a href="https://github.com/sapegin/grunt-webfont">grunt-webfont</a>.</footer>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
document.getElementById('icons').onclick = function(e) {
|
||||
e = e || window.event;
|
||||
var name = e.target.getAttribute('data-name') || e.target.parentNode.getAttribute('data-name');
|
||||
document.getElementById('name').innerHTML = name;
|
||||
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
BIN
searx/static/themes/simple/fonts/ion.svg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
searx/static/themes/simple/fonts/ion.ttf
Normal file
BIN
searx/static/themes/simple/fonts/ion.woff
Normal file
BIN
searx/static/themes/simple/fonts/ion.woff2
Normal file
150
searx/static/themes/simple/gruntfile.js
Normal file
@ -0,0 +1,150 @@
|
||||
module.exports = function(grunt) {
|
||||
|
||||
const path = require('path');
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
watch: {
|
||||
scripts: {
|
||||
files: ['<%= jshint.files %>', 'less/*.less'],
|
||||
tasks: ['jshint', 'concat', 'uglify', 'webfont', 'less:development', 'less:production']
|
||||
}
|
||||
},
|
||||
concat: {
|
||||
options: {
|
||||
separator: ';'
|
||||
},
|
||||
dist: {
|
||||
src: ['js/searx_src/*.js'],
|
||||
dest: 'js/searx.js'
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '/*! simple/searx.min.js | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n',
|
||||
preserveComments: 'some',
|
||||
sourceMap: true
|
||||
},
|
||||
dist: {
|
||||
files: {
|
||||
'js/searx.min.js': ['<%= concat.dist.dest %>']
|
||||
}
|
||||
}
|
||||
},
|
||||
jshint: {
|
||||
files: ['js/searx_src/*.js'],
|
||||
options: {
|
||||
proto: true,
|
||||
// options here to override JSHint defaults
|
||||
globals: {
|
||||
browser: true,
|
||||
jQuery: false,
|
||||
devel: true
|
||||
}
|
||||
}
|
||||
},
|
||||
less: {
|
||||
development: {
|
||||
options: {
|
||||
paths: ["less"],
|
||||
banner: '/*! searx | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
|
||||
},
|
||||
files: {
|
||||
"css/searx.css": "less/style.less",
|
||||
"css/searx-rtl.css": "less/style-rtl.less"
|
||||
}
|
||||
},
|
||||
production: {
|
||||
options: {
|
||||
paths: ["less"],
|
||||
plugins: [
|
||||
new (require('less-plugin-clean-css'))({
|
||||
advanced: true,
|
||||
compatibility: 'ie8'
|
||||
})
|
||||
],
|
||||
banner: '/*! searx | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
|
||||
},
|
||||
files: {
|
||||
"css/searx.min.css": "less/style.less",
|
||||
"css/searx-rtl.min.css": "less/style-rtl.less"
|
||||
}
|
||||
},
|
||||
},
|
||||
webfont: {
|
||||
icons: {
|
||||
// src: 'node_modules/ionicons-npm/src/*.svg',
|
||||
src: [
|
||||
'node_modules/ionicons-npm/src/navicon-round.svg',
|
||||
'node_modules/ionicons-npm/src/search.svg',
|
||||
'node_modules/ionicons-npm/src/play.svg',
|
||||
'node_modules/ionicons-npm/src/link.svg',
|
||||
'node_modules/ionicons-npm/src/chevron-up.svg',
|
||||
'node_modules/ionicons-npm/src/chevron-left.svg',
|
||||
'node_modules/ionicons-npm/src/chevron-right.svg',
|
||||
'node_modules/ionicons-npm/src/arrow-down-a.svg',
|
||||
'node_modules/ionicons-npm/src/arrow-up-a.svg',
|
||||
'node_modules/ionicons-npm/src/arrow-swap.svg',
|
||||
'node_modules/ionicons-npm/src/telephone.svg',
|
||||
'node_modules/ionicons-npm/src/android-arrow-dropdown.svg',
|
||||
'node_modules/ionicons-npm/src/android-globe.svg',
|
||||
'node_modules/ionicons-npm/src/android-time.svg',
|
||||
'node_modules/ionicons-npm/src/location.svg',
|
||||
'node_modules/ionicons-npm/src/alert-circled.svg',
|
||||
'node_modules/ionicons-npm/src/android-alert.svg',
|
||||
'node_modules/ionicons-npm/src/ios-film-outline.svg',
|
||||
'node_modules/ionicons-npm/src/music-note.svg',
|
||||
'node_modules/ionicons-npm/src/ion-close-round.svg',
|
||||
'node_modules/ionicons-npm/src/android-more-vertical.svg',
|
||||
'magnet.svg'
|
||||
],
|
||||
dest: 'fonts',
|
||||
destLess: 'less',
|
||||
options: {
|
||||
font: 'ion',
|
||||
hashes : true,
|
||||
syntax: 'bem',
|
||||
styles : 'font,icon',
|
||||
types : 'eot,woff2,woff,ttf,svg',
|
||||
order : 'eot,woff2,woff,ttf,svg',
|
||||
stylesheets : ['css', 'less'],
|
||||
relativeFontPath : '../fonts/',
|
||||
autoHint : false,
|
||||
normalize : false,
|
||||
// ligatures : true,
|
||||
optimize : true,
|
||||
// fontHeight : 400,
|
||||
rename : function(name) {
|
||||
basename = path.basename(name);
|
||||
if (basename === 'android-alert.svg') {
|
||||
return 'error.svg';
|
||||
}
|
||||
if (basename === 'alert-circled.svg') {
|
||||
return 'warning.svg';
|
||||
}
|
||||
if (basename === 'ion-close-round.svg') {
|
||||
return 'close.svg';
|
||||
}
|
||||
return basename.replace(/(ios|md|android)-/i, '');
|
||||
},
|
||||
templateOptions: {
|
||||
baseClass: 'ion-icon',
|
||||
classPrefix: 'ion-'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-less');
|
||||
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
||||
grunt.loadNpmTasks('grunt-webfont');
|
||||
|
||||
grunt.registerTask('test', ['jshint']);
|
||||
|
||||
grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'less:development', 'less:production']);
|
||||
};
|
BIN
searx/static/themes/simple/img/favicon.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
searx/static/themes/simple/img/loader.gif
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
searx/static/themes/simple/img/logo_searx_a.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
searx/static/themes/simple/img/searx.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
searx/static/themes/simple/img/searx_logo.svg
Normal file
After Width: | Height: | Size: 7.1 KiB |
1534
searx/static/themes/simple/js/searx.js
Normal file
BIN
searx/static/themes/simple/js/searx.min.js
vendored
Normal file
BIN
searx/static/themes/simple/js/searx.min.js.map
Normal file
155
searx/static/themes/simple/js/searx_src/00_searx_toolkit.js
Normal file
@ -0,0 +1,155 @@
|
||||
/**
|
||||
* searx is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* searx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
|
||||
*
|
||||
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
|
||||
*
|
||||
*/
|
||||
(function(w, d, searx) {
|
||||
|
||||
'use strict';
|
||||
|
||||
// not invented here tookit with bugs fixed elsewhere
|
||||
// purposes : be just good enough and as small as possible
|
||||
|
||||
// from https://plainjs.com/javascript/events/live-binding-event-handlers-14/
|
||||
if (w.Element) {
|
||||
(function(ElementPrototype) {
|
||||
ElementPrototype.matches = ElementPrototype.matches ||
|
||||
ElementPrototype.matchesSelector ||
|
||||
ElementPrototype.webkitMatchesSelector ||
|
||||
ElementPrototype.msMatchesSelector ||
|
||||
function(selector) {
|
||||
var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
|
||||
while (nodes[++i] && nodes[i] != node);
|
||||
return !!nodes[i];
|
||||
};
|
||||
})(Element.prototype);
|
||||
}
|
||||
|
||||
function callbackSafe(callback, el, e) {
|
||||
try {
|
||||
callback.call(el, e);
|
||||
} catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
}
|
||||
|
||||
searx = searx || {};
|
||||
|
||||
searx.on = function(obj, eventType, callback, useCapture) {
|
||||
useCapture = useCapture || false;
|
||||
if (typeof obj !== 'string') {
|
||||
// obj HTMLElement, HTMLDocument
|
||||
obj.addEventListener(eventType, callback, useCapture);
|
||||
} else {
|
||||
// obj is a selector
|
||||
d.addEventListener(eventType, function(e) {
|
||||
var el = e.target || e.srcElement, found = false;
|
||||
while (el && el.matches && el !== d && !(found = el.matches(obj))) el = el.parentElement;
|
||||
if (found) callbackSafe(callback, el, e);
|
||||
}, useCapture);
|
||||
}
|
||||
};
|
||||
|
||||
searx.ready = function(callback) {
|
||||
if (document.readyState != 'loading') {
|
||||
callback.call(w);
|
||||
} else {
|
||||
w.addEventListener('DOMContentLoaded', callback.bind(w));
|
||||
}
|
||||
};
|
||||
|
||||
searx.http = function(method, url, callback) {
|
||||
var req = new XMLHttpRequest(),
|
||||
resolve = function() {},
|
||||
reject = function() {},
|
||||
promise = {
|
||||
then: function(callback) { resolve = callback; return promise; },
|
||||
catch: function(callback) { reject = callback; return promise; }
|
||||
};
|
||||
|
||||
try {
|
||||
req.open(method, url, true);
|
||||
|
||||
// On load
|
||||
req.onload = function() {
|
||||
if (req.status == 200) {
|
||||
resolve(req.response, req.responseType);
|
||||
} else {
|
||||
reject(Error(req.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
// Handle network errors
|
||||
req.onerror = function() {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
req.onabort = function() {
|
||||
reject(Error("Transaction is aborted"));
|
||||
};
|
||||
|
||||
// Make the request
|
||||
req.send();
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
searx.loadStyle = function(src) {
|
||||
var path = searx.staticPath + src,
|
||||
id = "style_" + src.replace('.', '_'),
|
||||
s = d.getElementById(id);
|
||||
if (s === null) {
|
||||
s = d.createElement('link');
|
||||
s.setAttribute('id', id);
|
||||
s.setAttribute('rel', 'stylesheet');
|
||||
s.setAttribute('type', 'text/css');
|
||||
s.setAttribute('href', path);
|
||||
d.body.appendChild(s);
|
||||
}
|
||||
};
|
||||
|
||||
searx.loadScript = function(src, callback) {
|
||||
var path = searx.staticPath + src,
|
||||
id = "script_" + src.replace('.', '_'),
|
||||
s = d.getElementById(id);
|
||||
if (s === null) {
|
||||
s = d.createElement('script');
|
||||
s.setAttribute('id', id);
|
||||
s.setAttribute('src', path);
|
||||
s.onload = callback;
|
||||
s.onerror = function() {
|
||||
s.setAttribute('error', '1');
|
||||
};
|
||||
d.body.appendChild(s);
|
||||
} else if (!s.hasAttribute('error')) {
|
||||
try {
|
||||
callback.apply(s, []);
|
||||
} catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
} else {
|
||||
console.log("callback not executed : script '" + path + "' not loaded.");
|
||||
}
|
||||
};
|
||||
|
||||
searx.on('.close', 'click', function(e) {
|
||||
var el = e.target || e.srcElement;
|
||||
this.parentNode.style.display="None";
|
||||
});
|
||||
return searx;
|
||||
})(window, document, window.searx);
|
536
searx/static/themes/simple/js/searx_src/autocomplete.js
Normal file
@ -0,0 +1,536 @@
|
||||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.AutoComplete = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
/*
|
||||
* @license MIT
|
||||
*
|
||||
* Autocomplete.js v2.6.3
|
||||
* Developed by Baptiste Donaux
|
||||
* http://autocomplete-js.com
|
||||
*
|
||||
* (c) 2017, Baptiste Donaux
|
||||
*/
|
||||
"use strict";
|
||||
var ConditionOperator;
|
||||
(function (ConditionOperator) {
|
||||
ConditionOperator[ConditionOperator["AND"] = 0] = "AND";
|
||||
ConditionOperator[ConditionOperator["OR"] = 1] = "OR";
|
||||
})(ConditionOperator || (ConditionOperator = {}));
|
||||
var EventType;
|
||||
(function (EventType) {
|
||||
EventType[EventType["KEYDOWN"] = 0] = "KEYDOWN";
|
||||
EventType[EventType["KEYUP"] = 1] = "KEYUP";
|
||||
})(EventType || (EventType = {}));
|
||||
/**
|
||||
* Core
|
||||
*
|
||||
* @class
|
||||
* @author Baptiste Donaux <baptiste.donaux@gmail.com> @baptistedonaux
|
||||
*/
|
||||
var AutoComplete = (function () {
|
||||
// Constructor
|
||||
function AutoComplete(params, selector) {
|
||||
if (params === void 0) { params = {}; }
|
||||
if (selector === void 0) { selector = "[data-autocomplete]"; }
|
||||
if (Array.isArray(selector)) {
|
||||
selector.forEach(function (s) {
|
||||
new AutoComplete(params, s);
|
||||
});
|
||||
}
|
||||
else if (typeof selector == "string") {
|
||||
var elements = document.querySelectorAll(selector);
|
||||
Array.prototype.forEach.call(elements, function (input) {
|
||||
new AutoComplete(params, input);
|
||||
});
|
||||
}
|
||||
else {
|
||||
var specificParams = AutoComplete.merge(AutoComplete.defaults, params, {
|
||||
DOMResults: document.createElement("div")
|
||||
});
|
||||
AutoComplete.prototype.create(specificParams, selector);
|
||||
return specificParams;
|
||||
}
|
||||
}
|
||||
AutoComplete.prototype.create = function (params, element) {
|
||||
params.Input = element;
|
||||
if (params.Input.nodeName.match(/^INPUT$/i) && (params.Input.hasAttribute("type") === false || params.Input.getAttribute("type").match(/^TEXT|SEARCH$/i))) {
|
||||
params.Input.setAttribute("autocomplete", "off");
|
||||
params._Position(params);
|
||||
params.Input.parentNode.appendChild(params.DOMResults);
|
||||
params.$Listeners = {
|
||||
blur: params._Blur.bind(params),
|
||||
destroy: AutoComplete.prototype.destroy.bind(null, params),
|
||||
focus: params._Focus.bind(params),
|
||||
keyup: AutoComplete.prototype.event.bind(null, params, EventType.KEYUP),
|
||||
keydown: AutoComplete.prototype.event.bind(null, params, EventType.KEYDOWN),
|
||||
position: params._Position.bind(params)
|
||||
};
|
||||
for (var event in params.$Listeners) {
|
||||
params.Input.addEventListener(event, params.$Listeners[event]);
|
||||
}
|
||||
}
|
||||
};
|
||||
AutoComplete.prototype.getEventsByType = function (params, type) {
|
||||
var mappings = {};
|
||||
for (var key in params.KeyboardMappings) {
|
||||
var event = EventType.KEYUP;
|
||||
if (params.KeyboardMappings[key].Event !== undefined) {
|
||||
event = params.KeyboardMappings[key].Event;
|
||||
}
|
||||
if (event == type) {
|
||||
mappings[key] = params.KeyboardMappings[key];
|
||||
}
|
||||
}
|
||||
return mappings;
|
||||
};
|
||||
AutoComplete.prototype.event = function (params, type, event) {
|
||||
var eventIdentifier = function (condition) {
|
||||
if ((match === true && mapping.Operator == ConditionOperator.AND) || (match === false && mapping.Operator == ConditionOperator.OR)) {
|
||||
condition = AutoComplete.merge({
|
||||
Not: false
|
||||
}, condition);
|
||||
if (condition.hasOwnProperty("Is")) {
|
||||
if (condition.Is == event.keyCode) {
|
||||
match = !condition.Not;
|
||||
}
|
||||
else {
|
||||
match = condition.Not;
|
||||
}
|
||||
}
|
||||
else if (condition.hasOwnProperty("From") && condition.hasOwnProperty("To")) {
|
||||
if (event.keyCode >= condition.From && event.keyCode <= condition.To) {
|
||||
match = !condition.Not;
|
||||
}
|
||||
else {
|
||||
match = condition.Not;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
for (var name in AutoComplete.prototype.getEventsByType(params, type)) {
|
||||
var mapping = AutoComplete.merge({
|
||||
Operator: ConditionOperator.AND
|
||||
}, params.KeyboardMappings[name]), match = ConditionOperator.AND == mapping.Operator;
|
||||
mapping.Conditions.forEach(eventIdentifier);
|
||||
if (match === true) {
|
||||
mapping.Callback.call(params, event);
|
||||
}
|
||||
}
|
||||
};
|
||||
AutoComplete.prototype.makeRequest = function (params, callback) {
|
||||
var propertyHttpHeaders = Object.getOwnPropertyNames(params.HttpHeaders), request = new XMLHttpRequest(), method = params._HttpMethod(), url = params._Url(), queryParams = params._Pre(), queryParamsStringify = encodeURIComponent(params._QueryArg()) + "=" + encodeURIComponent(queryParams);
|
||||
if (method.match(/^GET$/i)) {
|
||||
if (url.indexOf("?") !== -1) {
|
||||
url += "&" + queryParamsStringify;
|
||||
}
|
||||
else {
|
||||
url += "?" + queryParamsStringify;
|
||||
}
|
||||
}
|
||||
request.open(method, url, true);
|
||||
for (var i = propertyHttpHeaders.length - 1; i >= 0; i--) {
|
||||
request.setRequestHeader(propertyHttpHeaders[i], params.HttpHeaders[propertyHttpHeaders[i]]);
|
||||
}
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState == 4 && request.status == 200) {
|
||||
params.$Cache[queryParams] = request.response;
|
||||
callback(request.response);
|
||||
}
|
||||
};
|
||||
return request;
|
||||
};
|
||||
AutoComplete.prototype.ajax = function (params, request, timeout) {
|
||||
if (timeout === void 0) { timeout = true; }
|
||||
if (params.$AjaxTimer) {
|
||||
window.clearTimeout(params.$AjaxTimer);
|
||||
}
|
||||
if (timeout === true) {
|
||||
params.$AjaxTimer = window.setTimeout(AutoComplete.prototype.ajax.bind(null, params, request, false), params.Delay);
|
||||
}
|
||||
else {
|
||||
if (params.Request) {
|
||||
params.Request.abort();
|
||||
}
|
||||
params.Request = request;
|
||||
params.Request.send(params._QueryArg() + "=" + params._Pre());
|
||||
}
|
||||
};
|
||||
AutoComplete.prototype.cache = function (params, callback) {
|
||||
var response = params._Cache(params._Pre());
|
||||
if (response === undefined) {
|
||||
var request = AutoComplete.prototype.makeRequest(params, callback);
|
||||
AutoComplete.prototype.ajax(params, request);
|
||||
}
|
||||
else {
|
||||
callback(response);
|
||||
}
|
||||
};
|
||||
AutoComplete.prototype.destroy = function (params) {
|
||||
for (var event in params.$Listeners) {
|
||||
params.Input.removeEventListener(event, params.$Listeners[event]);
|
||||
}
|
||||
params.DOMResults.parentNode.removeChild(params.DOMResults);
|
||||
};
|
||||
return AutoComplete;
|
||||
}());
|
||||
AutoComplete.merge = function () {
|
||||
var merge = {}, tmp;
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
for (tmp in arguments[i]) {
|
||||
merge[tmp] = arguments[i][tmp];
|
||||
}
|
||||
}
|
||||
return merge;
|
||||
};
|
||||
AutoComplete.defaults = {
|
||||
Delay: 150,
|
||||
EmptyMessage: "No result here",
|
||||
Highlight: {
|
||||
getRegex: function (value) {
|
||||
return new RegExp(value, "ig");
|
||||
},
|
||||
transform: function (value) {
|
||||
return "<strong>" + value + "</strong>";
|
||||
}
|
||||
},
|
||||
HttpHeaders: {
|
||||
"Content-type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
Limit: 0,
|
||||
MinChars: 0,
|
||||
HttpMethod: "GET",
|
||||
QueryArg: "q",
|
||||
Url: null,
|
||||
KeyboardMappings: {
|
||||
"Enter": {
|
||||
Conditions: [{
|
||||
Is: 13,
|
||||
Not: false
|
||||
}],
|
||||
Callback: function (event) {
|
||||
if (this.DOMResults.getAttribute("class").indexOf("open") != -1) {
|
||||
var liActive = this.DOMResults.querySelector("li.active");
|
||||
if (liActive !== null) {
|
||||
event.preventDefault();
|
||||
this._Select(liActive);
|
||||
this.DOMResults.setAttribute("class", "autocomplete");
|
||||
}
|
||||
}
|
||||
},
|
||||
Operator: ConditionOperator.AND,
|
||||
Event: EventType.KEYDOWN
|
||||
},
|
||||
"KeyUpAndDown_down": {
|
||||
Conditions: [{
|
||||
Is: 38,
|
||||
Not: false
|
||||
},
|
||||
{
|
||||
Is: 40,
|
||||
Not: false
|
||||
}],
|
||||
Callback: function (event) {
|
||||
event.preventDefault();
|
||||
},
|
||||
Operator: ConditionOperator.OR,
|
||||
Event: EventType.KEYDOWN
|
||||
},
|
||||
"KeyUpAndDown_up": {
|
||||
Conditions: [{
|
||||
Is: 38,
|
||||
Not: false
|
||||
},
|
||||
{
|
||||
Is: 40,
|
||||
Not: false
|
||||
}],
|
||||
Callback: function (event) {
|
||||
event.preventDefault();
|
||||
var first = this.DOMResults.querySelector("li:first-child:not(.locked)"), last = this.DOMResults.querySelector("li:last-child:not(.locked)"), active = this.DOMResults.querySelector("li.active");
|
||||
if (active) {
|
||||
var currentIndex = Array.prototype.indexOf.call(active.parentNode.children, active), position = currentIndex + (event.keyCode - 39), lisCount = this.DOMResults.getElementsByTagName("li").length;
|
||||
if (position < 0) {
|
||||
position = lisCount - 1;
|
||||
}
|
||||
else if (position >= lisCount) {
|
||||
position = 0;
|
||||
}
|
||||
active.classList.remove("active");
|
||||
active.parentElement.children.item(position).classList.add("active");
|
||||
}
|
||||
else if (last && event.keyCode == 38) {
|
||||
last.classList.add("active");
|
||||
}
|
||||
else if (first) {
|
||||
first.classList.add("active");
|
||||
}
|
||||
},
|
||||
Operator: ConditionOperator.OR,
|
||||
Event: EventType.KEYUP
|
||||
},
|
||||
"AlphaNum": {
|
||||
Conditions: [{
|
||||
Is: 13,
|
||||
Not: true
|
||||
}, {
|
||||
From: 35,
|
||||
To: 40,
|
||||
Not: true
|
||||
}],
|
||||
Callback: function () {
|
||||
var oldValue = this.Input.getAttribute("data-autocomplete-old-value"), currentValue = this._Pre();
|
||||
if (currentValue !== "" && currentValue.length >= this._MinChars()) {
|
||||
if (!oldValue || currentValue != oldValue) {
|
||||
this.DOMResults.setAttribute("class", "autocomplete open");
|
||||
}
|
||||
AutoComplete.prototype.cache(this, function (response) {
|
||||
this._Render(this._Post(response));
|
||||
this._Open();
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
Operator: ConditionOperator.AND,
|
||||
Event: EventType.KEYUP
|
||||
}
|
||||
},
|
||||
DOMResults: null,
|
||||
Request: null,
|
||||
Input: null,
|
||||
/**
|
||||
* Return the message when no result returns
|
||||
*/
|
||||
_EmptyMessage: function () {
|
||||
var emptyMessage = "";
|
||||
if (this.Input.hasAttribute("data-autocomplete-empty-message")) {
|
||||
emptyMessage = this.Input.getAttribute("data-autocomplete-empty-message");
|
||||
}
|
||||
else if (this.EmptyMessage !== false) {
|
||||
emptyMessage = this.EmptyMessage;
|
||||
}
|
||||
else {
|
||||
emptyMessage = "";
|
||||
}
|
||||
return emptyMessage;
|
||||
},
|
||||
/**
|
||||
* Returns the maximum number of results
|
||||
*/
|
||||
_Limit: function () {
|
||||
var limit = this.Input.getAttribute("data-autocomplete-limit");
|
||||
if (isNaN(limit) || limit === null) {
|
||||
return this.Limit;
|
||||
}
|
||||
return parseInt(limit, 10);
|
||||
},
|
||||
/**
|
||||
* Returns the minimum number of characters entered before firing ajax
|
||||
*/
|
||||
_MinChars: function () {
|
||||
var minchars = this.Input.getAttribute("data-autocomplete-minchars");
|
||||
if (isNaN(minchars) || minchars === null) {
|
||||
return this.MinChars;
|
||||
}
|
||||
return parseInt(minchars, 10);
|
||||
},
|
||||
/**
|
||||
* Apply transformation on labels response
|
||||
*/
|
||||
_Highlight: function (label) {
|
||||
return label.replace(this.Highlight.getRegex(this._Pre()), this.Highlight.transform);
|
||||
},
|
||||
/**
|
||||
* Returns the HHTP method to use
|
||||
*/
|
||||
_HttpMethod: function () {
|
||||
if (this.Input.hasAttribute("data-autocomplete-method")) {
|
||||
return this.Input.getAttribute("data-autocomplete-method");
|
||||
}
|
||||
return this.HttpMethod;
|
||||
},
|
||||
/**
|
||||
* Returns the query param to use
|
||||
*/
|
||||
_QueryArg: function () {
|
||||
if (this.Input.hasAttribute("data-autocomplete-param-name")) {
|
||||
return this.Input.getAttribute("data-autocomplete-param-name");
|
||||
}
|
||||
return this.QueryArg;
|
||||
},
|
||||
/**
|
||||
* Returns the URL to use for AJAX request
|
||||
*/
|
||||
_Url: function () {
|
||||
if (this.Input.hasAttribute("data-autocomplete")) {
|
||||
return this.Input.getAttribute("data-autocomplete");
|
||||
}
|
||||
return this.Url;
|
||||
},
|
||||
/**
|
||||
* Manage the close
|
||||
*/
|
||||
_Blur: function (now) {
|
||||
if (now === true) {
|
||||
this.DOMResults.setAttribute("class", "autocomplete");
|
||||
this.Input.setAttribute("data-autocomplete-old-value", this.Input.value);
|
||||
}
|
||||
else {
|
||||
var params = this;
|
||||
setTimeout(function () {
|
||||
params._Blur(true);
|
||||
}, 150);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Manage the cache
|
||||
*/
|
||||
_Cache: function (value) {
|
||||
return this.$Cache[value];
|
||||
},
|
||||
/**
|
||||
* Manage the open
|
||||
*/
|
||||
_Focus: function () {
|
||||
var oldValue = this.Input.getAttribute("data-autocomplete-old-value");
|
||||
if ((!oldValue || this.Input.value != oldValue) && this._MinChars() <= this.Input.value.length) {
|
||||
this.DOMResults.setAttribute("class", "autocomplete open");
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Bind all results item if one result is opened
|
||||
*/
|
||||
_Open: function () {
|
||||
var params = this;
|
||||
Array.prototype.forEach.call(this.DOMResults.getElementsByTagName("li"), function (li) {
|
||||
if (li.getAttribute("class") != "locked") {
|
||||
li.onclick = function (event) {
|
||||
params._Select(li);
|
||||
};
|
||||
li.onmouseenter = function () {
|
||||
var active = params.DOMResults.querySelector("li.active");
|
||||
if (active !== li) {
|
||||
if (active !== null) {
|
||||
active.classList.remove("active");
|
||||
}
|
||||
li.classList.add("active");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Position the results HTML element
|
||||
*/
|
||||
_Position: function () {
|
||||
this.DOMResults.setAttribute("class", "autocomplete");
|
||||
this.DOMResults.setAttribute("style", "top:" + (this.Input.offsetTop + this.Input.offsetHeight) + "px;left:" + this.Input.offsetLeft + "px;width:" + this.Input.clientWidth + "px;");
|
||||
},
|
||||
/**
|
||||
* Execute the render of results DOM element
|
||||
*/
|
||||
_Render: function (response) {
|
||||
var ul;
|
||||
if (typeof response == "string") {
|
||||
ul = this._RenderRaw(response);
|
||||
}
|
||||
else {
|
||||
ul = this._RenderResponseItems(response);
|
||||
}
|
||||
if (this.DOMResults.hasChildNodes()) {
|
||||
this.DOMResults.removeChild(this.DOMResults.childNodes[0]);
|
||||
}
|
||||
this.DOMResults.appendChild(ul);
|
||||
},
|
||||
/**
|
||||
* ResponseItems[] rendering
|
||||
*/
|
||||
_RenderResponseItems: function (response) {
|
||||
var ul = document.createElement("ul"), li = document.createElement("li"), limit = this._Limit();
|
||||
// Order
|
||||
if (limit < 0) {
|
||||
response = response.reverse();
|
||||
}
|
||||
else if (limit === 0) {
|
||||
limit = response.length;
|
||||
}
|
||||
for (var item = 0; item < Math.min(Math.abs(limit), response.length); item++) {
|
||||
li.innerHTML = response[item].Label;
|
||||
li.setAttribute("data-autocomplete-value", response[item].Value);
|
||||
ul.appendChild(li);
|
||||
li = document.createElement("li");
|
||||
}
|
||||
return ul;
|
||||
},
|
||||
/**
|
||||
* string response rendering (RAW HTML)
|
||||
*/
|
||||
_RenderRaw: function (response) {
|
||||
var ul = document.createElement("ul"), li = document.createElement("li");
|
||||
if (response.length > 0) {
|
||||
this.DOMResults.innerHTML = response;
|
||||
}
|
||||
else {
|
||||
var emptyMessage = this._EmptyMessage();
|
||||
if (emptyMessage !== "") {
|
||||
li.innerHTML = emptyMessage;
|
||||
li.setAttribute("class", "locked");
|
||||
ul.appendChild(li);
|
||||
}
|
||||
}
|
||||
return ul;
|
||||
},
|
||||
/**
|
||||
* Deal with request response
|
||||
*/
|
||||
_Post: function (response) {
|
||||
try {
|
||||
var returnResponse = [];
|
||||
//JSON return
|
||||
var json = JSON.parse(response);
|
||||
if (Object.keys(json).length === 0) {
|
||||
return "";
|
||||
}
|
||||
if (Array.isArray(json)) {
|
||||
for (var i = 0; i < Object.keys(json).length; i++) {
|
||||
returnResponse[returnResponse.length] = { "Value": json[i], "Label": this._Highlight(json[i]) };
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (var value in json) {
|
||||
returnResponse.push({
|
||||
"Value": value,
|
||||
"Label": this._Highlight(json[value])
|
||||
});
|
||||
}
|
||||
}
|
||||
return returnResponse;
|
||||
}
|
||||
catch (event) {
|
||||
//HTML return
|
||||
return response;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Return the autocomplete value to send (before request)
|
||||
*/
|
||||
_Pre: function () {
|
||||
return this.Input.value;
|
||||
},
|
||||
/**
|
||||
* Choice one result item
|
||||
*/
|
||||
_Select: function (item) {
|
||||
console.log('test test test');
|
||||
if (item.hasAttribute("data-autocomplete-value")) {
|
||||
this.Input.value = item.getAttribute("data-autocomplete-value");
|
||||
}
|
||||
else {
|
||||
this.Input.value = item.innerHTML;
|
||||
}
|
||||
this.Input.setAttribute("data-autocomplete-old-value", this.Input.value);
|
||||
},
|
||||
$AjaxTimer: null,
|
||||
$Cache: {},
|
||||
$Listeners: {}
|
||||
};
|
||||
module.exports = AutoComplete;
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
151
searx/static/themes/simple/js/searx_src/searx_imageresult.js
Normal file
@ -0,0 +1,151 @@
|
||||
/**
|
||||
*
|
||||
* 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);
|
360
searx/static/themes/simple/js/searx_src/searx_keyboard.js
Normal file
@ -0,0 +1,360 @@
|
||||
searx.ready(function() {
|
||||
|
||||
searx.on('.result', 'click', function() {
|
||||
highlightResult(this)(true);
|
||||
});
|
||||
|
||||
searx.on('.result a', 'focus', function(e) {
|
||||
var el = e.target;
|
||||
while (el !== undefined) {
|
||||
if (el.classList.contains('result')) {
|
||||
if (el.getAttribute("data-vim-selected") === null) {
|
||||
highlightResult(el)(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
}, true);
|
||||
|
||||
var vimKeys = {
|
||||
27: {
|
||||
key: 'Escape',
|
||||
fun: removeFocus,
|
||||
des: 'remove focus from the focused input',
|
||||
cat: 'Control'
|
||||
},
|
||||
73: {
|
||||
key: 'i',
|
||||
fun: searchInputFocus,
|
||||
des: 'focus on the search input',
|
||||
cat: 'Control'
|
||||
},
|
||||
66: {
|
||||
key: 'b',
|
||||
fun: scrollPage(-window.innerHeight),
|
||||
des: 'scroll one page up',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
70: {
|
||||
key: 'f',
|
||||
fun: scrollPage(window.innerHeight),
|
||||
des: 'scroll one page down',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
85: {
|
||||
key: 'u',
|
||||
fun: scrollPage(-window.innerHeight / 2),
|
||||
des: 'scroll half a page up',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
68: {
|
||||
key: 'd',
|
||||
fun: scrollPage(window.innerHeight / 2),
|
||||
des: 'scroll half a page down',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
71: {
|
||||
key: 'g',
|
||||
fun: scrollPageTo(-document.body.scrollHeight, 'top'),
|
||||
des: 'scroll to the top of the page',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
86: {
|
||||
key: 'v',
|
||||
fun: scrollPageTo(document.body.scrollHeight, 'bottom'),
|
||||
des: 'scroll to the bottom of the page',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
75: {
|
||||
key: 'k',
|
||||
fun: highlightResult('up'),
|
||||
des: 'select previous search result',
|
||||
cat: 'Results'
|
||||
},
|
||||
74: {
|
||||
key: 'j',
|
||||
fun: highlightResult('down'),
|
||||
des: 'select next search result',
|
||||
cat: 'Results'
|
||||
},
|
||||
80: {
|
||||
key: 'p',
|
||||
fun: pageButtonClick(0),
|
||||
des: 'go to previous page',
|
||||
cat: 'Results'
|
||||
},
|
||||
78: {
|
||||
key: 'n',
|
||||
fun: pageButtonClick(1),
|
||||
des: 'go to next page',
|
||||
cat: 'Results'
|
||||
},
|
||||
79: {
|
||||
key: 'o',
|
||||
fun: openResult(false),
|
||||
des: 'open search result',
|
||||
cat: 'Results'
|
||||
},
|
||||
84: {
|
||||
key: 't',
|
||||
fun: openResult(true),
|
||||
des: 'open the result in a new tab',
|
||||
cat: 'Results'
|
||||
},
|
||||
82: {
|
||||
key: 'r',
|
||||
fun: reloadPage,
|
||||
des: 'reload page from the server',
|
||||
cat: 'Control'
|
||||
},
|
||||
72: {
|
||||
key: 'h',
|
||||
fun: toggleHelp,
|
||||
des: 'toggle help window',
|
||||
cat: 'Other'
|
||||
}
|
||||
};
|
||||
|
||||
searx.on(document, "keyup", function(e) {
|
||||
// check for modifiers so we don't break browser's hotkeys
|
||||
if (vimKeys.hasOwnProperty(e.keyCode) && !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
|
||||
var tagName = e.target.tagName.toLowerCase();
|
||||
if (e.keyCode === 27) {
|
||||
if (tagName === 'input' || tagName === 'select' || tagName === 'textarea') {
|
||||
vimKeys[e.keyCode].fun();
|
||||
}
|
||||
} else {
|
||||
if (e.target === document.body || tagName === 'a' || tagName === 'button') {
|
||||
vimKeys[e.keyCode].fun();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function highlightResult(which) {
|
||||
return function(noScroll) {
|
||||
var current = document.querySelector('.result[data-vim-selected]'),
|
||||
effectiveWhich = which;
|
||||
if (current === null) {
|
||||
// no selection : choose the first one
|
||||
current = document.querySelector('.result');
|
||||
if (current === null) {
|
||||
// no first one : there are no results
|
||||
return;
|
||||
}
|
||||
// replace up/down actions by selecting first one
|
||||
if (which === "down" || which === "up") {
|
||||
effectiveWhich = current;
|
||||
}
|
||||
}
|
||||
|
||||
var next, results = document.querySelectorAll('.result');
|
||||
|
||||
if (typeof effectiveWhich !== 'string') {
|
||||
next = effectiveWhich;
|
||||
} else {
|
||||
switch (effectiveWhich) {
|
||||
case 'visible':
|
||||
var top = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
var bot = top + document.documentElement.clientHeight;
|
||||
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
next = results[i];
|
||||
var etop = next.offsetTop;
|
||||
var ebot = etop + next.clientHeight;
|
||||
|
||||
if ((ebot <= bot) && (etop > top)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'down':
|
||||
next = current.nextElementSibling;
|
||||
if (next === null) {
|
||||
next = results[0];
|
||||
}
|
||||
break;
|
||||
case 'up':
|
||||
next = current.previousElementSibling;
|
||||
if (next === null) {
|
||||
next = results[results.length - 1];
|
||||
}
|
||||
break;
|
||||
case 'bottom':
|
||||
next = results[results.length - 1];
|
||||
break;
|
||||
case 'top':
|
||||
/* falls through */
|
||||
default:
|
||||
next = results[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (next) {
|
||||
current.removeAttribute('data-vim-selected');
|
||||
next.setAttribute('data-vim-selected', 'true');
|
||||
var link = next.querySelector('h3 a') || next.querySelector('a');
|
||||
if (link !== null) {
|
||||
link.focus();
|
||||
}
|
||||
if (!noScroll) {
|
||||
scrollPageToSelected();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function reloadPage() {
|
||||
document.location.reload(true);
|
||||
}
|
||||
|
||||
function removeFocus() {
|
||||
if (document.activeElement) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
}
|
||||
|
||||
function pageButtonClick(num) {
|
||||
return function() {
|
||||
var buttons = $('div#pagination button[type="submit"]');
|
||||
if (buttons.length !== 2) {
|
||||
console.log('page navigation with this theme is not supported');
|
||||
return;
|
||||
}
|
||||
if (num >= 0 && num < buttons.length) {
|
||||
buttons[num].click();
|
||||
} else {
|
||||
console.log('pageButtonClick(): invalid argument');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function scrollPageToSelected() {
|
||||
var sel = document.querySelector('.result[data-vim-selected]');
|
||||
if (sel === null) {
|
||||
return;
|
||||
}
|
||||
var wtop = document.documentElement.scrollTop || document.body.scrollTop,
|
||||
wheight = document.documentElement.clientHeight,
|
||||
etop = sel.offsetTop,
|
||||
ebot = etop + sel.clientHeight,
|
||||
offset = 120;
|
||||
// first element ?
|
||||
if ((sel.previousElementSibling === null) && (ebot < wheight)) {
|
||||
// set to the top of page if the first element
|
||||
// is fully included in the viewport
|
||||
window.scroll(window.scrollX, 0);
|
||||
return;
|
||||
}
|
||||
if (wtop > (etop - offset)) {
|
||||
window.scroll(window.scrollX, etop - offset);
|
||||
} else {
|
||||
var wbot = wtop + wheight;
|
||||
if (wbot < (ebot + offset)) {
|
||||
window.scroll(window.scrollX, ebot - wheight + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scrollPage(amount) {
|
||||
return function() {
|
||||
window.scrollBy(0, amount);
|
||||
highlightResult('visible')();
|
||||
};
|
||||
}
|
||||
|
||||
function scrollPageTo(position, nav) {
|
||||
return function() {
|
||||
window.scrollTo(0, position);
|
||||
highlightResult(nav)();
|
||||
};
|
||||
}
|
||||
|
||||
function searchInputFocus() {
|
||||
window.scrollTo(0, 0);
|
||||
document.querySelector('#q').focus();
|
||||
}
|
||||
|
||||
function openResult(newTab) {
|
||||
return function() {
|
||||
var link = document.querySelector('.result[data-vim-selected] h3 a');
|
||||
if (link !== null) {
|
||||
var url = link.getAttribute('href');
|
||||
if (newTab) {
|
||||
window.open(url);
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function toggleHelp() {
|
||||
var helpPanel = document.querySelector('#vim-hotkeys-help');
|
||||
if (helpPanel.length) {
|
||||
helpPanel.classList.toggle('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
var categories = {};
|
||||
|
||||
for (var k in vimKeys) {
|
||||
var key = vimKeys[k];
|
||||
categories[key.cat] = categories[key.cat] || [];
|
||||
categories[key.cat].push(key);
|
||||
}
|
||||
|
||||
var sorted = Object.keys(categories).sort(function(a, b) {
|
||||
return categories[b].length - categories[a].length;
|
||||
});
|
||||
|
||||
if (sorted.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var html = '<div id="vim-hotkeys-help" class="well vim-hotkeys-help">';
|
||||
html += '<div class="container-fluid">';
|
||||
|
||||
html += '<div class="row">';
|
||||
html += '<div class="col-sm-12">';
|
||||
html += '<h3>How to navigate searx with Vim-like hotkeys</h3>';
|
||||
html += '</div>'; // col-sm-12
|
||||
html += '</div>'; // row
|
||||
|
||||
for (var i = 0; i < sorted.length; i++) {
|
||||
var cat = categories[sorted[i]];
|
||||
|
||||
var lastCategory = i === (sorted.length - 1);
|
||||
var first = i % 2 === 0;
|
||||
|
||||
if (first) {
|
||||
html += '<div class="row dflex">';
|
||||
}
|
||||
html += '<div class="col-sm-' + (first && lastCategory ? 12 : 6) + ' dflex">';
|
||||
|
||||
html += '<div class="panel panel-default iflex">';
|
||||
html += '<div class="panel-heading">' + cat[0].cat + '</div>';
|
||||
html += '<div class="panel-body">';
|
||||
html += '<ul class="list-unstyled">';
|
||||
|
||||
for (var cj in cat) {
|
||||
html += '<li><kbd>' + cat[cj].key + '</kbd> ' + cat[cj].des + '</li>';
|
||||
}
|
||||
|
||||
html += '</ul>';
|
||||
html += '</div>'; // panel-body
|
||||
html += '</div>'; // panel
|
||||
html += '</div>'; // col-sm-*
|
||||
|
||||
if (!first || lastCategory) {
|
||||
html += '</div>'; // row
|
||||
}
|
||||
}
|
||||
|
||||
html += '</div>'; // container-fluid
|
||||
html += '</div>'; // vim-hotkeys-help
|
||||
|
||||
$('body').append(html);
|
||||
}
|
||||
});
|
175
searx/static/themes/simple/js/searx_src/searx_mapresult.js
Normal file
@ -0,0 +1,175 @@
|
||||
/**
|
||||
* searx is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* searx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
|
||||
*
|
||||
* (C) 2014 by Thomas Pointhuber, <thomas.pointhuber@gmx.at>
|
||||
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
|
||||
*/
|
||||
(function (w, d, searx) {
|
||||
'use strict';
|
||||
|
||||
searx.ready(function () {
|
||||
searx.on('.searx_overpass_request', 'click', function(event) {
|
||||
// no more request
|
||||
this.classList.remove("searx_overpass_request");
|
||||
|
||||
//
|
||||
var overpass_url = "https://overpass-api.de/api/interpreter?data=";
|
||||
var query_start = overpass_url + "[out:json][timeout:25];(";
|
||||
var query_end = ");out meta;";
|
||||
|
||||
var osm_id = this.dataset.osmId;
|
||||
var osm_type = this.dataset.osmType;
|
||||
var result_table = d.querySelector("#" + this.dataset.resultTable);
|
||||
var result_table_loadicon = d.querySelector("#" + this.dataset.resultTableLoadicon);
|
||||
|
||||
// tags which can be ignored
|
||||
var osm_ignore_tags = [ "addr:city", "addr:country", "addr:housenumber", "addr:postcode", "addr:street" ];
|
||||
|
||||
if(osm_id && osm_type && result_table) {
|
||||
var query = null;
|
||||
switch(osm_type) {
|
||||
case 'node':
|
||||
query = query_start + "node(" + osm_id + ");" + query_end;
|
||||
break;
|
||||
case 'way':
|
||||
query = query_start + "way(" + osm_id + ");" + query_end;
|
||||
break;
|
||||
case 'relation':
|
||||
query = query_start + "relation(" + osm_id + ");" + query_end;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(query) {
|
||||
// console.log(query);
|
||||
searx.http( 'GET', query ).then(function(html, contentType) {
|
||||
html = JSON.parse(html);
|
||||
if(html && html.elements && html.elements[0]) {
|
||||
var element = html.elements[0];
|
||||
var newHtml = "";
|
||||
for (var row in element.tags) {
|
||||
if(element.tags.name === null || osm_ignore_tags.indexOf(row) == -1) {
|
||||
newHtml += "<tr><td>" + row + "</td><td>";
|
||||
switch(row) {
|
||||
case "phone":
|
||||
case "fax":
|
||||
newHtml += "<a href=\"tel:" + element.tags[row].replace(/ /g,'') + "\">" + element.tags[row] + "</a>";
|
||||
break;
|
||||
case "email":
|
||||
newHtml += "<a href=\"mailto:" + element.tags[row] + "\">" + element.tags[row] + "</a>";
|
||||
break;
|
||||
case "website":
|
||||
case "url":
|
||||
newHtml += "<a href=\"" + element.tags[row] + "\">" + element.tags[row] + "</a>";
|
||||
break;
|
||||
case "wikidata":
|
||||
newHtml += "<a href=\"https://www.wikidata.org/wiki/" + element.tags[row] + "\">" + element.tags[row] + "</a>";
|
||||
break;
|
||||
case "wikipedia":
|
||||
if(element.tags[row].indexOf(":") != -1) {
|
||||
newHtml += "<a href=\"https://" + element.tags[row].substring(0,element.tags[row].indexOf(":")) + ".wikipedia.org/wiki/" + element.tags[row].substring(element.tags[row].indexOf(":")+1) + "\">" + element.tags[row] + "</a>";
|
||||
break;
|
||||
}
|
||||
/* jshint ignore:start */
|
||||
default:
|
||||
/* jshint ignore:end */
|
||||
newHtml += element.tags[row];
|
||||
break;
|
||||
}
|
||||
newHtml += "</td></tr>";
|
||||
}
|
||||
}
|
||||
result_table_loadicon.classList.add('invisible');
|
||||
result_table.classList.remove('invisible');
|
||||
result_table.querySelector("tbody").innerHTML = newHtml;
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
result_table_loadicon.innerHTML = result_table_loadicon.innerHTML + "<p class=\"text-muted\">could not load data!</p>";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// this event occour only once per element
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
searx.on('.searx_init_map', 'click', function(event) {
|
||||
// no more request
|
||||
this.classList.remove("searx_init_map");
|
||||
|
||||
//
|
||||
var leaflet_target = this.dataset.leafletTarget;
|
||||
var map_lon = parseFloat(this.dataset.mapLon);
|
||||
var map_lat = parseFloat(this.dataset.mapLat);
|
||||
var map_zoom = parseFloat(this.dataset.mapZoom);
|
||||
var map_boundingbox = JSON.parse(this.dataset.mapBoundingbox);
|
||||
var map_geojson = JSON.parse(this.dataset.mapGeojson);
|
||||
|
||||
searx.loadStyle('leaflet/leaflet.css');
|
||||
searx.loadScript('leaflet/leaflet.js', function() {
|
||||
var map_bounds = null;
|
||||
if(map_boundingbox) {
|
||||
var southWest = L.latLng(map_boundingbox[0], map_boundingbox[2]);
|
||||
var northEast = L.latLng(map_boundingbox[1], map_boundingbox[3]);
|
||||
map_bounds = L.latLngBounds(southWest, northEast);
|
||||
}
|
||||
|
||||
// init map
|
||||
var map = L.map(leaflet_target);
|
||||
// create the tile layer with correct attribution
|
||||
var osmMapnikUrl='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||
var osmMapnikAttrib='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
|
||||
var osmMapnik = new L.TileLayer(osmMapnikUrl, {minZoom: 1, maxZoom: 19, attribution: osmMapnikAttrib});
|
||||
var osmWikimediaUrl='https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png';
|
||||
var osmWikimediaAttrib = 'Wikimedia maps beta | Maps data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
|
||||
var osmWikimedia = new L.TileLayer(osmWikimediaUrl, {minZoom: 1, maxZoom: 19, attribution: osmWikimediaAttrib});
|
||||
// init map view
|
||||
if(map_bounds) {
|
||||
// TODO hack: https://github.com/Leaflet/Leaflet/issues/2021
|
||||
// Still useful ?
|
||||
setTimeout(function () {
|
||||
map.fitBounds(map_bounds, {
|
||||
maxZoom:17
|
||||
});
|
||||
}, 0);
|
||||
} else if (map_lon && map_lat) {
|
||||
if(map_zoom) {
|
||||
map.setView(new L.latLng(map_lat, map_lon),map_zoom);
|
||||
} else {
|
||||
map.setView(new L.latLng(map_lat, map_lon),8);
|
||||
}
|
||||
}
|
||||
|
||||
map.addLayer(osmMapnik);
|
||||
|
||||
var baseLayers = {
|
||||
"OSM Mapnik": osmMapnik/*,
|
||||
"OSM Wikimedia": osmWikimedia*/
|
||||
};
|
||||
|
||||
L.control.layers(baseLayers).addTo(map);
|
||||
|
||||
if(map_geojson) {
|
||||
L.geoJson(map_geojson).addTo(map);
|
||||
} /*else if(map_bounds) {
|
||||
L.rectangle(map_bounds, {color: "#ff7800", weight: 3, fill:false}).addTo(map);
|
||||
}*/
|
||||
});
|
||||
|
||||
// this event occour only once per element
|
||||
event.preventDefault();
|
||||
});
|
||||
});
|
||||
})(window, document, window.searx);
|
63
searx/static/themes/simple/js/searx_src/searx_results.js
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* searx is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* searx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
|
||||
*
|
||||
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
|
||||
*/
|
||||
(function(w, d, searx) {
|
||||
'use strict';
|
||||
|
||||
searx.ready(function() {
|
||||
searx.image_thumbnail_layout = new searx.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 200);
|
||||
searx.image_thumbnail_layout.watch();
|
||||
|
||||
searx.on('.btn-collapse', 'click', function(event) {
|
||||
var btnLabelCollapsed = this.getAttribute('data-btn-text-collapsed');
|
||||
var btnLabelNotCollapsed = this.getAttribute('data-btn-text-not-collapsed');
|
||||
var target = this.getAttribute('data-target');
|
||||
var targetElement = d.querySelector(target);
|
||||
var html = this.innerHTML;
|
||||
if (this.classList.contains('collapsed')) {
|
||||
html = html.replace(btnLabelCollapsed, btnLabelNotCollapsed);
|
||||
} else {
|
||||
html = html.replace(btnLabelNotCollapsed, btnLabelCollapsed);
|
||||
}
|
||||
this.innerHTML = html;
|
||||
this.classList.toggle('collapsed');
|
||||
targetElement.classList.toggle('invisible');
|
||||
});
|
||||
|
||||
searx.on('.media-loader', 'click', function(event) {
|
||||
var target = this.getAttribute('data-target');
|
||||
var iframe_load = d.querySelector(target + ' > iframe');
|
||||
var srctest = iframe_load.getAttribute('src');
|
||||
if (srctest === null || srctest === undefined || srctest === false) {
|
||||
iframe_load.setAttribute('src', iframe_load.getAttribute('data-src'));
|
||||
}
|
||||
});
|
||||
|
||||
w.addEventListener('scroll', function() {
|
||||
var e = d.getElementById('backToTop'),
|
||||
scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
if (e !== null) {
|
||||
if (scrollTop >= 200) {
|
||||
e.style.opacity = 1;
|
||||
} else {
|
||||
e.style.opacity = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})(window, document, window.searx);
|
94
searx/static/themes/simple/js/searx_src/searx_search.js
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* searx is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* searx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
|
||||
*
|
||||
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
|
||||
*/
|
||||
(function(w, d, searx) {
|
||||
'use strict';
|
||||
|
||||
var firstFocus = true, qinput_id = "q", qinput;
|
||||
|
||||
function placeCursorAtEnd(element) {
|
||||
if (element.setSelectionRange) {
|
||||
var len = element.value.length;
|
||||
element.setSelectionRange(len, len);
|
||||
}
|
||||
}
|
||||
|
||||
function submitIfQuery() {
|
||||
if (qinput.value.length > 0) {
|
||||
var search = document.getElementById('search');
|
||||
setTimeout(search.submit.bind(search), 0);
|
||||
}
|
||||
}
|
||||
|
||||
searx.ready(function() {
|
||||
qinput = d.getElementById(qinput_id);
|
||||
|
||||
function placeCursorAtEndOnce(e) {
|
||||
if (firstFocus) {
|
||||
placeCursorAtEnd(qinput);
|
||||
firstFocus = false;
|
||||
} else {
|
||||
// e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
if (qinput !== null) {
|
||||
// autocompleter
|
||||
if (searx.autocompleter) {
|
||||
searx.autocomplete = AutoComplete.call(w, {
|
||||
Url: "./autocompleter",
|
||||
EmptyMessage: searx.noItemFound,
|
||||
HttpMethod: searx.method,
|
||||
MinChars: 4,
|
||||
Delay: 300,
|
||||
}, "#" + qinput_id);
|
||||
|
||||
// hack, see : https://github.com/autocompletejs/autocomplete.js/issues/37
|
||||
w.addEventListener('resize', function() {
|
||||
var event = new CustomEvent("position");
|
||||
qinput.dispatchEvent(event);
|
||||
});
|
||||
}
|
||||
|
||||
qinput.addEventListener('focus', placeCursorAtEndOnce, false);
|
||||
qinput.focus();
|
||||
}
|
||||
|
||||
// vanilla js version of search_on_category_select.js
|
||||
if (qinput !== null && searx.search_on_category_select) {
|
||||
d.querySelector('.help').className='invisible';
|
||||
|
||||
searx.on('#categories input', 'change', function(e) {
|
||||
var i, categories = d.querySelectorAll('#categories input[type="checkbox"]');
|
||||
for(i=0; i<categories.length; i++) {
|
||||
if (categories[i] !== this && categories[i].checked) {
|
||||
categories[i].click();
|
||||
}
|
||||
}
|
||||
if (! this.checked) {
|
||||
this.click();
|
||||
}
|
||||
submitIfQuery();
|
||||
return false;
|
||||
});
|
||||
|
||||
searx.on(d.getElementById('time_range'), 'change', submitIfQuery);
|
||||
searx.on(d.getElementById('language'), 'change', submitIfQuery);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(window, document, window.searx);
|
BIN
searx/static/themes/simple/leaflet/images/layers-2x.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
searx/static/themes/simple/leaflet/images/layers.png
Normal file
After Width: | Height: | Size: 696 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.6 KiB |
BIN
searx/static/themes/simple/leaflet/images/marker-icon-2x-red.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
searx/static/themes/simple/leaflet/images/marker-icon-2x.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
searx/static/themes/simple/leaflet/images/marker-icon-green.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
searx/static/themes/simple/leaflet/images/marker-icon-orange.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
searx/static/themes/simple/leaflet/images/marker-icon-red.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
searx/static/themes/simple/leaflet/images/marker-icon.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
searx/static/themes/simple/leaflet/images/marker-shadow.png
Normal file
After Width: | Height: | Size: 618 B |
BIN
searx/static/themes/simple/leaflet/leaflet.css
Normal file
BIN
searx/static/themes/simple/leaflet/leaflet.js
Normal file
67
searx/static/themes/simple/less/autocomplete.less
Normal file
@ -0,0 +1,67 @@
|
||||
@background_color: white;
|
||||
|
||||
.autocomplete {
|
||||
position: absolute;
|
||||
max-height: 0;
|
||||
overflow-y: hidden;
|
||||
text-align: left;
|
||||
|
||||
&:active, &:focus, &:hover {
|
||||
background-color: @background_color;
|
||||
}
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
> li {
|
||||
cursor: pointer;
|
||||
padding: 5px 0 5px 10px;
|
||||
|
||||
&.active, &:active, &:focus {
|
||||
background-color: @color-base;
|
||||
|
||||
a:active, a:focus, a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.locked {
|
||||
cursor: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.open {
|
||||
display: block;
|
||||
background-color: @background_color;
|
||||
border: 1px solid @color-base;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
z-index:100;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: @results-width) {
|
||||
|
||||
.autocomplete {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.autocomplete > ul > li {
|
||||
padding: 7px 0 7px 10px;
|
||||
border-bottom: 1px solid @color-result-top-border;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
}
|
83
searx/static/themes/simple/less/code.less
Normal file
@ -0,0 +1,83 @@
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight { background: #f8f8f8; }
|
||||
.highlight .c { color: #408080; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #B00040 } /* Keyword.Type */
|
||||
.highlight .m { color: #666666 } /* Literal.Number */
|
||||
.highlight .s { color: #BA2121 } /* Literal.String */
|
||||
.highlight .na { color: #7D9029 } /* Name.Attribute */
|
||||
.highlight .nb { color: #008000 } /* Name.Builtin */
|
||||
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #880000 } /* Name.Constant */
|
||||
.highlight .nd { color: #AA22FF } /* Name.Decorator */
|
||||
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #0000FF } /* Name.Function */
|
||||
.highlight .nl { color: #A0A000 } /* Name.Label */
|
||||
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #19177C } /* Name.Variable */
|
||||
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mf { color: #666666 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
|
||||
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #008000 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #19177C } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #19177C } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
|
||||
|
||||
.highlight pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.highlight .lineno {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
|
||||
&::selection {
|
||||
background: transparent; /* WebKit/Blink Browsers */
|
||||
}
|
||||
&::-moz-selection {
|
||||
background: transparent; /* Gecko Browsers */
|
||||
}
|
||||
}
|
135
searx/static/themes/simple/less/definitions.less
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*
|
||||
* To change the colors of the site, simple edit this variables
|
||||
*/
|
||||
|
||||
/// Basic Colors
|
||||
|
||||
@color-base: #3498DB;
|
||||
@color-base-dark: #084999;
|
||||
@color-base-light: #ECF0F1;
|
||||
@color-highlight: #094089;
|
||||
@color-black: #000000;
|
||||
|
||||
///
|
||||
@color-error: #db3434;
|
||||
@color-error-background: lighten(@color-error, 40%);
|
||||
|
||||
@color-warning: #dbba34;
|
||||
@color-warning-background: lighten(@color-warning, 40%);
|
||||
|
||||
/// General
|
||||
|
||||
@color-font: #444;
|
||||
@color-font-light: #888;
|
||||
|
||||
@color-red: #25a55b;
|
||||
|
||||
@color-url-font: #29314d;
|
||||
@color-url-visited-font: #684898;
|
||||
@results-width: 50em;
|
||||
@search-width: 40em;
|
||||
|
||||
//
|
||||
@color-a-font: @color-base;
|
||||
@color-a-font-hover: @color-base;
|
||||
|
||||
|
||||
/// Start-Screen
|
||||
|
||||
|
||||
|
||||
/// Search-Input
|
||||
|
||||
@color-search-border: @color-base;
|
||||
@color-search-background: #FFF;
|
||||
@color-search-font: #222;
|
||||
|
||||
/// Autocompleter
|
||||
|
||||
@color-autocompleter-choices-background: #FFF;
|
||||
@color-autocompleter-choices-border: @color-base;
|
||||
@color-autocompleter-choices-border-left-right: @color-base;
|
||||
@color-autocompleter-choices-border-bottom: @color-base;
|
||||
|
||||
@color-autocompleter-choices-font: #444;
|
||||
|
||||
/// Answers
|
||||
@color-answers-border: @color-base-dark;
|
||||
|
||||
// Selected
|
||||
@color-autocompleter-selected-background: #444;
|
||||
@color-autocompleter-selected-font: #FFF;
|
||||
@color-autocompleter-selected-queried-font: #9FCFFF;
|
||||
|
||||
/// Categories
|
||||
|
||||
@color-categories-item-selected: @color-base;
|
||||
@color-categories-item-selected-font: #FFF;
|
||||
|
||||
@color-categories-item-border-selected: @color-base-dark;
|
||||
@color-categories-item-border-unselected: #E8E7E6;
|
||||
@color-categories-item-border-unselected-hover: @color-base;
|
||||
|
||||
|
||||
/// Results
|
||||
|
||||
@color-suggestions-button-background: @color-base;
|
||||
@color-suggestions-button-font: #FFF;
|
||||
|
||||
@color-download-button-background: @color-base;
|
||||
@color-download-button-font: #FFF;
|
||||
|
||||
@color-result-search-background: @color-base-light;
|
||||
|
||||
@color-result-definition-border: gray;
|
||||
@color-result-torrent-border: lightgray;
|
||||
@color-result-top-border: #E8E7E6;
|
||||
|
||||
// Link to result
|
||||
@color-result-link-font: @color-base-dark;
|
||||
@color-result-link-visited-font: @color-url-visited-font;
|
||||
|
||||
// Url to result
|
||||
@color-result-url-font: @color-red;
|
||||
|
||||
// Publish Date
|
||||
@color-result-publishdate-font: @color-font-light;
|
||||
|
||||
// Images
|
||||
@color-result-image-span-background-hover: rgba(0, 0, 0, 0.6);
|
||||
@color-result-image-span-font: #FFF;
|
||||
|
||||
// Search-URL
|
||||
@color-result-search-url-border: #888;
|
||||
@color-result-search-url-font: #444;
|
||||
|
||||
|
||||
/// Settings
|
||||
|
||||
@color-settings-fieldset: @color-base;
|
||||
@color-settings-table-striped: #dbdbdb;
|
||||
@color-settings-tr-hover: #ececec;
|
||||
|
||||
// Labels
|
||||
@color-settings-label-allowed-background: #E74C3C;
|
||||
@color-settings-label-allowed-font: #FFF;
|
||||
|
||||
@color-settings-label-deny-background: #2ECC71;
|
||||
@color-settings-label-deny-font: @color-font;
|
||||
|
||||
@color-settings-return-background: @color-base;
|
||||
@color-settings-return-font: #FFF;
|
||||
|
||||
/// Other
|
||||
|
||||
@color-engines-font: @color-font-light;
|
||||
@color-percentage-div-background: #444;
|
||||
|
||||
/// Load fonts from this directory.
|
||||
@icon-font-path: "../../../fonts/";
|
||||
//** File name for all font files.
|
||||
@icon-font-name: "glyphicons-halflings-regular";
|
||||
//** Element ID within SVG icon file.
|
||||
@icon-font-svg-id: "glyphicons_halflingsregular";
|
43
searx/static/themes/simple/less/index.less
Normal file
@ -0,0 +1,43 @@
|
||||
.index {
|
||||
|
||||
text-align: center;
|
||||
|
||||
.title {
|
||||
background: url('../img/searx.png') no-repeat;
|
||||
width: 100%;
|
||||
min-height: 80px;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 5em;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#search {
|
||||
margin: 0 auto;
|
||||
background: inherit;
|
||||
border: inherit;
|
||||
}
|
||||
|
||||
.search_filters {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.category label {
|
||||
padding: 6px 10px;
|
||||
border-bottom: initial !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 75em) {
|
||||
|
||||
div.title {
|
||||
h1 {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
174
searx/static/themes/simple/less/ion.less
Normal file
@ -0,0 +1,174 @@
|
||||
// Generated by grunt-webfont
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family:"ion";
|
||||
src:url("../fonts/ion.eot?94af7082ea096aefe3a7b6642834716e");
|
||||
src:url("../fonts/ion.eot?#iefix") format("embedded-opentype"),
|
||||
url("../fonts/ion.woff2?94af7082ea096aefe3a7b6642834716e") format("woff2"),
|
||||
url("../fonts/ion.woff?94af7082ea096aefe3a7b6642834716e") format("woff"),
|
||||
url("../fonts/ion.ttf?94af7082ea096aefe3a7b6642834716e") format("truetype"),
|
||||
url("../fonts/ion.svg?94af7082ea096aefe3a7b6642834716e#ion") format("svg");
|
||||
font-weight:normal;
|
||||
font-style:normal;
|
||||
}
|
||||
|
||||
.ion-icon {
|
||||
&:before {
|
||||
font-family:"ion";
|
||||
}
|
||||
display:inline-block;
|
||||
vertical-align:middle;
|
||||
line-height:1;
|
||||
font-weight:normal;
|
||||
font-style:normal;
|
||||
speak:none;
|
||||
text-decoration:inherit;
|
||||
text-transform:none;
|
||||
text-rendering:auto;
|
||||
-webkit-font-smoothing:antialiased;
|
||||
-moz-osx-font-smoothing:grayscale;
|
||||
}
|
||||
|
||||
|
||||
// Icons
|
||||
|
||||
.ion-navicon-round {
|
||||
&:before {
|
||||
content:"\f101";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-search {
|
||||
&:before {
|
||||
content:"\f102";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-play {
|
||||
&:before {
|
||||
content:"\f103";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-link {
|
||||
&:before {
|
||||
content:"\f104";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-up {
|
||||
&:before {
|
||||
content:"\f105";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-left {
|
||||
&:before {
|
||||
content:"\f106";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-chevron-right {
|
||||
&:before {
|
||||
content:"\f107";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-down-a {
|
||||
&:before {
|
||||
content:"\f108";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-up-a {
|
||||
&:before {
|
||||
content:"\f109";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-swap {
|
||||
&:before {
|
||||
content:"\f10a";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-arrow-dropdown {
|
||||
&:before {
|
||||
content:"\f10b";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-globe {
|
||||
&:before {
|
||||
content:"\f10c";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-time {
|
||||
&:before {
|
||||
content:"\f10d";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-location {
|
||||
&:before {
|
||||
content:"\f10e";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-warning {
|
||||
&:before {
|
||||
content:"\f10f";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-error {
|
||||
&:before {
|
||||
content:"\f110";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-film-outline {
|
||||
&:before {
|
||||
content:"\f111";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-music-note {
|
||||
&:before {
|
||||
content:"\f112";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-more-vertical {
|
||||
&:before {
|
||||
content:"\f113";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ion-magnet {
|
||||
&:before {
|
||||
content:"\f114";
|
||||
}
|
||||
}
|
||||
|
62
searx/static/themes/simple/less/mixins.less
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*/
|
||||
|
||||
// Mixins
|
||||
.text-size-adjust (@property: 100%) {
|
||||
-webkit-text-size-adjust: @property;
|
||||
-ms-text-size-adjust: @property;
|
||||
-moz-text-size-adjust: @property;
|
||||
text-size-adjust: @property;
|
||||
}
|
||||
|
||||
.rounded-corners (@radius: 4px) {
|
||||
-webkit-border-radius: @radius;
|
||||
-moz-border-radius: @radius;
|
||||
border-radius: @radius;
|
||||
}
|
||||
|
||||
// disable user selection
|
||||
.disable-user-select () {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
// select all on focus
|
||||
.select-all-on-focus() {
|
||||
-webkit-user-select: all;
|
||||
-moz-user-select: all;
|
||||
-ms-user-select: all;
|
||||
user-select: all;
|
||||
}
|
||||
|
||||
// see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Advanced_layouts_with_flexbox
|
||||
.flexbox() {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.inline-flex() {
|
||||
display: -webkit-inline-box;
|
||||
display: -moz-inline-box;
|
||||
display: -webkit-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.flex-direction-row() {
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-box-orient: horizontal;
|
||||
-moz-box-direction: normal;
|
||||
-moz-box-orient: horizontal;
|
||||
-webkit-flex-direction: row;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
}
|
447
searx/static/themes/simple/less/normalize.less
vendored
Normal file
@ -0,0 +1,447 @@
|
||||
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in
|
||||
* IE on Windows Phone and in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers (opinionated).
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
footer,
|
||||
header,
|
||||
nav,
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in IE.
|
||||
*/
|
||||
|
||||
figcaption,
|
||||
figure,
|
||||
main { /* 1 */
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct margin in IE 8.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Remove the gray background on active links in IE 10.
|
||||
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent; /* 1 */
|
||||
-webkit-text-decoration-skip: objects; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font style in Android 4.3-.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct background and color in IE 9-.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background-color: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
audio,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in iOS 4-7.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10-.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the overflow in IE.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers (opinionated).
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: sans-serif; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
* controls in Android 4.
|
||||
* 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
html [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct display in IE 9-.
|
||||
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10-.
|
||||
* 2. Remove the padding in IE 10-.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in Edge, IE, and Firefox.
|
||||
*/
|
||||
|
||||
details, /* 1 */
|
||||
menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Scripting
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
canvas {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hidden
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10-.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
78
searx/static/themes/simple/less/preferences.less
Normal file
@ -0,0 +1,78 @@
|
||||
#main_preferences {
|
||||
form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin: 8px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
legend {
|
||||
margin: 0;
|
||||
padding: 5px 0 0 0;
|
||||
display: block;
|
||||
float:left;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.value {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
float:left;
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin: 0;
|
||||
padding: 5px 0 0 0;
|
||||
float:left;
|
||||
width: 50%;
|
||||
color: darken(#dcdcdc, 30%);
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
select {
|
||||
width: 200px;
|
||||
font-size: inherit !important;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.name, .shortcut {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.preferences_back {
|
||||
background: none repeat scroll 0 0 @color-settings-return-background;
|
||||
color: white;
|
||||
border: 0 none;
|
||||
.rounded-corners;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 2px 4px;
|
||||
padding: 0.5em;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
color: @color-settings-return-font;
|
||||
}
|
||||
|
||||
a::first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 75em) {
|
||||
.preferences_back {
|
||||
clear: both;
|
||||
}
|
||||
}
|
232
searx/static/themes/simple/less/search.less
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*/
|
||||
|
||||
#search {
|
||||
padding: 0 2em;
|
||||
margin: 0;
|
||||
background: #f7f7f7;
|
||||
border-bottom: 1px solid #d7d7d7;
|
||||
}
|
||||
|
||||
#search_wrapper {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.search_box {
|
||||
margin: 0 12px 0 0;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
|
||||
white-space: nowrap;
|
||||
/*
|
||||
&:has(q:focus) {
|
||||
box-shadow: 0px 0px 5px #CCC;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#q, #send_search {
|
||||
display: block !important;
|
||||
border-collapse: separate;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
height: 2.2em;
|
||||
background: none repeat scroll 0 0 @color-search-background;
|
||||
border: 1px solid @color-search-border;
|
||||
border-radius: 0px;
|
||||
outline: none;
|
||||
color: @color-search-font;
|
||||
font-size: 16px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#q {
|
||||
outline: medium none;
|
||||
padding-left: 8px;
|
||||
padding-right: 0px !important;
|
||||
border-right: none;
|
||||
width: @search-width;
|
||||
}
|
||||
|
||||
#send_search {
|
||||
border-left: none;
|
||||
width: 2.2em;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: @color-search-border;
|
||||
color: @color-base-light;
|
||||
}
|
||||
}
|
||||
|
||||
.no-js #send_search {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.search_filters {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 75em) {
|
||||
|
||||
#categories {
|
||||
font-size: 90%;
|
||||
clear: both;
|
||||
|
||||
.checkbox_container {
|
||||
margin-top: 2px;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
html.touch {
|
||||
#main_index, #main_results {
|
||||
|
||||
#categories_container {
|
||||
width: 1000px;
|
||||
width: -moz-max-content;
|
||||
width: -webkit-max-content;
|
||||
width: max-content;
|
||||
|
||||
.category {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
#categories {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: @results-width) {
|
||||
|
||||
#search {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0.1em 0 0 0;
|
||||
}
|
||||
|
||||
#search_wrapper {
|
||||
width: 100%;
|
||||
margin: 0 0 0.7em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.search_box {
|
||||
// hack, should bew 100% ?
|
||||
width: 99%;
|
||||
margin: 0.1em;
|
||||
padding: 0 0.1em 0 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#q {
|
||||
width: auto !important;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search_filters {
|
||||
display: block;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
.language, .time_range {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.category {
|
||||
display: block;
|
||||
width: 90%;
|
||||
|
||||
label {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#categories {
|
||||
margin: 0 10px 0 0;
|
||||
.disable-user-select;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.category {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 0 3px;
|
||||
padding: 0px;
|
||||
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
padding: 4px 10px;
|
||||
margin: 0;
|
||||
display: block;
|
||||
text-transform: capitalize;
|
||||
font-size: 0.9em;
|
||||
border-bottom: 2px solid transparent;
|
||||
.disable-user-select;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:focus + label {
|
||||
box-shadow: 0px 0px 8px #3498DB;
|
||||
}
|
||||
|
||||
/*label:hover {
|
||||
border-bottom: 2px solid @color-categories-item-border-unselected-hover;
|
||||
}*/
|
||||
|
||||
input[type="checkbox"]:checked + label {
|
||||
background: @color-categories-item-selected;
|
||||
color: @color-categories-item-selected-font;
|
||||
border-bottom: 2px solid @color-categories-item-border-selected;
|
||||
}
|
||||
}
|
||||
|
||||
#categories_container {
|
||||
|
||||
position: relative;
|
||||
|
||||
.help {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: -20px;
|
||||
overflow: hidden;
|
||||
|
||||
opacity: 0;
|
||||
transition: opacity 1s ease;
|
||||
|
||||
font-size: 0.8em;
|
||||
text-position: center;
|
||||
background: white;
|
||||
}
|
||||
|
||||
&:hover .help {
|
||||
opacity: 0.8;
|
||||
transition: opacity 1s ease;
|
||||
}
|
||||
|
||||
}
|
8
searx/static/themes/simple/less/stats.less
Normal file
@ -0,0 +1,8 @@
|
||||
.percentage {
|
||||
position: relative;
|
||||
width: 300px;
|
||||
|
||||
div {
|
||||
background: @color-percentage-div-background;
|
||||
}
|
||||
}
|
6
searx/static/themes/simple/less/style-rtl.less
Normal file
@ -0,0 +1,6 @@
|
||||
@import "style.less";
|
||||
|
||||
#search_submit {
|
||||
left: 1px;
|
||||
right:auto;
|
||||
}
|
709
searx/static/themes/simple/less/style.less
Normal file
@ -0,0 +1,709 @@
|
||||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*
|
||||
* To convert "style.less" to "style.css" run: $make styles
|
||||
*/
|
||||
|
||||
@import "normalize.less";
|
||||
|
||||
@import "definitions.less";
|
||||
|
||||
@import "mixins.less";
|
||||
|
||||
@import "code.less";
|
||||
|
||||
@import "toolkit.less";
|
||||
|
||||
@import "autocomplete.less";
|
||||
|
||||
// ion-icon
|
||||
@import "ion.less";
|
||||
|
||||
.ion-icon-big {
|
||||
.ion-icon;
|
||||
font-size: 149%;
|
||||
}
|
||||
|
||||
// for index.html template
|
||||
@import "index.less";
|
||||
|
||||
// for preferences.html template
|
||||
@import "preferences.less";
|
||||
|
||||
// Search-Field
|
||||
@import "search.less";
|
||||
|
||||
// Main LESS-Code
|
||||
html {
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 0.9em;
|
||||
.text-size-adjust;
|
||||
color: @color-font;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body, main {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
width: 100%;
|
||||
// position: absolute;
|
||||
}
|
||||
|
||||
footer {
|
||||
// position:absolute;
|
||||
bottom:0;
|
||||
width:100%;
|
||||
height:50px;
|
||||
}
|
||||
|
||||
#main_preferences, #main_about, #main_stats {
|
||||
margin: 3em;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
footer {
|
||||
bottom: 0;
|
||||
height: 3em;
|
||||
margin: 1em 0;
|
||||
padding: 1em 0;
|
||||
clear: both;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
|
||||
p {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
||||
#main_preferences h1, #main_stats h1 {
|
||||
background: url('../img/searx.png') no-repeat;
|
||||
background-size: auto 75%;
|
||||
min-height: 40px;
|
||||
margin: 0 auto;
|
||||
|
||||
span {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="submit"], #results button[type="submit"] {
|
||||
padding: 0.5rem;
|
||||
margin: 2px 4px;
|
||||
display: inline-block;
|
||||
background: @color-download-button-background;
|
||||
color: @color-download-button-font;
|
||||
.rounded-corners;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: @color-url-font;
|
||||
|
||||
&:visited {
|
||||
color: @color-url-visited-font;
|
||||
|
||||
.highlight {
|
||||
color: @color-url-visited-font;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
article[data-vim-selected] {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
|
||||
article[data-vim-selected]::before {
|
||||
position: absolute;
|
||||
left: 1em;
|
||||
padding: 2px;
|
||||
content: ">";
|
||||
font-weight: bold;
|
||||
color: @color-base;
|
||||
}
|
||||
|
||||
article.result-images[data-vim-selected] {
|
||||
background: @color-base;
|
||||
}
|
||||
|
||||
article.result-images[data-vim-selected]::before {
|
||||
display: none;
|
||||
content: "";
|
||||
}
|
||||
|
||||
.result {
|
||||
margin: 19px 0 18px 0;
|
||||
padding: 0;
|
||||
|
||||
h3 {
|
||||
font-size: 1.1em;
|
||||
word-wrap:break-word;
|
||||
margin: 5px 0 1px 0;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
a {
|
||||
color: @color-result-link-font;
|
||||
font-weight: normal;
|
||||
font-size: 1.1em;
|
||||
|
||||
&:visited {
|
||||
color: @color-result-link-visited-font;
|
||||
}
|
||||
|
||||
&:focus, &:hover {
|
||||
text-decoration: underline;
|
||||
border: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
outline:none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cache_link, .proxyfied_link {
|
||||
font-size: 0.9em !important;
|
||||
}
|
||||
|
||||
.content, .stat, .altlink {
|
||||
font-size: 0.9em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-width: 54em;
|
||||
word-wrap:break-word;
|
||||
line-height: 1.24;
|
||||
|
||||
.highlight {
|
||||
color: @color-black;
|
||||
background: inherit;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.codelines {
|
||||
.highlight {
|
||||
color: inherit;
|
||||
background: inherit;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.url {
|
||||
font-size: 0.9em;
|
||||
margin: 0 0 3px 0;
|
||||
padding: 0;
|
||||
max-width: 54em;
|
||||
word-wrap:break-word;
|
||||
color: @color-result-url-font;
|
||||
}
|
||||
|
||||
.published_date {
|
||||
font-size: 0.8em;
|
||||
color: @color-result-publishdate-font;
|
||||
}
|
||||
|
||||
img {
|
||||
|
||||
&.thumbnail {
|
||||
float: left;
|
||||
padding: 0 5px 10px 0;
|
||||
width: 20em;
|
||||
min-width: 20em;
|
||||
min-height: 8em;
|
||||
// background: @color-base-light;
|
||||
}
|
||||
|
||||
&.image {
|
||||
float: left;
|
||||
padding: 0 5px 10px 0;
|
||||
width: 100px;
|
||||
max-height: 100px;
|
||||
object-fit: scale-down;
|
||||
object-position: right top;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.break {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.category-social .image {
|
||||
width: auto !important;
|
||||
min-width: 48px;
|
||||
min-height: 48px;
|
||||
padding: 0 5px 25px 0 !important;
|
||||
}
|
||||
|
||||
.result-videos .content {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.engines {
|
||||
float: right;
|
||||
color: @color-engines-font;
|
||||
|
||||
span {
|
||||
font-size: smaller;
|
||||
margin: 0 0.5em 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.small_font {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: @color-highlight;
|
||||
background: inherit;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.result-images {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
max-height: 200px;
|
||||
|
||||
img {
|
||||
float: inherit;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
max-height: 200px;
|
||||
background: @color-base-dark;
|
||||
}
|
||||
|
||||
span a {
|
||||
display: none;
|
||||
color: @color-result-image-span-font;
|
||||
}
|
||||
|
||||
&:hover span a {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 4px;
|
||||
margin: 0 0 4px 4px;
|
||||
background-color: @color-result-image-span-background-hover;
|
||||
font-size: 0.7em;
|
||||
}
|
||||
}
|
||||
|
||||
.torrent_result {
|
||||
border-left: 10px solid @color-result-torrent-border;
|
||||
padding-left: 3px;
|
||||
|
||||
p {
|
||||
margin: 3px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: @color-result-link-font;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: @color-result-link-visited-font;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#results {
|
||||
margin: 2em 2em 20px 2em;
|
||||
padding: 0;
|
||||
width: @results-width;
|
||||
}
|
||||
|
||||
#suggestions {
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: flex-end;
|
||||
|
||||
form {
|
||||
display: inline-block;
|
||||
flex: 1 1 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#suggestions, #answers, #corrections {
|
||||
max-width: @results-width;
|
||||
}
|
||||
|
||||
#suggestions, #answers, #infoboxes, #corrections {
|
||||
|
||||
input {
|
||||
padding: 0;
|
||||
margin: 3px;
|
||||
font-size: 0.9em;
|
||||
display: inline-block;
|
||||
background: transparent;
|
||||
color: @color-result-search-url-font;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="submit"], .infobox .url a {
|
||||
color: @color-result-link-font;
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#corrections {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
margin: 1em 0;
|
||||
|
||||
h4, input[type="submit"] {
|
||||
display: inline-block;
|
||||
margin: 0 0.5em 0 0;
|
||||
}
|
||||
|
||||
input[type="submit"]::after {
|
||||
content: ", "
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#suggestions .title, #search_url .title, #apis .title {
|
||||
margin: 2em 0 0.5em 0;
|
||||
color: @color-font;
|
||||
}
|
||||
|
||||
#answers {
|
||||
margin: 10px 8px 10px 8px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 0.9em;
|
||||
box-shadow: 0px 0px 5px #CCC;
|
||||
|
||||
h4 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.answer {
|
||||
display: block;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
#answers, #infoboxes {
|
||||
form {
|
||||
min-width: 210px;
|
||||
}
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 57em;
|
||||
|
||||
margin: 0px 2px 5px 5px;
|
||||
padding: 0px 2px 2px;
|
||||
max-width: 25em;
|
||||
word-wrap: break-word;
|
||||
|
||||
.infobox {
|
||||
margin: 10px 0 10px;
|
||||
border: 1px solid #ddd;
|
||||
padding: 0.9em;
|
||||
font-size: 0.9em;
|
||||
box-shadow: 0px 0px 5px #CCC;
|
||||
|
||||
h2 {
|
||||
margin: 0 0 .5em 0;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 12em;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
display: inline;
|
||||
margin: 0.5em 0.25em 0.5em 0;
|
||||
padding: 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dd {
|
||||
display: inline;
|
||||
margin: 0.5em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
br {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.attributes, .urls {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#search_url {
|
||||
margin-top: 8px;
|
||||
|
||||
div {
|
||||
display: block;
|
||||
border: 1px solid @color-result-search-url-border;
|
||||
padding: 4px;
|
||||
color: @color-result-search-url-font;
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin: 0.1em;
|
||||
overflow: hidden;
|
||||
height: 1.2em;
|
||||
line-height: 1.2em;
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
width: 200em;
|
||||
font-size: 0.8em;
|
||||
word-break: break-all;
|
||||
margin: 0.1em;
|
||||
.select-all-on-focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#linkto_preferences {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 0.9em;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
display: block;
|
||||
|
||||
font-size: 1.2em;
|
||||
color: @color-search-font;
|
||||
|
||||
a:link *, a:hover *, a:visited *, a:active * {
|
||||
color: @color-search-font;
|
||||
}
|
||||
}
|
||||
|
||||
#pagination {
|
||||
clear: both;
|
||||
|
||||
br {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
#apis {
|
||||
margin-top: 8px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#backToTop {
|
||||
border: 1px solid #ddd;
|
||||
margin: 0 0 0 2em;
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
box-shadow: 0px 0px 5px #CCC;
|
||||
background: white;
|
||||
position: fixed;
|
||||
bottom: 85px;
|
||||
left: @results-width;
|
||||
transition: opacity 0.5s;
|
||||
opacity: 0;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0.6em;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 75em) {
|
||||
|
||||
#main_preferences, #main_about, #main_stats {
|
||||
margin: 0.5em;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#suggestions, #answers {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
#infoboxes {
|
||||
position: inherit;
|
||||
max-width: inherit;
|
||||
|
||||
.infobox {
|
||||
clear:both;
|
||||
|
||||
img {
|
||||
float: left;
|
||||
max-width: 10em;
|
||||
margin: 0.5em 0.5em 0.5em 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: static;
|
||||
max-width: @results-width;
|
||||
margin: 0 0 2px 0;
|
||||
padding: 0;
|
||||
float: none;
|
||||
border: none;
|
||||
width: auto;
|
||||
|
||||
input {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#apis {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#search_url {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.result {
|
||||
border-bottom: 1px solid @color-result-top-border;
|
||||
margin: 0;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 6px;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 1px 0;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
max-width: 98%;
|
||||
}
|
||||
|
||||
.url {
|
||||
|
||||
span.url {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
float: right;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.engines {
|
||||
float: right;
|
||||
padding: 0 0 3px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.result-images {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.image_result {
|
||||
max-width: 98%;
|
||||
img {
|
||||
max-width: 98%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: @results-width) {
|
||||
|
||||
article[data-vim-selected]::before {
|
||||
display: none;
|
||||
content: "";
|
||||
}
|
||||
|
||||
#linkto_preferences {
|
||||
display: none;
|
||||
postion: fixed !important;
|
||||
top: 100px;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
margin: 0 5px 2px 5px;
|
||||
}
|
||||
|
||||
#corrections {
|
||||
margin: 1em 5px 1em 5px;
|
||||
}
|
||||
|
||||
#results {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: initial;
|
||||
}
|
||||
|
||||
#backToTop {
|
||||
left: 40em;
|
||||
bottom: 35px;
|
||||
}
|
||||
|
||||
.result {
|
||||
padding: 8px 10px 6px 10px;
|
||||
}
|
||||
|
||||
.result-images {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 35em) {
|
||||
|
||||
.result-videos {
|
||||
|
||||
img.thumbnail {
|
||||
float: none !important;
|
||||
}
|
||||
.content {
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
346
searx/static/themes/simple/less/toolkit.less
Normal file
@ -0,0 +1,346 @@
|
||||
// other solution : http://stackoverflow.com/questions/1577598/how-to-hide-parts-of-html-when-javascript-is-disabled/13857783#13857783
|
||||
html.no-js .hide_if_nojs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html.js .show_if_nojs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right ;
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.danger {
|
||||
background-color: @color-error-background;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
background-color: #777;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: baseline;
|
||||
min-width: 10px;
|
||||
padding: 1px 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
// table
|
||||
table {
|
||||
|
||||
width: 100%;
|
||||
|
||||
&.striped {
|
||||
tr {
|
||||
border-bottom: 1px solid @color-settings-tr-hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
tr {
|
||||
&:hover {
|
||||
background: @color-settings-tr-hover;
|
||||
}
|
||||
}
|
||||
|
||||
// dialog
|
||||
.dialog() {
|
||||
position: relative;
|
||||
width: 70%;
|
||||
padding: 1em 1em 1em 2.7em;
|
||||
margin: 0em 8% 1em 8%;
|
||||
border: 1px solid black;
|
||||
border-radius: 4px;
|
||||
text-align: left;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0.5em;
|
||||
left: 0.5em;
|
||||
font-family:"ion";
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.close {
|
||||
float:right;
|
||||
position: relative;
|
||||
top: -3px;
|
||||
color: inherit;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
ul, ol, p {
|
||||
margin: 1px 0 0 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.dialog-error {
|
||||
.dialog();
|
||||
color: @color-error;
|
||||
background: @color-error-background;
|
||||
border-color: @color-error;
|
||||
.ion-error();
|
||||
}
|
||||
|
||||
.dialog-warning {
|
||||
.dialog();
|
||||
color: @color-warning;
|
||||
background: @color-warning-background;
|
||||
border-color: @color-warning;
|
||||
.ion-warning();
|
||||
}
|
||||
|
||||
// btn-collapse
|
||||
.btn-collapse {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
//
|
||||
.scrollx {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
display: block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
// tabs
|
||||
.tabs .tabs > label {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
.flexbox();
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
|
||||
& > * {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
& > input[type=radio] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
& > label {
|
||||
order: 1;
|
||||
padding: 0.7em;
|
||||
margin: 0 0.7em;
|
||||
letter-spacing:0.5px;
|
||||
text-transform: uppercase;
|
||||
|
||||
border: solid white;
|
||||
border-width: 0px 0px 2px 0;
|
||||
|
||||
.disable-user-select();
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
& > label:hover {
|
||||
border-bottom: 2px solid @color-categories-item-border-selected;
|
||||
}
|
||||
|
||||
& > section {
|
||||
min-width: 100%;
|
||||
padding: 0.7rem 0;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid black;
|
||||
display: none;
|
||||
}
|
||||
|
||||
// default selection
|
||||
& > label:last-of-type {
|
||||
border-bottom: 2px solid @color-categories-item-border-selected;
|
||||
background: @color-categories-item-selected;
|
||||
color: @color-categories-item-selected-font;
|
||||
font-weight: bold;
|
||||
letter-spacing:-0.1px;
|
||||
}
|
||||
|
||||
& > section:last-of-type {
|
||||
display: block;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
html body .tabs > input:checked {
|
||||
~ section {
|
||||
display: none;
|
||||
}
|
||||
~ label {
|
||||
position: inherited;
|
||||
background: inherit;
|
||||
border-bottom: 2px solid transparent;
|
||||
font-weight: normal;
|
||||
color: inherit;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 2px solid @color-categories-item-border-selected;
|
||||
}
|
||||
}
|
||||
+ label {
|
||||
border-bottom: 2px solid @color-categories-item-border-selected;
|
||||
background: @color-categories-item-selected;
|
||||
color: @color-categories-item-selected-font;
|
||||
font-weight: bold;
|
||||
letter-spacing:-0.1px;
|
||||
}
|
||||
+ label + section {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
// select
|
||||
select {
|
||||
height: 28px;
|
||||
margin: 0 1em 0 0;
|
||||
padding: 2px 8px 2px 0 !important;
|
||||
color: @color-search-font;
|
||||
font-size: 12px;
|
||||
z-index: 2;
|
||||
|
||||
&:hover, &:focus {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@supports ((background-position-x: 100%) and ((appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none))) {
|
||||
|
||||
select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
border-bottom: 1px solid #d7d7d7;
|
||||
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI1MTJweCIgaGVpZ2h0PSI1MTJweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUxMiA1MTIiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwb2x5Z29uIHBvaW50cz0iMTI4LDE5MiAyNTYsMzIwIDM4NCwxOTIiLz48L2c+PC9zdmc+Cg==) no-repeat;
|
||||
background-position-x: 105%;
|
||||
background-size: 2em;
|
||||
background-origin: content-box;
|
||||
outline: medium none;
|
||||
|
||||
&:hover, &:focus {
|
||||
border-bottom: 1px solid @color-search-border;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// checkbox-onoff
|
||||
@supports (border-radius: 50px) {
|
||||
.checkbox-onoff {
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 10px;
|
||||
background: #dcdcdc;
|
||||
margin: 8px auto;
|
||||
position: relative;
|
||||
border-radius: 50px;
|
||||
label {
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
cursor: pointer;
|
||||
border-radius: 50px;
|
||||
box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.3);
|
||||
transition: all 0.4s ease;
|
||||
|
||||
left: 27px;
|
||||
background-color: #3498DB;
|
||||
}
|
||||
input[type=checkbox] {
|
||||
visibility: hidden;
|
||||
&:checked + label {
|
||||
left: -5px;
|
||||
background: #dcdcdc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkbox
|
||||
@supports (transform: rotate(-45deg)) {
|
||||
.checkbox {
|
||||
width: 20px;
|
||||
position: relative;
|
||||
margin: 20px auto;
|
||||
label {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0px 1px 1px white, 0px 1px 4px rgba(0,0,0,0.5);
|
||||
&:after {
|
||||
content: '';
|
||||
width: 9px;
|
||||
height: 5px;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
border: 3px solid #333;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
background: transparent;
|
||||
opacity: 0;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
visibility: hidden;
|
||||
&:checked + label:after {
|
||||
border-color: #3498DB;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// disabled : can't be focused, show only the check mark
|
||||
input[disabled] + label {
|
||||
background-color: transparent !important;
|
||||
box-shadow: none !important;
|
||||
cursor: inherit;;
|
||||
}
|
||||
|
||||
// if not checked and possible to checked then display a "light" check mark on hover
|
||||
input:not(:checked):not([readonly]):not([disabled]) + label:hover::after {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 50em) {
|
||||
.tabs > label {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
BIN
searx/static/themes/simple/magnet.svg
Normal file
After Width: | Height: | Size: 1.1 KiB |
20
searx/static/themes/simple/package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"grunt": "~1.0.1",
|
||||
"grunt-contrib-concat": "~1.0.1",
|
||||
"grunt-contrib-cssmin": "^2.2.1",
|
||||
"grunt-contrib-jshint": "~1.1.0",
|
||||
"grunt-contrib-less": "^1.4.1",
|
||||
"grunt-contrib-uglify": "~3.0.1",
|
||||
"grunt-contrib-watch": "~1.0.0",
|
||||
"grunt-webfont": "^1.6.0",
|
||||
"ionicons-npm": "^2.0.1",
|
||||
"jslint": "^0.10.3",
|
||||
"less-plugin-clean-css": "^1.5.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm install && grunt",
|
||||
"start": "grunt watch",
|
||||
"test": "grunt"
|
||||
}
|
||||
}
|
@ -171,7 +171,7 @@
|
||||
{{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in disabled_engines) }}
|
||||
</td>
|
||||
<th>{{ search_engine.name }}</th>
|
||||
<td>{{ shortcuts[search_engine.name] }}</td>
|
||||
<td class="name">{{ shortcuts[search_engine.name] }}</td>
|
||||
<td><input type="checkbox" {{ "checked" if current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages else ""}} readonly="readonly" disabled="disabled"></td>
|
||||
<td><input type="checkbox" {{ "checked" if search_engine.safesearch==True else ""}} readonly="readonly" disabled="disabled"></td>
|
||||
<td><input type="checkbox" {{ "checked" if search_engine.time_range_support==True else ""}} readonly="readonly" disabled="disabled"></td>
|
||||
|
9
searx/templates/simple/404.html
Normal file
@ -0,0 +1,9 @@
|
||||
{% extends "simple/base.html" %}
|
||||
{% block content %}
|
||||
<div class="center">
|
||||
<h1>{{ _('Page not found') }}</h1>
|
||||
{% autoescape false %}
|
||||
<p>{{ _('Go to %(search_page)s.', search_page='<a href="{}">{}</a>'.decode('utf-8').format(url_for('index'), _('search page'))) }}</p>
|
||||
{% endautoescape %}
|
||||
</div>
|
||||
{% endblock %}
|
4
searx/templates/simple/about.html
Normal file
@ -0,0 +1,4 @@
|
||||
{% extends 'simple/base.html' %}
|
||||
{% block content %}
|
||||
{% include '__common__/about.html' %}
|
||||
{% endblock %}
|
61
searx/templates/simple/base.html
Normal file
@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="no-js" lang="en" {% if rtl %} dir="rtl"{% endif %}>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="searx - a privacy-respecting, hackable metasearch engine">
|
||||
<meta name="keywords" content="searx, search, search engine, metasearch, meta search">
|
||||
<meta name="generator" content="searx/{{ searx_version }}">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<meta name="robots" content="noarchive">
|
||||
<meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=1">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<title>{% block title %}{% endblock %}searx</title>
|
||||
{% if rtl %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/searx-rtl.min.css') }}" type="text/css" media="screen" />
|
||||
{% else %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/searx.min.css') }}" type="text/css" media="screen" />
|
||||
{% endif %}
|
||||
{% block styles %}{% endblock %}
|
||||
{% block meta %}{% endblock %}
|
||||
{% block head %}
|
||||
<link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
|
||||
{% endblock %}
|
||||
<link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.png') }}" />
|
||||
<script type="text/javascript">
|
||||
var searx = {
|
||||
autocompleter: {% if autocomplete %}true{% else %}false{% endif %},
|
||||
method: "{{ method or 'POST' }}",
|
||||
touch: (("ontouchstart" in window) || window.DocumentTouch && document instanceof DocumentTouch) || false,
|
||||
staticPath: "{{ url_for('static', filename='themes/simple') }}/",
|
||||
noItemFound: "{{ _('No item found') }}",
|
||||
search_on_category_select: {{ 'true' if 'plugins/js/search_on_category_select.js' in scripts else 'false'}},
|
||||
infinite_scroll: {{ 'true' if 'plugins/js/infinite_scroll.js' in scripts else 'false' }}
|
||||
};
|
||||
document.getElementsByTagName("html")[0].className = (searx.touch)?"js touch":"js";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<main id="main_{{ self._TemplateReference__context.name|replace("simple/", "")|replace(".html", "") }}">
|
||||
{% if errors %}
|
||||
<div class="dialog-error" role="alert">
|
||||
<a href="#" class="close" aria-label="close" title="close">×</a>
|
||||
<ul>
|
||||
{% for message in errors %}
|
||||
<li>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
<footer>
|
||||
<p>{{ _('Powered by') }} <a href="{{ url_for('about') }}">searx</a> - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}</p>
|
||||
</footer>
|
||||
<!--[if gte IE 9]>-->
|
||||
<script src="{{ url_for('static', filename='js/searx.min.js') }}" ></script>
|
||||
<!--<![endif]-->
|
||||
</body>
|
||||
</html>
|
8
searx/templates/simple/categories.html
Normal file
@ -0,0 +1,8 @@
|
||||
<div id="categories">{{- '' -}}
|
||||
<div id="categories_container">
|
||||
{%- for category in categories -%}
|
||||
<div class="category"><input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}"{% if category in selected_categories %} checked="checked"{% endif %}/><label for="checkbox_{{ category|replace(' ', '_') }}" class="tooltips">{{ _(category) }}</label></div>
|
||||
{%- endfor -%}
|
||||
{%- if display_tooltip %}<div class="help">{{ _('Click on the magnifier to perform search') }}</div>{% endif -%}
|
||||
</div>{{- '' -}}
|
||||
</div>
|
12
searx/templates/simple/index.html
Normal file
@ -0,0 +1,12 @@
|
||||
{% extends "simple/base.html" %}
|
||||
{% from 'simple/macros.html' import icon %}
|
||||
{% block meta %}
|
||||
<link rel="preload" href="{{ url_for('static', filename='img/searx.png') }}" as="image" />
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<nav id="linkto_preferences"><a href="{{ url_for('preferences') }}">{{ icon('navicon-round') }}</a></nav>
|
||||
<div class="index">
|
||||
<div class="title"><h1>searx</h1></div>
|
||||
{% include 'simple/search.html' %}
|
||||
</div>
|
||||
{% endblock %}
|
46
searx/templates/simple/infobox.html
Normal file
@ -0,0 +1,46 @@
|
||||
<aside class="infobox">
|
||||
<h2><bdi>{{ infobox.infobox }}</bdi></h2>
|
||||
{% if infobox.img_src %}<img src="{{ image_proxify(infobox.img_src) }}" title="{{ infobox.infobox|striptags }}" alt="{{ infobox.infobox|striptags }}" />{% endif %}
|
||||
<p><bdi>{{ infobox.entity }}</bdi></p>
|
||||
<p><bdi>{{ infobox.content | safe }}</bdi></p>
|
||||
{% if infobox.attributes %}
|
||||
<div class="attributes">
|
||||
{% for attribute in infobox.attributes %}
|
||||
<dl>
|
||||
<dt><bdi>{{ attribute.label }} :</bdi></dt>
|
||||
{%- if attribute.image -%}
|
||||
<dd><img src="{{ image_proxify(attribute.image.src) }}" alt="{{ attribute.image.alt }}" /></dd>
|
||||
{%- else -%}
|
||||
<dd><bdi>{{ attribute.value }}</bdi></dd>
|
||||
{%- endif -%}
|
||||
</dl>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if infobox.urls %}
|
||||
<div class="urls">
|
||||
<ul>
|
||||
{%- for url in infobox.urls -%}
|
||||
<li class="url"><bdi><a href="{{ url.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ url.title }}</a></bdi></li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if infobox.relatedTopics %}
|
||||
<div class="relatedTopics">
|
||||
{% for topic in infobox.relatedTopics %}
|
||||
<div>
|
||||
<h3><bdi>{{ topic.name }}</bdi></h3>
|
||||
{% for suggestion in topic.suggestions %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<input type="hidden" name="q" value="{{ suggestion }}">
|
||||
<input type="submit" value="{{ suggestion }}" />
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</aside>
|
8
searx/templates/simple/languages.html
Normal file
@ -0,0 +1,8 @@
|
||||
<select class="language" id="language" name="language" tabindex="2">{{- '' -}}
|
||||
<option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Default language') }}</option>
|
||||
{%- for lang_id,lang_name,country_name,english_name in language_codes | sort(attribute=1) -%}
|
||||
<option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>
|
||||
{{- lang_name }} {% if country_name %}({{ country_name }}) {% endif %}- {{ lang_id -}}
|
||||
</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
86
searx/templates/simple/macros.html
Normal file
@ -0,0 +1,86 @@
|
||||
<!-- Draw glyphicon icon from bootstrap-theme -->
|
||||
{% macro icon(action) -%}
|
||||
<span class="ion-icon-big ion-{{ action }}"></span>
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro icon_small(action) -%}
|
||||
<span class="ion-icon ion-{{ action }}"></span>
|
||||
{%- endmacro %}
|
||||
|
||||
<!-- Draw favicon -->
|
||||
<!-- TODO: using url_for methode -->
|
||||
{% macro draw_favicon(favicon) -%}
|
||||
<img width="14" height="14" class="favicon" src="static/themes/simple/img/icons/{{ favicon }}.png" alt="{{ favicon }}" />
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro result_open_link(url, classes='') -%}
|
||||
<a href="{{ url }}" {% if classes %}class="{{ classes }}" {% endif %}{% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro result_close_link() -%}
|
||||
</a>
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro result_link(url, title, classes='') -%}
|
||||
{{ result_open_link(url, classes) }}{{ title }}{{ result_close_link() }}
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- Draw result header -->
|
||||
{% macro result_header(result, favicons, image_proxify) -%}
|
||||
<article class="result {% if result['template'] %}result-{{ result.template|replace('.html', '') }}{% else %}result-default{% endif %} {% if result['category'] %}category-{{ result['category'] }}{% endif %}">
|
||||
{%- if result.img_src %}{{ result_open_link(result.url) }}<img class="image" src="{{ image_proxify(result.img_src) }}" alt="{{ result.title|striptags }}" title="{{ result.title|striptags }}" class="image" />{{ result_close_link() }}{% endif -%}
|
||||
{%- if result.thumbnail %}{{ result_open_link(result.url) }}<img class="thumbnail" src="{{ image_proxify(result.thumbnail) }}" title="{{ result.title|striptags }}" alt="{{ result.title|striptags }}"/>{{ result_close_link() }}{% endif -%}
|
||||
<h3>{{ result_link(result.url, result.title|safe) }}</h3>
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- Draw result sub header -->
|
||||
{%- macro result_sub_header(result) -%}
|
||||
{% if result.publishedDate %}<time class="published_date" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- Draw result sub footer -->
|
||||
{%- macro result_sub_footer(result, proxify) -%}
|
||||
<div class="engines">{% for engine in result.engines %}<span>{{ engine }}</span>{% endfor %}</div>{{- '' -}}
|
||||
<p class="url"><span class="url">{{ result.pretty_url }}</span>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "cache_link") }}‎ {% if proxify %} {{ result_link(proxify(result.url), icon('link') + _('proxied'), "proxyfied_link") }} {% endif %}</p>{{- '' -}}
|
||||
<div class="break"></div>{{- '' -}}
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- Draw result footer -->
|
||||
{%- macro result_footer(result) -%}
|
||||
</article>
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- -->
|
||||
{%- macro tabs_open() -%}
|
||||
<div class="tabs" role="tablist">
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro tab_header(name, id, label) -%}
|
||||
<input type="radio" name="{{ name }}" id="tab_{{ id }}"/>
|
||||
<label for="tab_{{ id }}" role="tab"
|
||||
aria-controls="panel{{ id }}">{{ label }}</label>
|
||||
<section id="tab-content{{ id }}" role="tabpanel"
|
||||
aria-labelledby="{{ label }}" aria-hidden="false">
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro tab_footer() -%}
|
||||
</section>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro tabs_close() -%}
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro checkbox_onoff(name, checked) -%}
|
||||
<div class="checkbox-onoff">{{- '' -}}
|
||||
<input type="checkbox" value="None" id="{{ name }}" name="{{ name }}" {% if checked %}checked{% endif %}/>{{- '' -}}
|
||||
<label for="{{ name }}"></label>{{- '' -}}
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro checkbox(name, checked, readonly, disabled) -%}
|
||||
<div class="checkbox">{{- '' -}}
|
||||
<input type="checkbox" value="None" id="{{ name }}" name="{{ name }}" {% if checked %}checked{% endif %}{% if readonly %} readonly="readonly" {% endif %}{% if disabled %} disabled="disabled" {% endif %}/>{{- '' -}}
|
||||
<label for="{{ name }}"></label>{{- '' -}}
|
||||
</div>
|
||||
{%- endmacro -%}
|
190
searx/templates/simple/preferences.html
Normal file
@ -0,0 +1,190 @@
|
||||
{% from 'simple/macros.html' import tabs_open, tabs_close, tab_header, tab_footer, checkbox_onoff, checkbox %}
|
||||
|
||||
{% extends "simple/base.html" %}
|
||||
|
||||
{%- macro plugin_preferences(section) -%}
|
||||
{%- for plugin in plugins -%}
|
||||
{%- if plugin.preference_section == section -%}
|
||||
<fieldset>{{- '' -}}
|
||||
<legend>{{ _(plugin.name) }}</legend>{{- '' -}}
|
||||
<div class="value">
|
||||
{{- checkbox_onoff('plugin_' + plugin.id, plugin.id not in allowed_plugins) -}}
|
||||
</div>{{- '' -}}
|
||||
<div class="description">
|
||||
{{- _(plugin.description) -}}
|
||||
</div>{{- '' -}}
|
||||
</fieldset>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% block head %} {% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<a href="{{ url_for('index') }}"><h1><span>searx</span></h1></a>
|
||||
|
||||
<h2>{{ _('Preferences') }}</h2>
|
||||
|
||||
<form id="search_form" method="post" action="{{ url_for('preferences') }}">
|
||||
|
||||
{{ tabs_open() }}
|
||||
|
||||
{{ tab_header('maintab', 'general', _('General')) }}
|
||||
<fieldset>
|
||||
<legend>{{ _('Default categories') }}</legend>
|
||||
{% set display_tooltip = false %}
|
||||
{% include 'simple/categories.html' %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Search language') }}</legend>
|
||||
<p class="value">{{- '' -}}
|
||||
<select name='language'>{{- '' -}}
|
||||
<option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Default language') }}</option>
|
||||
{%- for lang_id,lang_name,country_name,english_name in language_codes | sort(attribute=1) -%}
|
||||
<option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name }} {% if country_name %}({{ country_name }}) {% endif %}- {{ lang_id }}</option>
|
||||
{%- endfor -%}
|
||||
</select>{{- '' -}}
|
||||
</p>
|
||||
<div class="description">{{ _('What language do you prefer for search?') }}</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Autocomplete') }}</legend>
|
||||
<p class="value">
|
||||
<select name="autocomplete">
|
||||
<option value=""> - </option>
|
||||
{% for backend in autocomplete_backends %}
|
||||
<option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Find stuff as you type') }}</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('SafeSearch') }}</legend>
|
||||
<p class="value">
|
||||
<select name='safesearch'>
|
||||
<option value="2" {% if safesearch == '2' %}selected="selected"{% endif %}>{{ _('Strict') }}</option>
|
||||
<option value="1" {% if safesearch == '1' %}selected="selected"{% endif %}>{{ _('Moderate') }}</option>
|
||||
<option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Filter content') }}</p>
|
||||
</fieldset>
|
||||
{{ plugin_preferences('general') }}
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tab_header('maintab', 'engines', _('Engines')) }}
|
||||
<p>{{ _('Currently used search engines') }}</p>
|
||||
|
||||
{{ tabs_open() }}
|
||||
{% for categ in all_categories %}
|
||||
|
||||
{{ tab_header('enginetab', 'category' + categ, _(categ)) }}
|
||||
<div class="scrollx">
|
||||
<table class="striped">
|
||||
<tr>
|
||||
<th class="engine_checkbox">{{ _("Allow") }}</th>
|
||||
<th class="name">{{ _("Engine name") }}</th>
|
||||
<th class="shortcut">{{ _("Shortcut") }}</th>
|
||||
<th>{{ _("Supports selected language") }}</th>
|
||||
<th>{{ _("SafeSearch") }}</th>
|
||||
<th>{{ _("Time range") }}</th>
|
||||
<th>{{ _("Avg. time") }}</th>
|
||||
<th>{{ _("Max time") }}</th>
|
||||
</tr>
|
||||
{% for search_engine in engines_by_category[categ] %}
|
||||
|
||||
{% if not search_engine.private %}
|
||||
{% set engine_id = 'engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_') %}
|
||||
<tr>
|
||||
<td class="engine_checkbox">{{ checkbox_onoff(engine_id, (search_engine.name, categ) in disabled_engines) }}</td>
|
||||
<th class="name">{{ search_engine.name }}</th>
|
||||
<td class="shortcut">{{ shortcuts[search_engine.name] }}</td>
|
||||
<td>{{ checkbox(engine_id + '_supported_languages', current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages, true, true) }}</td>
|
||||
<td>{{ checkbox(engine_id + '_safesearch', search_engine.safesearch==True, true, true) }}</td>
|
||||
<td>{{ checkbox(engine_id + '_time_range_support', search_engine.time_range_support==True, true, true) }}</td>
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
<div>
|
||||
{{ tab_footer() }}
|
||||
{% endfor %}
|
||||
{{ tabs_close() }}
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tab_header('maintab', 'ui', _('User interface')) }}
|
||||
<fieldset>
|
||||
<legend>{{ _('Interface language') }}</legend>
|
||||
<p class="value">
|
||||
<select name='locale'>
|
||||
{% for locale_id,locale_name in locales.items() | sort %}
|
||||
<option value="{{ locale_id }}" {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Change the language of the layout') }}</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Themes') }}</legend>
|
||||
<p class="value">
|
||||
<select name="theme">
|
||||
{%- for name in themes -%}
|
||||
<option value="{{ name }}" {% if name == theme %}selected="selected"{% endif %}>{{ name }}</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Change searx layout') }}</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Results on new tabs') }}</legend>
|
||||
<p class="value">
|
||||
<select name='results_on_new_tab'>
|
||||
<option value="1" {% if results_on_new_tab %}selected="selected"{% endif %}>{{ _('On') }}</option>
|
||||
<option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{_('Open result links on new browser tabs') }}</div>
|
||||
</fieldset>
|
||||
{{ plugin_preferences('ui') }}
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tab_header('maintab', 'privacy', _('Privacy')) }}
|
||||
<fieldset>
|
||||
<legend>{{ _('Method') }}</legend>
|
||||
<p class="value">
|
||||
<select name='method'>
|
||||
<option value="POST" {% if method == 'POST' %}selected="selected"{% endif %}>POST</option>
|
||||
<option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Search language') }}</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Image proxy') }}</legend>
|
||||
<p class="value">
|
||||
<select name='image_proxy'>
|
||||
<option value="1" {% if image_proxy %}selected="selected"{% endif %}>{{ _('Enabled') }}</option>
|
||||
<option value="" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled') }}</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Proxying image results through searx') }}</div>
|
||||
</fieldset>
|
||||
{{ plugin_preferences('privacy') }}
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tabs_close() }}
|
||||
|
||||
<p class="small_font">{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }}
|
||||
<br />
|
||||
{{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }}
|
||||
</p>
|
||||
|
||||
<input type="submit" value="{{ _('save') }}" />
|
||||
<div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('clear_cookies') }}">{{ _('Reset defaults') }}</a></div>
|
||||
<div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('index') }}">{{ _('back') }}</a></div>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
13
searx/templates/simple/result_templates/code.html
Normal file
@ -0,0 +1,13 @@
|
||||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
{%- if result.content %}{{ result.content|safe }}{% endif %}</p>
|
||||
{%- if result.repository -%}
|
||||
<p class="content"><a href="{{ result.repository|safe }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.repository }}</a></p>
|
||||
{%- endif -%}
|
||||
<div dir="ltr" class="codelines">
|
||||
{{- result.codelines|code_highlighter(result.code_language)|safe -}}
|
||||
</div>{{- '' -}}
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{{ result_footer(result) }}
|
17
searx/templates/simple/result_templates/default.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
{% if result.embedded -%}
|
||||
<p class="altlink"> • <a class="btn-collapse collapsed media-loader disabled_if_nojs" data-target="#result-media-{{ index }}" data-btn-text-collapsed="{{ _('show media') }}" data-btn-text-not-collapsed="{{ _('hide media') }}">{{ icon('music-note') }} {{ _('show media') }}</a></p>
|
||||
{%- endif %}
|
||||
<p class="content">
|
||||
{%- if result.content %}{{ result.content|safe }}{% endif -%}
|
||||
</p>
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{% if result.embedded -%}
|
||||
<div id="result-media-{{ index }}" class="invisible">
|
||||
{{- result.embedded|safe -}}
|
||||
</div>
|
||||
{%- endif %}
|
||||
{{- result_footer(result) }}
|
4
searx/templates/simple/result_templates/images.html
Normal file
@ -0,0 +1,4 @@
|
||||
<article class="result result-images {% if result['category'] %}category-{{ result['category'] }}{% endif %}">
|
||||
<a href="{{ result.img_src }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}><img class="image_thumbnail" src="{% if result.thumbnail_src %}{{ image_proxify(result.thumbnail_src) }}{% else %}{{ image_proxify(result.img_src) }}{% endif %}" title="{{ result.title|striptags }}" alt="{{ result.title|striptags }}" /></a>
|
||||
<span class="url"><a href="{{ result.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %} class="small_font">{{ result.parsed_url[0] }}://{{ result.parsed_url[1] }}</a></span>
|
||||
</article>
|
71
searx/templates/simple/result_templates/map.html
Normal file
@ -0,0 +1,71 @@
|
||||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl, icon %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
|
||||
{%- if (result.latitude and result.longitude) or result.boundingbox -%}
|
||||
<small> • <a class="btn-collapse collapsed searx_init_map hide_if_nojs" data-target="#result-map-{{ index }}" data-btn-text-collapsed="{{ _('show map') }}" data-btn-text-not-collapsed="{{ _('hide map') }}" data-leaflet-target="osm-map-{{ index }}" data-map-lon="{{ result.longitude }}" data-map-lat="{{ result.latitude }}" {% if result.boundingbox %}data-map-boundingbox='{{ result.boundingbox|tojson|safe }}'{% endif %} {% if result.geojson %}data-map-geojson='{{ result.geojson|tojson|safe }}'{% endif %}>{{ icon( 'globe') }} {{ _('show map') }}</a></small>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if result.osm and (result.osm.type and result.osm.id) -%}
|
||||
<small> • <a class="btn-collapse collapsed hide_if_nojs searx_overpass_request" data-target="#result-overpass-{{ index }}" data-btn-text-collapsed="{{ _('show details') }}" data-btn-text-not-collapsed="{{ _('hide details') }}" data-osm-type="{{ result.osm.type }}" data-osm-id="{{ result.osm.id }}" data-result-table="result-overpass-table-{{ index }}" data-result-table-loadicon="result-overpass-table-loading-{{ index }}">{{ icon('location') }} {{ _('show details') }}</a></small>
|
||||
{%- endif -%}
|
||||
{#-
|
||||
{% if (result.latitude and result.longitude) %}
|
||||
<small> • <a class="btn-collapse disabled_if_nojs" data-target="#result-geodata-{{ index }}" data-btn-text-collapsed="{{ _('show geodata') }}" data-btn-text-not-collapsed="{{ _('hide geodata') }}">{{ icon('location') }} {{ _('show geodata') }}</a></small>
|
||||
{% endif %}
|
||||
-#}
|
||||
|
||||
{%- if result.address -%}
|
||||
<p itemscope itemtype="http://schema.org/PostalAddress" class="content">
|
||||
{%- if result.address.name -%}
|
||||
<strong itemprop="name">{{ result.address.name }}</strong><br/>
|
||||
{%- endif -%}
|
||||
{% if result.address.road -%}
|
||||
<span itemprop="streetAddress">
|
||||
{% if result.address.house_number %}{{ result.address.house_number }}, {% endif %}
|
||||
{{ result.address.road }}
|
||||
</span><br/>
|
||||
{%- endif %}
|
||||
{%- if result.address.locality -%}
|
||||
<span itemprop="addressLocality">{{ result.address.locality }}</span>
|
||||
{% if result.address.postcode %}, <span itemprop="postalCode">{{ result.address.postcode }}</span>{% endif %}
|
||||
<br/>
|
||||
{%- endif -%}
|
||||
{%- if result.address.country -%}
|
||||
<span itemprop="addressCountry">{{ result.address.country }}</span>
|
||||
{%- endif -%}
|
||||
</p>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif -%}
|
||||
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
|
||||
{% if result.osm and (result.osm.type and result.osm.id) -%}
|
||||
<div class="result-content invisible" id="result-overpass-{{ index }}"{% if rtl %} dir="ltr"{% endif %}>
|
||||
<div id="result-overpass-table-loading-{{ index }}"><img src="{{ url_for('static', filename='img/loader.gif') }}" alt="Loading ..."/></div>
|
||||
<table id="result-overpass-table-{{ index }}">
|
||||
<thead>
|
||||
<tr><th>key</th><th>value</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
{#-
|
||||
{% if (result.latitude and result.longitude) -%}
|
||||
<div id="result-geodata-{{ index }}" class="invisible">
|
||||
<strong>Longitude:</strong> {{ result.longitude }} <br/>
|
||||
<strong>Latitude:</strong> {{ result.latitude }}
|
||||
</div>
|
||||
{%- endif %}
|
||||
-#}
|
||||
|
||||
{% if (result.latitude and result.longitude) or result.boundingbox -%}
|
||||
<div id="result-map-{{ index }}" class="invisible"><div id="osm-map-{{ index }}" style="height:300px; width:100%; margin: 10px 0;" ></div></div>
|
||||
{%- endif %}
|
||||
|
||||
{{- result_footer(result) }}
|
24
searx/templates/simple/result_templates/torrent.html
Normal file
@ -0,0 +1,24 @@
|
||||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl, result_link %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
|
||||
{% if result.magnetlink %}<p class="altlink"> • {{ result_link(result.magnetlink, icon('magnet') + _('magnet link'), "magnetlink") }}</p>{% endif %}
|
||||
{% if result.torrentfile %}<p class="altlink"> • {{ result_link(result.torrentfile, icon('download-alt') + _('torrent file'), "torrentfile") }}</p>{% endif %}
|
||||
|
||||
{% if result.seed %}<p class="stat"> • {{ icon('arrow-swap') }} {{ _('Seeder') }} <span class="badge">{{ result.seed }}</span> • {{ _('Leecher') }} <span class="badge">{{ result.leech }}</span></p>{% endif %}
|
||||
|
||||
{%- if result.filesize %}<p class="stat">{{ icon('floppy-disk') }} {{ _('Filesize') }}<span class="badge">
|
||||
{%- if result.filesize < 1024 %}{{ result.filesize }} {{ _('Bytes') }}
|
||||
{%- elif result.filesize < 1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024) }} {{ _('kiB') }}
|
||||
{%- elif result.filesize < 1024*1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024/1024) }} {{ _('MiB') }}
|
||||
{%- elif result.filesize < 1024*1024*1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024/1024/1024) }} {{ _('GiB') }}
|
||||
{%- else %}{{ '{0:0.2f}'.format(result.filesize/1024/1024/1024/1024) }} {{ _('TiB') }}{% endif -%}
|
||||
</span></p>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if result.files %}<p class="stat">{{ icon('file') }} {{ _('Number of Files') }} <span class="badge">{{ result.files }}</span></p>{% endif -%}
|
||||
|
||||
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif -%}
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{{- result_footer(result) }}
|
15
searx/templates/simple/result_templates/videos.html
Normal file
@ -0,0 +1,15 @@
|
||||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) }}
|
||||
{{ result_sub_header(result) }}
|
||||
{% if result.embedded -%}
|
||||
<p class="altlink"> • <a class="btn-collapse collapsed media-loader disabled_if_nojs" data-target="#result-video-{{ index }}" data-btn-text-collapsed="{{ _('show video') }}" data-btn-text-not-collapsed="{{ _('hide video') }}">{{ icon('film-outline') }} {{ _('show video') }}</a></p>
|
||||
{%- endif %}
|
||||
{% if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif %}
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{% if result.embedded -%}
|
||||
<div id="result-video-{{ index }}" class="invisible">
|
||||
{{- result.embedded|safe -}}
|
||||
</div>
|
||||
{%- endif %}
|
||||
{{ result_footer(result) }}
|
151
searx/templates/simple/results.html
Normal file
@ -0,0 +1,151 @@
|
||||
{% extends "simple/base.html" %}
|
||||
{% from 'simple/macros.html' import icon, icon_small %}
|
||||
{% block title %}{{ q|e }} - {% endblock %}
|
||||
{% block meta %}<link rel="alternate" type="application/rss+xml" title="Searx search: {{ q|e }}" href="{{ url_for('index') }}?q={{ q|urlencode }}&categories={{ selected_categories|join(",") | replace(' ','+') }}&pageno={{ pageno }}&time_range={{ time_range }}&language={{ current_language }}&safesearch={{ safesearch }}&format=rss">{% endblock %}
|
||||
{% block content %}
|
||||
<nav id="linkto_preferences"><a href="{{ url_for('preferences') }}">{{ icon('navicon-round') }}</a></nav>
|
||||
{% include 'simple/search.html' %}
|
||||
<div id="results">
|
||||
{% if answers %}
|
||||
<div id="answers"><h4 class="title">{{ _('Answers') }} : </h4>
|
||||
{% for answer in answers -%}
|
||||
<div class="answer">{{ answer }}</div>
|
||||
{%- endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="sidebar">
|
||||
|
||||
{% if number_of_results != '0' -%}
|
||||
<p id="result_count"><small>{{ _('Number of results') }}: {{ number_of_results }}</small></p>
|
||||
{%- endif %}
|
||||
|
||||
{% if unresponsive_engines and results|length >= 1 %}
|
||||
<div class="dialog-error" role="alert">
|
||||
<p><strong>{{ _('Error!') }}</strong> {{ _('Engines cannot retrieve results') }}:</p>
|
||||
<p>{% for engine_name, error_type in unresponsive_engines %}
|
||||
{{ engine_name }} ({{ error_type }}){% if not loop.last %}, {% endif %}
|
||||
{% endfor %}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if infoboxes %}
|
||||
<div id="infoboxes">
|
||||
{% for infobox in infoboxes %}
|
||||
{% include 'simple/infobox.html' %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if suggestions %}
|
||||
<div id="suggestions">
|
||||
<h4 class="title">{{ _('Suggestions') }} : </h4>
|
||||
<div class="wrapper">
|
||||
{% for suggestion in suggestions %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<input type="hidden" name="q" value="{{ suggestion }}">
|
||||
<input type="hidden" name="language" value="{{ current_language }}">
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}">
|
||||
<input type="hidden" name="theme" value="{{ theme }}">
|
||||
<input type="submit" class="suggestion" value="• {{ suggestion }}">
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="search_url">
|
||||
<h4 class="title">{{ _('Search URL') }} :</h4>
|
||||
<div><pre>{{ base_url }}?q={{ q|urlencode }}&language={{ current_language }}&time_range={{ time_range }}&safesearch={{ safesearch }}{% if pageno > 1 %}&pageno={{ pageno }}{% endif %}{% if selected_categories %}&categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}</pre></div>
|
||||
</div>
|
||||
<div id="apis">
|
||||
<h4 class="title">{{ _('Download results') }}</h4>
|
||||
{% for output_type in ('csv', 'json', 'rss') %}
|
||||
<div class="left">
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<input type="hidden" name="q" value="{{ q|e }}">
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1">
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ pageno }}">
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}">
|
||||
<input type="hidden" name="language" value="{{ current_language }}">
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}">
|
||||
<input type="hidden" name="format" value="{{ output_type }}">
|
||||
<input type="submit" value="{{ output_type }}">
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if corrections %}
|
||||
<div id="corrections">
|
||||
<h4>{{ _('Try searching for:') }}</h4>
|
||||
{% for correction in corrections %}
|
||||
<div class="left">
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}" role="navigation">
|
||||
<input type="hidden" name="q" value="{{ correction }}">
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}">
|
||||
<input type="hidden" name="language" value="{{ current_language }}">
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}">
|
||||
<input type="hidden" name="theme" value="{{ theme }}">
|
||||
<input type="submit" value="{{ correction }}">
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="urls">
|
||||
{% for result in results %}
|
||||
{% set index = loop.index %}
|
||||
{% if result['template'] %}
|
||||
{% include get_result_template('simple', result['template']) %}
|
||||
{% else %}
|
||||
{% include 'simple/result_templates/default.html' %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if not results and not answers %}
|
||||
{% include 'simple/messages/no_results.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="backToTop">
|
||||
<a href="#">{{ icon_small('chevron-up') }}</a>
|
||||
</div>
|
||||
{% if paging %}
|
||||
<nav id="pagination">
|
||||
{% if pageno > 1 %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<div class="{% if rtl %}right{% else %}left{% endif %}">
|
||||
<input type="hidden" name="q" value="{{ q|e }}" >
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1" >
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ pageno-1 }}" >
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}" >
|
||||
<input type="hidden" name="language" value="{{ current_language }}" >
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
|
||||
<input type="hidden" name="theme" value="{{ theme }}" >
|
||||
<button type="submit">{{ icon_small('chevron-left') }} {{ _('previous page') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<div class="{% if rtl %}left{% else %}right{% endif %}">
|
||||
<input type="hidden" name="q" value="{{ q|e }}" >
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1" >
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ pageno+1 }}" >
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}" >
|
||||
<input type="hidden" name="language" value="{{ current_language }}" >
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
|
||||
<input type="hidden" name="theme" value="{{ theme }}" >
|
||||
<button type="submit">{{ _('next page') }} {{ icon_small('chevron-right') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</nav>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
16
searx/templates/simple/search.html
Normal file
@ -0,0 +1,16 @@
|
||||
<form id="search" method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<div id="search_wrapper">
|
||||
<div class="search_box">
|
||||
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" tabindex="1" autocomplete="off" spellcheck="false" dir="auto" {% if q %}value="{{ q }}"{% endif %} >
|
||||
<button id="send_search" type="submit" tabindex="-1"><span class="hide_if_nojs">{{ icon('search') }}</span><span class="show_if_nojs">{{ _('Start search') }}</span></button>
|
||||
</div>
|
||||
<div class="search_filters">
|
||||
{% include 'simple/languages.html' %}
|
||||
{% include 'simple/time-range.html' %}
|
||||
</div>
|
||||
</div>
|
||||
{% set display_tooltip = true %}
|
||||
{% include 'simple/categories.html' %}
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
|
||||
<input type="hidden" name="theme" value="{{ theme }}" >
|
||||
</form>
|
40
searx/templates/simple/simple.spec.txt
Normal file
@ -0,0 +1,40 @@
|
||||
#container
|
||||
.search
|
||||
#search_form
|
||||
|
||||
#results
|
||||
|
||||
#sidebar
|
||||
#result-count
|
||||
.title
|
||||
.content
|
||||
|
||||
.infobox
|
||||
h2
|
||||
img
|
||||
p
|
||||
div#attributes
|
||||
table
|
||||
tbody
|
||||
tr
|
||||
td
|
||||
td
|
||||
div#urls
|
||||
ul
|
||||
li
|
||||
|
||||
#suggestions
|
||||
.title
|
||||
.suggestion
|
||||
|
||||
#search_url
|
||||
.title
|
||||
input
|
||||
|
||||
#apis
|
||||
.title
|
||||
.api-link
|
||||
|
||||
.result
|
||||
|
||||
|
25
searx/templates/simple/stats.html
Normal file
@ -0,0 +1,25 @@
|
||||
{% extends "simple/base.html" %}
|
||||
{% block head %} {% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<a href="{{ url_for('index') }}"><h1><span>searx</span></h1></a>
|
||||
|
||||
<h2>{{ _('Engine stats') }}</h2>
|
||||
|
||||
{% for stat_name,stat_category in stats %}
|
||||
<div class="left">
|
||||
<table>
|
||||
<tr colspan="3">
|
||||
<th>{{ stat_name }}</th>
|
||||
</tr>
|
||||
{% for engine in stat_category %}
|
||||
<tr>
|
||||
<td>{{ engine.name }}</td>
|
||||
<td>{{ '%.02f'|format(engine.avg) }}</td>
|
||||
<td class="percentage"><div style="width: {{ engine.percentage }}%"> </div></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
17
searx/templates/simple/time-range.html
Normal file
@ -0,0 +1,17 @@
|
||||
<select name="time_range" id="time_range" class="time_range" tabindex="3">{{- '' -}}
|
||||
<option id="time-range-anytime" value="" {{ "selected" if time_range=="" or not time_range else ""}}>
|
||||
{{- _('Anytime') -}}
|
||||
</option>{{- '' -}}
|
||||
<option id="time-range-day" value="day" {{ "selected" if time_range=="day" else ""}}>
|
||||
{{- _('Last day') -}}
|
||||
</option>{{- '' -}}
|
||||
<option id="time-range-week" value="week" {{ "selected" if time_range=="week" else ""}}>
|
||||
{{- _('Last week') -}}
|
||||
</option>{{- '' -}}
|
||||
<option id="time-range-month" value="month" {{ "selected" if time_range=="month" else ""}}>
|
||||
{{- _('Last month') -}}
|
||||
</option>{{- '' -}}
|
||||
<option id="time-range-year" value="year" {{ "selected" if time_range=="year" else ""}}>
|
||||
{{- _('Last year') -}}
|
||||
</option>{{- '' -}}
|
||||
</select>
|