diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..0a75fa6d8 --- /dev/null +++ b/.gitattributes @@ -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 diff --git a/.travis.yml b/.travis.yml index b6017cd93..1eb6573f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/manage.sh b/manage.sh index 2466f25ca..681f3a975 100755 --- a/manage.sh +++ b/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() { diff --git a/searx/plugins/doai_rewrite.py b/searx/plugins/doai_rewrite.py index 95efa8f9b..b7b814fac 100644 --- a/searx/plugins/doai_rewrite.py +++ b/searx/plugins/doai_rewrite.py @@ -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): diff --git a/searx/plugins/https_rewrite.py b/searx/plugins/https_rewrite.py index 4462c86bc..3d986770e 100644 --- a/searx/plugins/https_rewrite.py +++ b/searx/plugins/https_rewrite.py @@ -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'] diff --git a/searx/plugins/infinite_scroll.py b/searx/plugins/infinite_scroll.py index 422a4befb..e3726671a 100644 --- a/searx/plugins/infinite_scroll.py +++ b/searx/plugins/infinite_scroll.py @@ -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',) diff --git a/searx/plugins/search_on_category_select.py b/searx/plugins/search_on_category_select.py index f72c63d76..2a38cac78 100644 --- a/searx/plugins/search_on_category_select.py +++ b/searx/plugins/search_on_category_select.py @@ -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',) diff --git a/searx/plugins/tracker_url_remover.py b/searx/plugins/tracker_url_remover.py index a84012828..630c8a638 100644 --- a/searx/plugins/tracker_url_remover.py +++ b/searx/plugins/tracker_url_remover.py @@ -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): diff --git a/searx/static/themes/simple/.jshintignore b/searx/static/themes/simple/.jshintignore new file mode 100644 index 000000000..3b2b7148f --- /dev/null +++ b/searx/static/themes/simple/.jshintignore @@ -0,0 +1 @@ +js/searx_src/autocomplete.js diff --git a/searx/static/themes/simple/css/searx-rtl.css b/searx/static/themes/simple/css/searx-rtl.css new file mode 100644 index 000000000..e43f02d50 --- /dev/null +++ b/searx/static/themes/simple/css/searx-rtl.css @@ -0,0 +1,2049 @@ +/*! searx | 06-08-2017 | https://github.com/asciimoo/searx */ +/* +* searx, A privacy-respecting, hackable metasearch engine +* +* To convert "style.less" to "style.css" run: $make styles +*/ +/*! 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"], +[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, +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; +} +/* + * searx, A privacy-respecting, hackable metasearch engine + * + * To change the colors of the site, simple edit this variables + */ +/* +* searx, A privacy-respecting, hackable metasearch engine +*/ +.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; +} +.highlight .lineno::selection { + background: transparent; + /* WebKit/Blink Browsers */ +} +.highlight .lineno::-moz-selection { + background: transparent; + /* Gecko Browsers */ +} +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: #fae1e1; +} +.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 { + width: 100%; +} +table.striped tr { + border-bottom: 1px solid #ececec; +} +th { + padding: 0.4em; +} +td { + padding: 0 4px; +} +tr:hover { + background: #ececec; +} +.dialog-error { + 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; + color: #db3434; + background: #fae1e1; + border-color: #db3434; +} +.dialog-error:before { + position: absolute; + top: 0.5em; + left: 0.5em; + font-family: "ion"; + font-size: 1.5em; +} +.dialog-error .close { + float: right; + position: relative; + top: -3px; + color: inherit; + font-size: 1.5em; +} +.dialog-error ul, +.dialog-error ol, +.dialog-error p { + margin: 1px 0 0 0; +} +.dialog-error:before { + content: "\f110"; +} +.dialog-warning { + 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; + color: #dbba34; + background: #faf5e1; + border-color: #dbba34; +} +.dialog-warning:before { + position: absolute; + top: 0.5em; + left: 0.5em; + font-family: "ion"; + font-size: 1.5em; +} +.dialog-warning .close { + float: right; + position: relative; + top: -3px; + color: inherit; + font-size: 1.5em; +} +.dialog-warning ul, +.dialog-warning ol, +.dialog-warning p { + margin: 1px 0 0 0; +} +.dialog-warning:before { + content: "\f10f"; +} +.btn-collapse { + cursor: pointer; +} +.scrollx { + overflow-x: auto; + overflow-y: hidden; + display: block; + padding: 0; + margin: 0; + border: none; +} +.tabs .tabs > label { + font-size: 90%; +} +.tabs { + display: -webkit-box; + display: -moz-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + flex-wrap: wrap; + width: 100%; + min-width: 100%; +} +.tabs > * { + order: 2; +} +.tabs > input[type=radio] { + display: none; +} +.tabs > 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; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; +} +.tabs > label:hover { + border-bottom: 2px solid #084999; +} +.tabs > section { + min-width: 100%; + padding: 0.7rem 0; + box-sizing: border-box; + border-top: 1px solid black; + display: none; +} +.tabs > label:last-of-type { + border-bottom: 2px solid #084999; + background: #3498DB; + color: #FFF; + font-weight: bold; + letter-spacing: -0.1px; +} +.tabs > section:last-of-type { + display: block; +} +html body .tabs > input:checked ~ section { + display: none; +} +html body .tabs > input:checked ~ label { + position: inherited; + background: inherit; + border-bottom: 2px solid transparent; + font-weight: normal; + color: inherit; +} +html body .tabs > input:checked ~ label:hover { + border-bottom: 2px solid #084999; +} +html body .tabs > input:checked + label { + border-bottom: 2px solid #084999; + background: #3498DB; + color: #FFF; + font-weight: bold; + letter-spacing: -0.1px; +} +html body .tabs > input:checked + label + section { + display: block; +} +select { + height: 28px; + margin: 0 1em 0 0; + padding: 2px 8px 2px 0 !important; + color: #222; + font-size: 12px; + z-index: 2; +} +select:hover, +select: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; + } + select:hover, + select:focus { + border-bottom: 1px solid #3498DB; + } +} +@supports (border-radius: 50px) { + .checkbox-onoff { + display: inline-block; + width: 40px; + height: 10px; + background: #dcdcdc; + margin: 8px auto; + position: relative; + border-radius: 50px; + } + .checkbox-onoff 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; + } + .checkbox-onoff input[type=checkbox] { + visibility: hidden; + } + .checkbox-onoff input[type=checkbox]:checked + label { + left: -5px; + background: #dcdcdc; + } +} +@supports (transform: rotate(-45deg)) { + .checkbox { + width: 20px; + position: relative; + margin: 20px auto; + } + .checkbox 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); + } + .checkbox label: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); + } + .checkbox input[type=checkbox] { + visibility: hidden; + } + .checkbox input[type=checkbox]:checked + label:after { + border-color: #3498DB; + opacity: 1; + } + .checkbox input[disabled] + label { + background-color: transparent !important; + box-shadow: none !important; + cursor: inherit; + } + .checkbox input:not(:checked):not([readonly]):not([disabled]) + label:hover::after { + opacity: 0.5; + } +} +@media screen and (max-width: 50em) { + .tabs > label { + width: 100%; + } +} +.autocomplete { + position: absolute; + max-height: 0; + overflow-y: hidden; + text-align: left; +} +.autocomplete:active, +.autocomplete:focus, +.autocomplete:hover { + background-color: white; +} +.autocomplete:empty { + display: none; +} +.autocomplete > ul { + list-style-type: none; + margin: 0; + padding: 0; +} +.autocomplete > ul > li { + cursor: pointer; + padding: 5px 0 5px 10px; +} +.autocomplete > ul > li.active, +.autocomplete > ul > li:active, +.autocomplete > ul > li:focus { + background-color: #3498DB; +} +.autocomplete > ul > li.active a:active, +.autocomplete > ul > li:active a:active, +.autocomplete > ul > li:focus a:active, +.autocomplete > ul > li.active a:focus, +.autocomplete > ul > li:active a:focus, +.autocomplete > ul > li:focus a:focus, +.autocomplete > ul > li.active a:hover, +.autocomplete > ul > li:active a:hover, +.autocomplete > ul > li:focus a:hover { + text-decoration: none; +} +.autocomplete > ul > li.locked { + cursor: inherit; +} +.autocomplete.open { + display: block; + background-color: white; + border: 1px solid #3498DB; + max-height: 500px; + overflow-y: auto; + z-index: 100; +} +.autocomplete.open:empty { + display: none; +} +@media screen and (max-width: 50em) { + .autocomplete { + bottom: 0; + } + .autocomplete > ul > li { + padding: 7px 0 7px 10px; + border-bottom: 1px solid #E8E7E6; + text-align: left; + } +} +@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 { + 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; +} +.ion-icon:before { + font-family: "ion"; +} +.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"; +} +.ion-icon-big { + 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; + font-size: 149%; +} +.ion-icon-big:before { + font-family: "ion"; +} +.index { + text-align: center; +} +.index .title { + background: url('../img/searx.png') no-repeat; + width: 100%; + min-height: 80px; + background-position: center; +} +.index h1 { + font-size: 5em; + visibility: hidden; +} +.index #search { + margin: 0 auto; + background: inherit; + border: inherit; +} +.index .search_filters { + display: block; + margin: 1em 0; +} +.index .category label { + padding: 6px 10px; + border-bottom: initial !important; +} +@media screen and (max-width: 75em) { + div.title h1 { + font-size: 1em; + } +} +#main_preferences form { + width: 100%; +} +#main_preferences fieldset { + margin: 8px; + border: none; +} +#main_preferences legend { + margin: 0; + padding: 5px 0 0 0; + display: block; + float: left; + width: 300px; +} +#main_preferences .value { + margin: 0; + padding: 0; + float: left; + width: 15em; +} +#main_preferences .description { + margin: 0; + padding: 5px 0 0 0; + float: left; + width: 50%; + color: #909090; + font-size: 90%; +} +#main_preferences select { + width: 200px; + font-size: inherit !important; +} +#main_preferences table { + border-collapse: collapse; +} +#main_preferences table td { + text-align: center; +} +#main_preferences .name, +#main_preferences .shortcut { + text-align: left; +} +#main_preferences .preferences_back { + background: none repeat scroll 0 0 #3498DB; + color: white; + border: 0 none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + cursor: pointer; + display: inline-block; + margin: 2px 4px; + padding: 0.5em; +} +#main_preferences .preferences_back a { + display: block; + color: #FFF; +} +#main_preferences .preferences_back a::first-letter { + text-transform: uppercase; +} +@media screen and (max-width: 75em) { + .preferences_back { + clear: both; + } +} +/* +* 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 #FFF; + border: 1px solid #3498DB; + border-radius: 0px; + outline: none; + color: #222; + font-size: 16px; + z-index: 2; +} +#q { + outline: medium none; + padding-left: 8px; + padding-right: 0px !important; + border-right: none; + width: 40em; +} +#send_search { + border-left: none; + width: 2.2em; +} +#send_search:hover { + cursor: pointer; + background-color: #3498DB; + color: #ECF0F1; +} +.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; + } + #categories .checkbox_container { + margin-top: 2px; + margin: auto; + } + html.touch #main_index #categories_container, + html.touch #main_results #categories_container { + width: 1000px; + width: -moz-max-content; + width: -webkit-max-content; + width: max-content; + } + html.touch #main_index #categories_container .category, + html.touch #main_results #categories_container .category { + display: inline-block; + width: auto; + } + html.touch #main_index #categories, + html.touch #main_results #categories { + width: 100%; + margin: 0; + text-align: left; + overflow-x: scroll; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + } +} +@media screen and (max-width: 50em) { + #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 { + 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%; + } + .category label { + border-bottom: 0; + } +} +#categories { + margin: 0 10px 0 0; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#categories::-webkit-scrollbar { + width: 0; + height: 0; +} +.category { + display: inline-block; + position: relative; + margin: 0 3px; + padding: 0px; + /*label:hover { + border-bottom: 2px solid @color-categories-item-border-unselected-hover; + }*/ +} +.category input { + display: none; +} +.category label { + cursor: pointer; + padding: 4px 10px; + margin: 0; + display: block; + text-transform: capitalize; + font-size: 0.9em; + border-bottom: 2px solid transparent; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.category input[type="checkbox"]:focus + label { + box-shadow: 0px 0px 8px #3498DB; +} +.category input[type="checkbox"]:checked + label { + background: #3498DB; + color: #FFF; + border-bottom: 2px solid #084999; +} +#categories_container { + position: relative; +} +#categories_container .help { + position: absolute; + width: 100%; + bottom: -20px; + overflow: hidden; + opacity: 0; + transition: opacity 1s ease; + font-size: 0.8em; + text-position: center; + background: white; +} +#categories_container:hover .help { + opacity: 0.8; + transition: opacity 1s ease; +} +html { + font-family: arial, sans-serif; + font-size: 0.9em; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + text-size-adjust: 100%; + color: #444; + padding: 0; + margin: 0; +} +body, +main { + padding: 0; + margin: 0; +} +main { + width: 100%; +} +footer { + 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; +} +footer 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; +} +#main_preferences h1 span, +#main_stats h1 span { + visibility: hidden; +} +input[type="submit"], +#results button[type="submit"] { + padding: 0.5rem; + margin: 2px 4px; + display: inline-block; + background: #3498DB; + color: #FFF; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + border: 0; + cursor: pointer; +} +a { + text-decoration: none; + color: #29314d; +} +a:visited { + color: #684898; +} +a:visited .highlight { + color: #684898; +} +article[data-vim-selected] { + background: #f7f7f7; +} +article[data-vim-selected]::before { + position: absolute; + left: 1em; + padding: 2px; + content: ">"; + font-weight: bold; + color: #3498DB; +} +article.result-images[data-vim-selected] { + background: #3498DB; +} +article.result-images[data-vim-selected]::before { + display: none; + content: ""; +} +.result { + margin: 19px 0 18px 0; + padding: 0; +} +.result h3 { + font-size: 1.1em; + word-wrap: break-word; + margin: 5px 0 1px 0; + padding: 0; + margin-bottom: 0; +} +.result h3 a { + color: #084999; + font-weight: normal; + font-size: 1.1em; +} +.result h3 a:visited { + color: #684898; +} +.result h3 a:focus, +.result h3 a:hover { + text-decoration: underline; + border: none; + -webkit-box-shadow: none; + box-shadow: none; + outline: none; +} +.result .cache_link, +.result .proxyfied_link { + font-size: 0.9em !important; +} +.result .content, +.result .stat, +.result .altlink { + font-size: 0.9em; + margin: 0; + padding: 0; + max-width: 54em; + word-wrap: break-word; + line-height: 1.24; +} +.result .content .highlight, +.result .stat .highlight, +.result .altlink .highlight { + color: #000000; + background: inherit; + font-weight: bold; +} +.result .codelines .highlight { + color: inherit; + background: inherit; + font-weight: normal; +} +.result .url { + font-size: 0.9em; + margin: 0 0 3px 0; + padding: 0; + max-width: 54em; + word-wrap: break-word; + color: #25a55b; +} +.result .published_date { + font-size: 0.8em; + color: #888; +} +.result img.thumbnail { + float: left; + padding: 0 5px 10px 0; + width: 20em; + min-width: 20em; + min-height: 8em; +} +.result img.image { + float: left; + padding: 0 5px 10px 0; + width: 100px; + max-height: 100px; + object-fit: scale-down; + object-position: right top; +} +.result .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: #888; +} +.engines span { + font-size: smaller; + margin: 0 0.5em 0 0; +} +.small_font { + font-size: 0.8em; +} +.highlight { + color: #094089; + background: inherit; + font-weight: bold; +} +.result-images { + display: inline-block; + margin: 0; + padding: 0; + position: relative; + max-height: 200px; +} +.result-images img { + float: inherit; + margin: 0; + padding: 0; + border: none; + max-height: 200px; + background: #084999; +} +.result-images span a { + display: none; + color: #FFF; +} +.result-images:hover span a { + display: block; + position: absolute; + bottom: 0; + right: 0; + padding: 4px; + margin: 0 0 4px 4px; + background-color: rgba(0, 0, 0, 0.6); + font-size: 0.7em; +} +.torrent_result { + border-left: 10px solid lightgray; + padding-left: 3px; +} +.torrent_result p { + margin: 3px; + font-size: 0.8em; +} +.torrent_result a { + color: #084999; +} +.torrent_result a:hover { + text-decoration: underline; +} +.torrent_result a:visited { + color: #684898; +} +#results { + margin: 2em 2em 20px 2em; + padding: 0; + width: 50em; +} +#suggestions .wrapper { + display: flex; + flex-flow: row wrap; + justify-content: flex-end; +} +#suggestions .wrapper form { + display: inline-block; + flex: 1 1 50%; +} +#suggestions, +#answers, +#corrections { + max-width: 50em; +} +#suggestions input, +#answers input, +#infoboxes input, +#corrections input { + padding: 0; + margin: 3px; + font-size: 0.9em; + display: inline-block; + background: transparent; + color: #444; + cursor: pointer; +} +#suggestions input[type="submit"], +#answers input[type="submit"], +#infoboxes input[type="submit"], +#corrections input[type="submit"], +#suggestions .infobox .url a, +#answers .infobox .url a, +#infoboxes .infobox .url a, +#corrections .infobox .url a { + color: #084999; + text-decoration: none; + font-size: 0.9rem; +} +#suggestions input[type="submit"]:hover, +#answers input[type="submit"]:hover, +#infoboxes input[type="submit"]:hover, +#corrections input[type="submit"]:hover, +#suggestions .infobox .url a:hover, +#answers .infobox .url a:hover, +#infoboxes .infobox .url a:hover, +#corrections .infobox .url a:hover { + text-decoration: underline; +} +#corrections { + display: flex; + flex-flow: row wrap; + margin: 1em 0; +} +#corrections h4, +#corrections input[type="submit"] { + display: inline-block; + margin: 0 0.5em 0 0; +} +#corrections input[type="submit"]::after { + content: ", "; +} +#suggestions .title, +#search_url .title, +#apis .title { + margin: 2em 0 0.5em 0; + color: #444; +} +#answers { + margin: 10px 8px 10px 8px; + border: 1px solid #ddd; + padding: 0.9em; + box-shadow: 0px 0px 5px #CCC; +} +#answers h4 { + display: none; +} +#answers .answer { + display: block; + font-size: 1.2em; + font-weight: bold; +} +#answers form, +#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; +} +#sidebar .infobox { + margin: 10px 0 10px; + border: 1px solid #ddd; + padding: 0.9em; + font-size: 0.9em; + box-shadow: 0px 0px 5px #CCC; +} +#sidebar .infobox h2 { + margin: 0 0 .5em 0; +} +#sidebar .infobox img { + max-width: 100%; + max-height: 12em; + display: block; + margin: 0; + padding: 0; +} +#sidebar .infobox dl { + margin: 0.5em 0; +} +#sidebar .infobox dt { + display: inline; + margin: 0.5em 0.25em 0.5em 0; + padding: 0; + font-weight: bold; +} +#sidebar .infobox dd { + display: inline; + margin: 0.5em 0; + padding: 0; +} +#sidebar .infobox input { + font-size: 1em; +} +#sidebar .infobox br { + clear: both; +} +#sidebar .infobox .attributes, +#sidebar .infobox .urls { + clear: both; +} +#search_url { + margin-top: 8px; +} +#search_url div { + border: 1px solid #888; + padding: 4px; + color: #444; + width: 100%; + display: block; + margin: 0.1em; + overflow: hidden; + height: 1.2em; + line-height: 1.2em; +} +#search_url div pre { + display: block; + width: 200em; + font-size: 0.8em; + word-break: break-all; + margin: 0.1em; + -webkit-user-select: all; + -moz-user-select: all; + -ms-user-select: all; + user-select: all; +} +#linkto_preferences { + position: absolute; + right: 10px; + top: 0.9em; + padding: 0; + border: 0; + display: block; + font-size: 1.2em; + color: #222; +} +#linkto_preferences a:link *, +#linkto_preferences a:hover *, +#linkto_preferences a:visited *, +#linkto_preferences a:active * { + color: #222; +} +#pagination { + clear: both; +} +#pagination 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: 50em; + transition: opacity 0.5s; + opacity: 0; +} +#backToTop 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; + } + #infoboxes .infobox { + clear: both; + } + #infoboxes .infobox img { + float: left; + max-width: 10em; + margin: 0.5em 0.5em 0.5em 0; + } + #sidebar { + position: static; + max-width: 50em; + margin: 0 0 2px 0; + padding: 0; + float: none; + border: none; + width: auto; + } + #sidebar input { + border: 0; + } + #apis { + display: none; + } + #search_url { + display: none; + } + .result { + border-bottom: 1px solid #E8E7E6; + margin: 0; + padding-top: 8px; + padding-bottom: 6px; + } + .result h3 { + margin: 0 0 1px 0; + } + .result .thumbnail { + max-width: 98%; + } + .result .url span.url { + display: block; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + width: 100%; + } + .result .url a { + float: right; + padding: 0 0.5em; + } + .result .engines { + float: right; + padding: 0 0 3px 0; + } + .result-images { + border-bottom: none !important; + } + .image_result { + max-width: 98%; + } + .image_result img { + max-width: 98%; + } +} +@media screen and (max-width: 50em) { + 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; + } + .result-videos .content { + overflow: inherit; + } +} +#search_submit { + left: 1px; + right: auto; +} diff --git a/searx/static/themes/simple/css/searx-rtl.min.css b/searx/static/themes/simple/css/searx-rtl.min.css new file mode 100644 index 000000000..16d03f1e3 Binary files /dev/null and b/searx/static/themes/simple/css/searx-rtl.min.css differ diff --git a/searx/static/themes/simple/css/searx.css b/searx/static/themes/simple/css/searx.css new file mode 100644 index 000000000..b276bc59a --- /dev/null +++ b/searx/static/themes/simple/css/searx.css @@ -0,0 +1,2045 @@ +/*! searx | 06-08-2017 | https://github.com/asciimoo/searx */ +/* +* searx, A privacy-respecting, hackable metasearch engine +* +* To convert "style.less" to "style.css" run: $make styles +*/ +/*! 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"], +[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, +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; +} +/* + * searx, A privacy-respecting, hackable metasearch engine + * + * To change the colors of the site, simple edit this variables + */ +/* +* searx, A privacy-respecting, hackable metasearch engine +*/ +.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; +} +.highlight .lineno::selection { + background: transparent; + /* WebKit/Blink Browsers */ +} +.highlight .lineno::-moz-selection { + background: transparent; + /* Gecko Browsers */ +} +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: #fae1e1; +} +.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 { + width: 100%; +} +table.striped tr { + border-bottom: 1px solid #ececec; +} +th { + padding: 0.4em; +} +td { + padding: 0 4px; +} +tr:hover { + background: #ececec; +} +.dialog-error { + 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; + color: #db3434; + background: #fae1e1; + border-color: #db3434; +} +.dialog-error:before { + position: absolute; + top: 0.5em; + left: 0.5em; + font-family: "ion"; + font-size: 1.5em; +} +.dialog-error .close { + float: right; + position: relative; + top: -3px; + color: inherit; + font-size: 1.5em; +} +.dialog-error ul, +.dialog-error ol, +.dialog-error p { + margin: 1px 0 0 0; +} +.dialog-error:before { + content: "\f110"; +} +.dialog-warning { + 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; + color: #dbba34; + background: #faf5e1; + border-color: #dbba34; +} +.dialog-warning:before { + position: absolute; + top: 0.5em; + left: 0.5em; + font-family: "ion"; + font-size: 1.5em; +} +.dialog-warning .close { + float: right; + position: relative; + top: -3px; + color: inherit; + font-size: 1.5em; +} +.dialog-warning ul, +.dialog-warning ol, +.dialog-warning p { + margin: 1px 0 0 0; +} +.dialog-warning:before { + content: "\f10f"; +} +.btn-collapse { + cursor: pointer; +} +.scrollx { + overflow-x: auto; + overflow-y: hidden; + display: block; + padding: 0; + margin: 0; + border: none; +} +.tabs .tabs > label { + font-size: 90%; +} +.tabs { + display: -webkit-box; + display: -moz-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + flex-wrap: wrap; + width: 100%; + min-width: 100%; +} +.tabs > * { + order: 2; +} +.tabs > input[type=radio] { + display: none; +} +.tabs > 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; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; +} +.tabs > label:hover { + border-bottom: 2px solid #084999; +} +.tabs > section { + min-width: 100%; + padding: 0.7rem 0; + box-sizing: border-box; + border-top: 1px solid black; + display: none; +} +.tabs > label:last-of-type { + border-bottom: 2px solid #084999; + background: #3498DB; + color: #FFF; + font-weight: bold; + letter-spacing: -0.1px; +} +.tabs > section:last-of-type { + display: block; +} +html body .tabs > input:checked ~ section { + display: none; +} +html body .tabs > input:checked ~ label { + position: inherited; + background: inherit; + border-bottom: 2px solid transparent; + font-weight: normal; + color: inherit; +} +html body .tabs > input:checked ~ label:hover { + border-bottom: 2px solid #084999; +} +html body .tabs > input:checked + label { + border-bottom: 2px solid #084999; + background: #3498DB; + color: #FFF; + font-weight: bold; + letter-spacing: -0.1px; +} +html body .tabs > input:checked + label + section { + display: block; +} +select { + height: 28px; + margin: 0 1em 0 0; + padding: 2px 8px 2px 0 !important; + color: #222; + font-size: 12px; + z-index: 2; +} +select:hover, +select: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; + } + select:hover, + select:focus { + border-bottom: 1px solid #3498DB; + } +} +@supports (border-radius: 50px) { + .checkbox-onoff { + display: inline-block; + width: 40px; + height: 10px; + background: #dcdcdc; + margin: 8px auto; + position: relative; + border-radius: 50px; + } + .checkbox-onoff 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; + } + .checkbox-onoff input[type=checkbox] { + visibility: hidden; + } + .checkbox-onoff input[type=checkbox]:checked + label { + left: -5px; + background: #dcdcdc; + } +} +@supports (transform: rotate(-45deg)) { + .checkbox { + width: 20px; + position: relative; + margin: 20px auto; + } + .checkbox 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); + } + .checkbox label: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); + } + .checkbox input[type=checkbox] { + visibility: hidden; + } + .checkbox input[type=checkbox]:checked + label:after { + border-color: #3498DB; + opacity: 1; + } + .checkbox input[disabled] + label { + background-color: transparent !important; + box-shadow: none !important; + cursor: inherit; + } + .checkbox input:not(:checked):not([readonly]):not([disabled]) + label:hover::after { + opacity: 0.5; + } +} +@media screen and (max-width: 50em) { + .tabs > label { + width: 100%; + } +} +.autocomplete { + position: absolute; + max-height: 0; + overflow-y: hidden; + text-align: left; +} +.autocomplete:active, +.autocomplete:focus, +.autocomplete:hover { + background-color: white; +} +.autocomplete:empty { + display: none; +} +.autocomplete > ul { + list-style-type: none; + margin: 0; + padding: 0; +} +.autocomplete > ul > li { + cursor: pointer; + padding: 5px 0 5px 10px; +} +.autocomplete > ul > li.active, +.autocomplete > ul > li:active, +.autocomplete > ul > li:focus { + background-color: #3498DB; +} +.autocomplete > ul > li.active a:active, +.autocomplete > ul > li:active a:active, +.autocomplete > ul > li:focus a:active, +.autocomplete > ul > li.active a:focus, +.autocomplete > ul > li:active a:focus, +.autocomplete > ul > li:focus a:focus, +.autocomplete > ul > li.active a:hover, +.autocomplete > ul > li:active a:hover, +.autocomplete > ul > li:focus a:hover { + text-decoration: none; +} +.autocomplete > ul > li.locked { + cursor: inherit; +} +.autocomplete.open { + display: block; + background-color: white; + border: 1px solid #3498DB; + max-height: 500px; + overflow-y: auto; + z-index: 100; +} +.autocomplete.open:empty { + display: none; +} +@media screen and (max-width: 50em) { + .autocomplete { + bottom: 0; + } + .autocomplete > ul > li { + padding: 7px 0 7px 10px; + border-bottom: 1px solid #E8E7E6; + text-align: left; + } +} +@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 { + 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; +} +.ion-icon:before { + font-family: "ion"; +} +.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"; +} +.ion-icon-big { + 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; + font-size: 149%; +} +.ion-icon-big:before { + font-family: "ion"; +} +.index { + text-align: center; +} +.index .title { + background: url('../img/searx.png') no-repeat; + width: 100%; + min-height: 80px; + background-position: center; +} +.index h1 { + font-size: 5em; + visibility: hidden; +} +.index #search { + margin: 0 auto; + background: inherit; + border: inherit; +} +.index .search_filters { + display: block; + margin: 1em 0; +} +.index .category label { + padding: 6px 10px; + border-bottom: initial !important; +} +@media screen and (max-width: 75em) { + div.title h1 { + font-size: 1em; + } +} +#main_preferences form { + width: 100%; +} +#main_preferences fieldset { + margin: 8px; + border: none; +} +#main_preferences legend { + margin: 0; + padding: 5px 0 0 0; + display: block; + float: left; + width: 300px; +} +#main_preferences .value { + margin: 0; + padding: 0; + float: left; + width: 15em; +} +#main_preferences .description { + margin: 0; + padding: 5px 0 0 0; + float: left; + width: 50%; + color: #909090; + font-size: 90%; +} +#main_preferences select { + width: 200px; + font-size: inherit !important; +} +#main_preferences table { + border-collapse: collapse; +} +#main_preferences table td { + text-align: center; +} +#main_preferences .name, +#main_preferences .shortcut { + text-align: left; +} +#main_preferences .preferences_back { + background: none repeat scroll 0 0 #3498DB; + color: white; + border: 0 none; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + cursor: pointer; + display: inline-block; + margin: 2px 4px; + padding: 0.5em; +} +#main_preferences .preferences_back a { + display: block; + color: #FFF; +} +#main_preferences .preferences_back a::first-letter { + text-transform: uppercase; +} +@media screen and (max-width: 75em) { + .preferences_back { + clear: both; + } +} +/* +* 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 #FFF; + border: 1px solid #3498DB; + border-radius: 0px; + outline: none; + color: #222; + font-size: 16px; + z-index: 2; +} +#q { + outline: medium none; + padding-left: 8px; + padding-right: 0px !important; + border-right: none; + width: 40em; +} +#send_search { + border-left: none; + width: 2.2em; +} +#send_search:hover { + cursor: pointer; + background-color: #3498DB; + color: #ECF0F1; +} +.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; + } + #categories .checkbox_container { + margin-top: 2px; + margin: auto; + } + html.touch #main_index #categories_container, + html.touch #main_results #categories_container { + width: 1000px; + width: -moz-max-content; + width: -webkit-max-content; + width: max-content; + } + html.touch #main_index #categories_container .category, + html.touch #main_results #categories_container .category { + display: inline-block; + width: auto; + } + html.touch #main_index #categories, + html.touch #main_results #categories { + width: 100%; + margin: 0; + text-align: left; + overflow-x: scroll; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + } +} +@media screen and (max-width: 50em) { + #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 { + 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%; + } + .category label { + border-bottom: 0; + } +} +#categories { + margin: 0 10px 0 0; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +#categories::-webkit-scrollbar { + width: 0; + height: 0; +} +.category { + display: inline-block; + position: relative; + margin: 0 3px; + padding: 0px; + /*label:hover { + border-bottom: 2px solid @color-categories-item-border-unselected-hover; + }*/ +} +.category input { + display: none; +} +.category label { + cursor: pointer; + padding: 4px 10px; + margin: 0; + display: block; + text-transform: capitalize; + font-size: 0.9em; + border-bottom: 2px solid transparent; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.category input[type="checkbox"]:focus + label { + box-shadow: 0px 0px 8px #3498DB; +} +.category input[type="checkbox"]:checked + label { + background: #3498DB; + color: #FFF; + border-bottom: 2px solid #084999; +} +#categories_container { + position: relative; +} +#categories_container .help { + position: absolute; + width: 100%; + bottom: -20px; + overflow: hidden; + opacity: 0; + transition: opacity 1s ease; + font-size: 0.8em; + text-position: center; + background: white; +} +#categories_container:hover .help { + opacity: 0.8; + transition: opacity 1s ease; +} +html { + font-family: arial, sans-serif; + font-size: 0.9em; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + text-size-adjust: 100%; + color: #444; + padding: 0; + margin: 0; +} +body, +main { + padding: 0; + margin: 0; +} +main { + width: 100%; +} +footer { + 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; +} +footer 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; +} +#main_preferences h1 span, +#main_stats h1 span { + visibility: hidden; +} +input[type="submit"], +#results button[type="submit"] { + padding: 0.5rem; + margin: 2px 4px; + display: inline-block; + background: #3498DB; + color: #FFF; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + border: 0; + cursor: pointer; +} +a { + text-decoration: none; + color: #29314d; +} +a:visited { + color: #684898; +} +a:visited .highlight { + color: #684898; +} +article[data-vim-selected] { + background: #f7f7f7; +} +article[data-vim-selected]::before { + position: absolute; + left: 1em; + padding: 2px; + content: ">"; + font-weight: bold; + color: #3498DB; +} +article.result-images[data-vim-selected] { + background: #3498DB; +} +article.result-images[data-vim-selected]::before { + display: none; + content: ""; +} +.result { + margin: 19px 0 18px 0; + padding: 0; +} +.result h3 { + font-size: 1.1em; + word-wrap: break-word; + margin: 5px 0 1px 0; + padding: 0; + margin-bottom: 0; +} +.result h3 a { + color: #084999; + font-weight: normal; + font-size: 1.1em; +} +.result h3 a:visited { + color: #684898; +} +.result h3 a:focus, +.result h3 a:hover { + text-decoration: underline; + border: none; + -webkit-box-shadow: none; + box-shadow: none; + outline: none; +} +.result .cache_link, +.result .proxyfied_link { + font-size: 0.9em !important; +} +.result .content, +.result .stat, +.result .altlink { + font-size: 0.9em; + margin: 0; + padding: 0; + max-width: 54em; + word-wrap: break-word; + line-height: 1.24; +} +.result .content .highlight, +.result .stat .highlight, +.result .altlink .highlight { + color: #000000; + background: inherit; + font-weight: bold; +} +.result .codelines .highlight { + color: inherit; + background: inherit; + font-weight: normal; +} +.result .url { + font-size: 0.9em; + margin: 0 0 3px 0; + padding: 0; + max-width: 54em; + word-wrap: break-word; + color: #25a55b; +} +.result .published_date { + font-size: 0.8em; + color: #888; +} +.result img.thumbnail { + float: left; + padding: 0 5px 10px 0; + width: 20em; + min-width: 20em; + min-height: 8em; +} +.result img.image { + float: left; + padding: 0 5px 10px 0; + width: 100px; + max-height: 100px; + object-fit: scale-down; + object-position: right top; +} +.result .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: #888; +} +.engines span { + font-size: smaller; + margin: 0 0.5em 0 0; +} +.small_font { + font-size: 0.8em; +} +.highlight { + color: #094089; + background: inherit; + font-weight: bold; +} +.result-images { + display: inline-block; + margin: 0; + padding: 0; + position: relative; + max-height: 200px; +} +.result-images img { + float: inherit; + margin: 0; + padding: 0; + border: none; + max-height: 200px; + background: #084999; +} +.result-images span a { + display: none; + color: #FFF; +} +.result-images:hover span a { + display: block; + position: absolute; + bottom: 0; + right: 0; + padding: 4px; + margin: 0 0 4px 4px; + background-color: rgba(0, 0, 0, 0.6); + font-size: 0.7em; +} +.torrent_result { + border-left: 10px solid lightgray; + padding-left: 3px; +} +.torrent_result p { + margin: 3px; + font-size: 0.8em; +} +.torrent_result a { + color: #084999; +} +.torrent_result a:hover { + text-decoration: underline; +} +.torrent_result a:visited { + color: #684898; +} +#results { + margin: 2em 2em 20px 2em; + padding: 0; + width: 50em; +} +#suggestions .wrapper { + display: flex; + flex-flow: row wrap; + justify-content: flex-end; +} +#suggestions .wrapper form { + display: inline-block; + flex: 1 1 50%; +} +#suggestions, +#answers, +#corrections { + max-width: 50em; +} +#suggestions input, +#answers input, +#infoboxes input, +#corrections input { + padding: 0; + margin: 3px; + font-size: 0.9em; + display: inline-block; + background: transparent; + color: #444; + cursor: pointer; +} +#suggestions input[type="submit"], +#answers input[type="submit"], +#infoboxes input[type="submit"], +#corrections input[type="submit"], +#suggestions .infobox .url a, +#answers .infobox .url a, +#infoboxes .infobox .url a, +#corrections .infobox .url a { + color: #084999; + text-decoration: none; + font-size: 0.9rem; +} +#suggestions input[type="submit"]:hover, +#answers input[type="submit"]:hover, +#infoboxes input[type="submit"]:hover, +#corrections input[type="submit"]:hover, +#suggestions .infobox .url a:hover, +#answers .infobox .url a:hover, +#infoboxes .infobox .url a:hover, +#corrections .infobox .url a:hover { + text-decoration: underline; +} +#corrections { + display: flex; + flex-flow: row wrap; + margin: 1em 0; +} +#corrections h4, +#corrections input[type="submit"] { + display: inline-block; + margin: 0 0.5em 0 0; +} +#corrections input[type="submit"]::after { + content: ", "; +} +#suggestions .title, +#search_url .title, +#apis .title { + margin: 2em 0 0.5em 0; + color: #444; +} +#answers { + margin: 10px 8px 10px 8px; + border: 1px solid #ddd; + padding: 0.9em; + box-shadow: 0px 0px 5px #CCC; +} +#answers h4 { + display: none; +} +#answers .answer { + display: block; + font-size: 1.2em; + font-weight: bold; +} +#answers form, +#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; +} +#sidebar .infobox { + margin: 10px 0 10px; + border: 1px solid #ddd; + padding: 0.9em; + font-size: 0.9em; + box-shadow: 0px 0px 5px #CCC; +} +#sidebar .infobox h2 { + margin: 0 0 .5em 0; +} +#sidebar .infobox img { + max-width: 100%; + max-height: 12em; + display: block; + margin: 0; + padding: 0; +} +#sidebar .infobox dl { + margin: 0.5em 0; +} +#sidebar .infobox dt { + display: inline; + margin: 0.5em 0.25em 0.5em 0; + padding: 0; + font-weight: bold; +} +#sidebar .infobox dd { + display: inline; + margin: 0.5em 0; + padding: 0; +} +#sidebar .infobox input { + font-size: 1em; +} +#sidebar .infobox br { + clear: both; +} +#sidebar .infobox .attributes, +#sidebar .infobox .urls { + clear: both; +} +#search_url { + margin-top: 8px; +} +#search_url div { + border: 1px solid #888; + padding: 4px; + color: #444; + width: 100%; + display: block; + margin: 0.1em; + overflow: hidden; + height: 1.2em; + line-height: 1.2em; +} +#search_url div pre { + display: block; + width: 200em; + font-size: 0.8em; + word-break: break-all; + margin: 0.1em; + -webkit-user-select: all; + -moz-user-select: all; + -ms-user-select: all; + user-select: all; +} +#linkto_preferences { + position: absolute; + right: 10px; + top: 0.9em; + padding: 0; + border: 0; + display: block; + font-size: 1.2em; + color: #222; +} +#linkto_preferences a:link *, +#linkto_preferences a:hover *, +#linkto_preferences a:visited *, +#linkto_preferences a:active * { + color: #222; +} +#pagination { + clear: both; +} +#pagination 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: 50em; + transition: opacity 0.5s; + opacity: 0; +} +#backToTop 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; + } + #infoboxes .infobox { + clear: both; + } + #infoboxes .infobox img { + float: left; + max-width: 10em; + margin: 0.5em 0.5em 0.5em 0; + } + #sidebar { + position: static; + max-width: 50em; + margin: 0 0 2px 0; + padding: 0; + float: none; + border: none; + width: auto; + } + #sidebar input { + border: 0; + } + #apis { + display: none; + } + #search_url { + display: none; + } + .result { + border-bottom: 1px solid #E8E7E6; + margin: 0; + padding-top: 8px; + padding-bottom: 6px; + } + .result h3 { + margin: 0 0 1px 0; + } + .result .thumbnail { + max-width: 98%; + } + .result .url span.url { + display: block; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + width: 100%; + } + .result .url a { + float: right; + padding: 0 0.5em; + } + .result .engines { + float: right; + padding: 0 0 3px 0; + } + .result-images { + border-bottom: none !important; + } + .image_result { + max-width: 98%; + } + .image_result img { + max-width: 98%; + } +} +@media screen and (max-width: 50em) { + 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; + } + .result-videos .content { + overflow: inherit; + } +} diff --git a/searx/static/themes/simple/css/searx.min.css b/searx/static/themes/simple/css/searx.min.css new file mode 100644 index 000000000..0513de2b0 Binary files /dev/null and b/searx/static/themes/simple/css/searx.min.css differ diff --git a/searx/static/themes/simple/fonts/ion.css b/searx/static/themes/simple/fonts/ion.css new file mode 100644 index 000000000..b1b599a13 --- /dev/null +++ b/searx/static/themes/simple/fonts/ion.css @@ -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"; +} diff --git a/searx/static/themes/simple/fonts/ion.eot b/searx/static/themes/simple/fonts/ion.eot new file mode 100644 index 000000000..f4fc07ec6 Binary files /dev/null and b/searx/static/themes/simple/fonts/ion.eot differ diff --git a/searx/static/themes/simple/fonts/ion.html b/searx/static/themes/simple/fonts/ion.html new file mode 100644 index 000000000..defea2647 --- /dev/null +++ b/searx/static/themes/simple/fonts/ion.html @@ -0,0 +1,261 @@ + + + + + ion + + + +

ion

+ +
+ +
ion-navicon-round
+ +
ion-search
+ +
ion-play
+ +
ion-link
+ +
ion-chevron-up
+ +
ion-chevron-left
+ +
ion-chevron-right
+ +
ion-arrow-down-a
+ +
ion-arrow-up-a
+ +
ion-arrow-swap
+ +
ion-arrow-dropdown
+ +
ion-globe
+ +
ion-time
+ +
ion-location
+ +
ion-warning
+ +
ion-error
+ +
ion-film-outline
+ +
ion-music-note
+ +
ion-more-vertical
+ +
ion-magnet
+ +
+ + + +

Usage

+
<i class="ion-icon ion-name"></i>
+ + + + + + + diff --git a/searx/static/themes/simple/fonts/ion.svg b/searx/static/themes/simple/fonts/ion.svg new file mode 100644 index 000000000..db43668d4 Binary files /dev/null and b/searx/static/themes/simple/fonts/ion.svg differ diff --git a/searx/static/themes/simple/fonts/ion.ttf b/searx/static/themes/simple/fonts/ion.ttf new file mode 100644 index 000000000..4631e91b8 Binary files /dev/null and b/searx/static/themes/simple/fonts/ion.ttf differ diff --git a/searx/static/themes/simple/fonts/ion.woff b/searx/static/themes/simple/fonts/ion.woff new file mode 100644 index 000000000..767c1263a Binary files /dev/null and b/searx/static/themes/simple/fonts/ion.woff differ diff --git a/searx/static/themes/simple/fonts/ion.woff2 b/searx/static/themes/simple/fonts/ion.woff2 new file mode 100644 index 000000000..377710b51 Binary files /dev/null and b/searx/static/themes/simple/fonts/ion.woff2 differ diff --git a/searx/static/themes/simple/gruntfile.js b/searx/static/themes/simple/gruntfile.js new file mode 100644 index 000000000..288ab6633 --- /dev/null +++ b/searx/static/themes/simple/gruntfile.js @@ -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']); +}; diff --git a/searx/static/themes/simple/img/favicon.png b/searx/static/themes/simple/img/favicon.png new file mode 100644 index 000000000..36be5fc01 Binary files /dev/null and b/searx/static/themes/simple/img/favicon.png differ diff --git a/searx/static/themes/simple/img/loader.gif b/searx/static/themes/simple/img/loader.gif new file mode 100644 index 000000000..419cdeeda Binary files /dev/null and b/searx/static/themes/simple/img/loader.gif differ diff --git a/searx/static/themes/simple/img/logo_searx_a.png b/searx/static/themes/simple/img/logo_searx_a.png new file mode 100644 index 000000000..2db081710 Binary files /dev/null and b/searx/static/themes/simple/img/logo_searx_a.png differ diff --git a/searx/static/themes/simple/img/searx.png b/searx/static/themes/simple/img/searx.png new file mode 100644 index 000000000..98538da3a Binary files /dev/null and b/searx/static/themes/simple/img/searx.png differ diff --git a/searx/static/themes/simple/img/searx_logo.svg b/searx/static/themes/simple/img/searx_logo.svg new file mode 100644 index 000000000..67a2d4588 Binary files /dev/null and b/searx/static/themes/simple/img/searx_logo.svg differ diff --git a/searx/static/themes/simple/js/searx.js b/searx/static/themes/simple/js/searx.js new file mode 100644 index 000000000..64329fde1 --- /dev/null +++ b/searx/static/themes/simple/js/searx.js @@ -0,0 +1,1534 @@ +/** +* 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, +* +*/ +(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); +;(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 @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 "" + value + ""; + } + }, + 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) +}); +;/** +* +* Google Image Layout v0.0.1 +* Description, by Anh Trinh. +* Heavily modified for searx +* http://trinhtrunganh.com +* +* @license Free to use under the MIT License. +* +*/ +(function(w, d) { + 'use strict'; + + function ImageLayout(container_selector, results_selector, img_selector, maxHeight) { + this.container_selector = container_selector; + this.results_selector = results_selector; + this.img_selector = img_selector; + this.margin = 10; + this.maxHeight = maxHeight; + this._alignAllDone = true; + } + + /** + * Get the height that make all images fit the container + * + * width = w1 + w2 + w3 + ... = r1*h + r2*h + r3*h + ... + * + * @param {[type]} images the images to be calculated + * @param {[type]} width the container witdth + * @param {[type]} margin the margin between each image + * + * @return {[type]} the height + */ + ImageLayout.prototype._getHeigth = function(images, width) { + var r = 0, + img; + + width -= images.length * this.margin; + for (var i = 0; i < images.length; i++) { + img = images[i]; + if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { + r += img.naturalWidth / img.naturalHeight; + } else { + // assume that not loaded images are square + r += 1; + } + } + + return width / r; //have to round down because Firefox will automatically roundup value with number of decimals > 3 + }; + + ImageLayout.prototype._setSize = function(images, height) { + var img, imgWidth, imagesLength = images.length; + for (var i = 0; i < imagesLength; i++) { + img = images[i]; + if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) { + imgWidth = height * img.naturalWidth / img.naturalHeight; + } else { + // not loaded image : make it square as _getHeigth said it + imgWidth = height; + } + img.style.width = imgWidth + 'px'; + img.style.height = height + 'px'; + img.style.marginLeft = '3px'; + img.style.marginTop = '3px'; + img.style.marginRight = this.margin - 7 + 'px'; // -4 is the negative margin of the inline element + img.style.marginBottom = this.margin - 7 + 'px'; + } + }; + + ImageLayout.prototype._alignImgs = function(imgGroup) { + var slice, h, + containerWidth = d.querySelector(this.container_selector).clientWidth; + + w: while (imgGroup.length > 0) { + for (var i = 1; i <= imgGroup.length; i++) { + slice = imgGroup.slice(0, i); + h = this._getHeigth(slice, containerWidth); + if (h < this.maxHeight) { + this._setSize(slice, h); + imgGroup = imgGroup.slice(i); + continue w; + } + } + this._setSize(slice, Math.min(this.maxHeight, h)); + break; + } + }; + + ImageLayout.prototype.align = function(results_selector) { + var results_selectorNode = d.querySelectorAll(this.results_selector), + results_length = results_selectorNode.length, + previous = null, + current = null, + imgGroup = []; + for (var i = 0; i < results_length; i++) { + current = results_selectorNode[i]; + if (current.previousElementSibling !== previous && imgGroup.length > 0) { + // the current image is not conected to previous one + // so the current image is the start of a new group of images. + // so call _alignImgs to align the current group + this._alignImgs(imgGroup); + // and start a new empty group of images + imgGroup = []; + } + // add the current image to the group (only the img tag) + imgGroup.push(current.querySelector(this.img_selector)); + // update the previous variable + previous = current; + } + // align the remaining images + if (imgGroup.length > 0) { + this._alignImgs(imgGroup); + } + }; + + ImageLayout.prototype.watch = function() { + var i, img, imgGroup, imgNodeLength, + obj = this, + results_nodes = d.querySelectorAll(this.results_selector), + results_length = results_nodes.length; + + function align(e) { + obj.align(); + } + + function throttleAlign(e) { + if (obj._alignAllDone) { + obj._alignAllDone = false; + setTimeout(function() { + obj.align(); + obj._alignAllDone = true; + }, 100); + } + } + + w.addEventListener('resize', throttleAlign); + w.addEventListener('pageshow', align); + + for (i = 0; i < results_length; i++) { + img = results_nodes[i].querySelector(this.img_selector); + if (typeof img !== 'undefined') { + img.addEventListener('load', throttleAlign); + img.addEventListener('error', throttleAlign); + } + } + }; + + w.searx.ImageLayout = ImageLayout; + +})(window, document); +;searx.ready(function() { + + searx.on('.result', 'click', function() { + 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 = '
'; + html += '
'; + + html += '
'; + html += '
'; + html += '

How to navigate searx with Vim-like hotkeys

'; + html += '
'; // col-sm-12 + html += '
'; // 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 += '
'; + } + html += '
'; + + html += '
'; + html += '
' + cat[0].cat + '
'; + html += '
'; + html += '
    '; + + for (var cj in cat) { + html += '
  • ' + cat[cj].key + ' ' + cat[cj].des + '
  • '; + } + + html += '
'; + html += '
'; // panel-body + html += '
'; // panel + html += '
'; // col-sm-* + + if (!first || lastCategory) { + html += '
'; // row + } + } + + html += '
'; // container-fluid + html += '
'; // vim-hotkeys-help + + $('body').append(html); + } +}); +;/** +* 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, +* (C) 2017 by Alexandre Flament, +*/ +(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 += "" + row + ""; + switch(row) { + case "phone": + case "fax": + newHtml += "" + element.tags[row] + ""; + break; + case "email": + newHtml += "" + element.tags[row] + ""; + break; + case "website": + case "url": + newHtml += "" + element.tags[row] + ""; + break; + case "wikidata": + newHtml += "" + element.tags[row] + ""; + break; + case "wikipedia": + if(element.tags[row].indexOf(":") != -1) { + newHtml += "" + element.tags[row] + ""; + break; + } + /* jshint ignore:start */ + default: + /* jshint ignore:end */ + newHtml += element.tags[row]; + break; + } + newHtml += ""; + } + } + 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 + "

could not load data!

"; + }); + } + } + + // 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 © OpenStreetMap 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 © OpenStreetMap 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); +;/** +* 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, +*/ +(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); +;/** +* 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, +*/ +(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. +* +* (C) 2017 by Alexandre Flament, +* +*/ +(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); diff --git a/searx/static/themes/simple/js/searx_src/autocomplete.js b/searx/static/themes/simple/js/searx_src/autocomplete.js new file mode 100644 index 000000000..b95fbcfb2 --- /dev/null +++ b/searx/static/themes/simple/js/searx_src/autocomplete.js @@ -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 @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 "" + value + ""; + } + }, + 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) +}); diff --git a/searx/static/themes/simple/js/searx_src/searx_imageresult.js b/searx/static/themes/simple/js/searx_src/searx_imageresult.js new file mode 100644 index 000000000..7bbfc1454 --- /dev/null +++ b/searx/static/themes/simple/js/searx_src/searx_imageresult.js @@ -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); diff --git a/searx/static/themes/simple/js/searx_src/searx_keyboard.js b/searx/static/themes/simple/js/searx_src/searx_keyboard.js new file mode 100644 index 000000000..6365b5243 --- /dev/null +++ b/searx/static/themes/simple/js/searx_src/searx_keyboard.js @@ -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 = '
'; + html += '
'; + + html += '
'; + html += '
'; + html += '

How to navigate searx with Vim-like hotkeys

'; + html += '
'; // col-sm-12 + html += '
'; // 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 += '
'; + } + html += '
'; + + html += '
'; + html += '
' + cat[0].cat + '
'; + html += '
'; + html += '
    '; + + for (var cj in cat) { + html += '
  • ' + cat[cj].key + ' ' + cat[cj].des + '
  • '; + } + + html += '
'; + html += '
'; // panel-body + html += '
'; // panel + html += '
'; // col-sm-* + + if (!first || lastCategory) { + html += '
'; // row + } + } + + html += '
'; // container-fluid + html += '
'; // vim-hotkeys-help + + $('body').append(html); + } +}); diff --git a/searx/static/themes/simple/js/searx_src/searx_mapresult.js b/searx/static/themes/simple/js/searx_src/searx_mapresult.js new file mode 100644 index 000000000..823f64815 --- /dev/null +++ b/searx/static/themes/simple/js/searx_src/searx_mapresult.js @@ -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, +* (C) 2017 by Alexandre Flament, +*/ +(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 += "" + row + ""; + switch(row) { + case "phone": + case "fax": + newHtml += "" + element.tags[row] + ""; + break; + case "email": + newHtml += "" + element.tags[row] + ""; + break; + case "website": + case "url": + newHtml += "" + element.tags[row] + ""; + break; + case "wikidata": + newHtml += "" + element.tags[row] + ""; + break; + case "wikipedia": + if(element.tags[row].indexOf(":") != -1) { + newHtml += "" + element.tags[row] + ""; + break; + } + /* jshint ignore:start */ + default: + /* jshint ignore:end */ + newHtml += element.tags[row]; + break; + } + newHtml += ""; + } + } + 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 + "

could not load data!

"; + }); + } + } + + // 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 © OpenStreetMap 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 © OpenStreetMap 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); diff --git a/searx/static/themes/simple/js/searx_src/searx_results.js b/searx/static/themes/simple/js/searx_src/searx_results.js new file mode 100644 index 000000000..b13da8391 --- /dev/null +++ b/searx/static/themes/simple/js/searx_src/searx_results.js @@ -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, +*/ +(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); diff --git a/searx/static/themes/simple/js/searx_src/searx_search.js b/searx/static/themes/simple/js/searx_src/searx_search.js new file mode 100644 index 000000000..1b93f9039 --- /dev/null +++ b/searx/static/themes/simple/js/searx_src/searx_search.js @@ -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, +*/ +(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 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; + } + +} diff --git a/searx/static/themes/simple/less/code.less b/searx/static/themes/simple/less/code.less new file mode 100644 index 000000000..a688dd98d --- /dev/null +++ b/searx/static/themes/simple/less/code.less @@ -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 */ + } +} diff --git a/searx/static/themes/simple/less/definitions.less b/searx/static/themes/simple/less/definitions.less new file mode 100644 index 000000000..7a43720b8 --- /dev/null +++ b/searx/static/themes/simple/less/definitions.less @@ -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"; diff --git a/searx/static/themes/simple/less/index.less b/searx/static/themes/simple/less/index.less new file mode 100644 index 000000000..e1efdac90 --- /dev/null +++ b/searx/static/themes/simple/less/index.less @@ -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; + } + } + +} diff --git a/searx/static/themes/simple/less/ion.less b/searx/static/themes/simple/less/ion.less new file mode 100644 index 000000000..9ec6b9955 --- /dev/null +++ b/searx/static/themes/simple/less/ion.less @@ -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"; + } +} + diff --git a/searx/static/themes/simple/less/mixins.less b/searx/static/themes/simple/less/mixins.less new file mode 100644 index 000000000..097ab4964 --- /dev/null +++ b/searx/static/themes/simple/less/mixins.less @@ -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; +} diff --git a/searx/static/themes/simple/less/normalize.less b/searx/static/themes/simple/less/normalize.less new file mode 100644 index 000000000..fa4e73dd4 --- /dev/null +++ b/searx/static/themes/simple/less/normalize.less @@ -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; +} diff --git a/searx/static/themes/simple/less/preferences.less b/searx/static/themes/simple/less/preferences.less new file mode 100644 index 000000000..b8e096cd5 --- /dev/null +++ b/searx/static/themes/simple/less/preferences.less @@ -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; + } +} diff --git a/searx/static/themes/simple/less/search.less b/searx/static/themes/simple/less/search.less new file mode 100644 index 000000000..beeac3e8a --- /dev/null +++ b/searx/static/themes/simple/less/search.less @@ -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; + } + +} diff --git a/searx/static/themes/simple/less/stats.less b/searx/static/themes/simple/less/stats.less new file mode 100644 index 000000000..c134bd0ec --- /dev/null +++ b/searx/static/themes/simple/less/stats.less @@ -0,0 +1,8 @@ +.percentage { + position: relative; + width: 300px; + + div { + background: @color-percentage-div-background; + } +} diff --git a/searx/static/themes/simple/less/style-rtl.less b/searx/static/themes/simple/less/style-rtl.less new file mode 100644 index 000000000..2b68bcfde --- /dev/null +++ b/searx/static/themes/simple/less/style-rtl.less @@ -0,0 +1,6 @@ +@import "style.less"; + +#search_submit { + left: 1px; + right:auto; +} diff --git a/searx/static/themes/simple/less/style.less b/searx/static/themes/simple/less/style.less new file mode 100644 index 000000000..b79b3eb24 --- /dev/null +++ b/searx/static/themes/simple/less/style.less @@ -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; + } + + } + +} diff --git a/searx/static/themes/simple/less/toolkit.less b/searx/static/themes/simple/less/toolkit.less new file mode 100644 index 000000000..641747c6c --- /dev/null +++ b/searx/static/themes/simple/less/toolkit.less @@ -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%; + } +} diff --git a/searx/static/themes/simple/magnet.svg b/searx/static/themes/simple/magnet.svg new file mode 100644 index 000000000..5a7a16329 Binary files /dev/null and b/searx/static/themes/simple/magnet.svg differ diff --git a/searx/static/themes/simple/package.json b/searx/static/themes/simple/package.json new file mode 100644 index 000000000..f3d6bbfe2 --- /dev/null +++ b/searx/static/themes/simple/package.json @@ -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" + } +} diff --git a/searx/templates/oscar/preferences.html b/searx/templates/oscar/preferences.html index 49f67bcd8..afb389e44 100644 --- a/searx/templates/oscar/preferences.html +++ b/searx/templates/oscar/preferences.html @@ -171,7 +171,7 @@ {{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in disabled_engines) }} {{ search_engine.name }} - {{ shortcuts[search_engine.name] }} + {{ shortcuts[search_engine.name] }} diff --git a/searx/templates/simple/404.html b/searx/templates/simple/404.html new file mode 100644 index 000000000..1843c9892 --- /dev/null +++ b/searx/templates/simple/404.html @@ -0,0 +1,9 @@ +{% extends "simple/base.html" %} +{% block content %} +
+

{{ _('Page not found') }}

+ {% autoescape false %} +

{{ _('Go to %(search_page)s.', search_page='{}'.decode('utf-8').format(url_for('index'), _('search page'))) }}

+ {% endautoescape %} +
+{% endblock %} diff --git a/searx/templates/simple/about.html b/searx/templates/simple/about.html new file mode 100644 index 000000000..1913879da --- /dev/null +++ b/searx/templates/simple/about.html @@ -0,0 +1,4 @@ +{% extends 'simple/base.html' %} +{% block content %} +{% include '__common__/about.html' %} +{% endblock %} diff --git a/searx/templates/simple/base.html b/searx/templates/simple/base.html new file mode 100644 index 000000000..0003f113e --- /dev/null +++ b/searx/templates/simple/base.html @@ -0,0 +1,61 @@ + + + + + + + + + + + + + {% block title %}{% endblock %}searx + {% if rtl %} + + {% else %} + + {% endif %} + {% block styles %}{% endblock %} + {% block meta %}{% endblock %} + {% block head %} + + {% endblock %} + + + + +
+ {% if errors %} + + {% endif %} + + {% block content %} + {% endblock %} +
+
+

{{ _('Powered by') }} searx - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}

+
+ + + + + diff --git a/searx/templates/simple/categories.html b/searx/templates/simple/categories.html new file mode 100644 index 000000000..127d55b2b --- /dev/null +++ b/searx/templates/simple/categories.html @@ -0,0 +1,8 @@ +
{{- '' -}} +
+ {%- for category in categories -%} +
+ {%- endfor -%} + {%- if display_tooltip %}
{{ _('Click on the magnifier to perform search') }}
{% endif -%} +
{{- '' -}} +
diff --git a/searx/templates/simple/index.html b/searx/templates/simple/index.html new file mode 100644 index 000000000..4e8e76cce --- /dev/null +++ b/searx/templates/simple/index.html @@ -0,0 +1,12 @@ +{% extends "simple/base.html" %} +{% from 'simple/macros.html' import icon %} +{% block meta %} + +{% endblock %} +{% block content %} + +
+

searx

+ {% include 'simple/search.html' %} +
+{% endblock %} diff --git a/searx/templates/simple/infobox.html b/searx/templates/simple/infobox.html new file mode 100644 index 000000000..d99806ac4 --- /dev/null +++ b/searx/templates/simple/infobox.html @@ -0,0 +1,46 @@ + diff --git a/searx/templates/simple/languages.html b/searx/templates/simple/languages.html new file mode 100644 index 000000000..dd928ff68 --- /dev/null +++ b/searx/templates/simple/languages.html @@ -0,0 +1,8 @@ + diff --git a/searx/templates/simple/macros.html b/searx/templates/simple/macros.html new file mode 100644 index 000000000..76c53a635 --- /dev/null +++ b/searx/templates/simple/macros.html @@ -0,0 +1,86 @@ + +{% macro icon(action) -%} + +{%- endmacro %} + +{% macro icon_small(action) -%} + +{%- endmacro %} + + + +{% macro draw_favicon(favicon) -%} + {{ favicon }} +{%- endmacro %} + +{% macro result_open_link(url, classes='') -%} + +{%- endmacro %} + +{%- macro result_close_link() -%} + +{%- endmacro %} + +{%- macro result_link(url, title, classes='') -%} + {{ result_open_link(url, classes) }}{{ title }}{{ result_close_link() }} +{%- endmacro -%} + + +{% macro result_header(result, favicons, image_proxify) -%} +
+ {%- if result.img_src %}{{ result_open_link(result.url) }}{{ result.title|striptags }}{{ result_close_link() }}{% endif -%} + {%- if result.thumbnail %}{{ result_open_link(result.url) }}{{ result.title|striptags }}{{ result_close_link() }}{% endif -%} +

{{ result_link(result.url, result.title|safe) }}

+{%- endmacro -%} + + +{%- macro result_sub_header(result) -%} + {% if result.publishedDate %}{% endif %} +{%- endmacro -%} + + +{%- macro result_sub_footer(result, proxify) -%} +
{% for engine in result.engines %}{{ engine }}{% endfor %}
{{- '' -}} +

{{ result.pretty_url }}{{ 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 %}

{{- '' -}} +
{{- '' -}} +{%- endmacro -%} + + +{%- macro result_footer(result) -%} +
+{%- endmacro -%} + + +{%- macro tabs_open() -%} +
+{%- endmacro -%} + +{%- macro tab_header(name, id, label) -%} + + +
+{%- endmacro -%} + +{%- macro tab_footer() -%} +
+{%- endmacro -%} + +{%- macro tabs_close() -%} +
+{%- endmacro -%} + +{%- macro checkbox_onoff(name, checked) -%} +
{{- '' -}} + {{- '' -}} + {{- '' -}} +
+{%- endmacro -%} + +{%- macro checkbox(name, checked, readonly, disabled) -%} +
{{- '' -}} + {{- '' -}} + {{- '' -}} +
+{%- endmacro -%} diff --git a/searx/templates/simple/preferences.html b/searx/templates/simple/preferences.html new file mode 100644 index 000000000..4529fea8c --- /dev/null +++ b/searx/templates/simple/preferences.html @@ -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 -%} +
{{- '' -}} + {{ _(plugin.name) }}{{- '' -}} +
+ {{- checkbox_onoff('plugin_' + plugin.id, plugin.id not in allowed_plugins) -}} +
{{- '' -}} +
+ {{- _(plugin.description) -}} +
{{- '' -}} +
+{%- endif -%} +{%- endfor -%} +{%- endmacro -%} + +{% block head %} {% endblock %} +{% block content %} + +

searx

+ +

{{ _('Preferences') }}

+ +
+ +{{ tabs_open() }} + +{{ tab_header('maintab', 'general', _('General')) }} +
+ {{ _('Default categories') }} + {% set display_tooltip = false %} + {% include 'simple/categories.html' %} +
+
+ {{ _('Search language') }} +

{{- '' -}} + {{- '' -}} +

+
{{ _('What language do you prefer for search?') }}
+
+
+ {{ _('Autocomplete') }} +

+ +

+
{{ _('Find stuff as you type') }}
+
+
+ {{ _('SafeSearch') }} +

+ +

+
{{ _('Filter content') }}

+
+ {{ plugin_preferences('general') }} + {{ tab_footer() }} + + {{ tab_header('maintab', 'engines', _('Engines')) }} +

{{ _('Currently used search engines') }}

+ + {{ tabs_open() }} + {% for categ in all_categories %} + + {{ tab_header('enginetab', 'category' + categ, _(categ)) }} +
+ + + + + + + + + + + + {% for search_engine in engines_by_category[categ] %} + + {% if not search_engine.private %} + {% set engine_id = 'engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_') %} + + + + + + + + + + + {% endif %} + {% endfor %} +
{{ _("Allow") }}{{ _("Engine name") }}{{ _("Shortcut") }}{{ _("Supports selected language") }}{{ _("SafeSearch") }}{{ _("Time range") }}{{ _("Avg. time") }}{{ _("Max time") }}
{{ checkbox_onoff(engine_id, (search_engine.name, categ) in disabled_engines) }}{{ search_engine.name }}{{ shortcuts[search_engine.name] }}{{ 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) }}{{ checkbox(engine_id + '_safesearch', search_engine.safesearch==True, true, true) }}{{ checkbox(engine_id + '_time_range_support', search_engine.time_range_support==True, true, true) }}{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}{{ search_engine.timeout }}
+
+ {{ tab_footer() }} + {% endfor %} + {{ tabs_close() }} + {{ tab_footer() }} + + {{ tab_header('maintab', 'ui', _('User interface')) }} +
+ {{ _('Interface language') }} +

+ +

+
{{ _('Change the language of the layout') }}
+
+
+ {{ _('Themes') }} +

+ +

+
{{ _('Change searx layout') }}
+
+
+ {{ _('Results on new tabs') }} +

+ +

+
{{_('Open result links on new browser tabs') }}
+
+ {{ plugin_preferences('ui') }} + {{ tab_footer() }} + + {{ tab_header('maintab', 'privacy', _('Privacy')) }} +
+ {{ _('Method') }} +

+ +

+
{{ _('Search language') }}
+
+
+ {{ _('Image proxy') }} +

+ +

+
{{ _('Proxying image results through searx') }}
+
+ {{ plugin_preferences('privacy') }} + {{ tab_footer() }} + + {{ tabs_close() }} + +

{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }} +
+ {{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }} +

+ + + + + + +{% endblock %} diff --git a/searx/templates/simple/result_templates/code.html b/searx/templates/simple/result_templates/code.html new file mode 100644 index 000000000..9db05311f --- /dev/null +++ b/searx/templates/simple/result_templates/code.html @@ -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 %}

+{%- if result.repository -%} +

{{ result.repository }}

+{%- endif -%} +
+ {{- result.codelines|code_highlighter(result.code_language)|safe -}} +
{{- '' -}} +{{- result_sub_footer(result, proxify) -}} +{{ result_footer(result) }} diff --git a/searx/templates/simple/result_templates/default.html b/searx/templates/simple/result_templates/default.html new file mode 100644 index 000000000..b29ca550f --- /dev/null +++ b/searx/templates/simple/result_templates/default.html @@ -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 -%} + +{%- endif %} +

+ {%- if result.content %}{{ result.content|safe }}{% endif -%} +

+{{- result_sub_footer(result, proxify) -}} +{% if result.embedded -%} + +{%- endif %} +{{- result_footer(result) }} diff --git a/searx/templates/simple/result_templates/images.html b/searx/templates/simple/result_templates/images.html new file mode 100644 index 000000000..f756acbe3 --- /dev/null +++ b/searx/templates/simple/result_templates/images.html @@ -0,0 +1,4 @@ + diff --git a/searx/templates/simple/result_templates/map.html b/searx/templates/simple/result_templates/map.html new file mode 100644 index 000000000..1fe0c86ac --- /dev/null +++ b/searx/templates/simple/result_templates/map.html @@ -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 -%} + +{%- endif -%} + +{%- if result.osm and (result.osm.type and result.osm.id) -%} + +{%- endif -%} +{#- +{% if (result.latitude and result.longitude) %} + {{ icon('location') }} {{ _('show geodata') }} +{% endif %} +-#} + +{%- if result.address -%} +

+ {%- if result.address.name -%} + {{ result.address.name }}
+ {%- endif -%} + {% if result.address.road -%} + + {% if result.address.house_number %}{{ result.address.house_number }}, {% endif %} + {{ result.address.road }} +
+ {%- endif %} + {%- if result.address.locality -%} + {{ result.address.locality }} + {% if result.address.postcode %}, {{ result.address.postcode }}{% endif %} +
+ {%- endif -%} + {%- if result.address.country -%} + {{ result.address.country }} + {%- endif -%} +

+{%- endif -%} + +{%- if result.content %}

{{ result.content|safe }}

{% endif -%} + +{{- result_sub_footer(result, proxify) -}} + +{% if result.osm and (result.osm.type and result.osm.id) -%} + +{%- endif %} + +{#- +{% if (result.latitude and result.longitude) -%} + +{%- endif %} +-#} + +{% if (result.latitude and result.longitude) or result.boundingbox -%} + +{%- endif %} + +{{- result_footer(result) }} diff --git a/searx/templates/simple/result_templates/torrent.html b/searx/templates/simple/result_templates/torrent.html new file mode 100644 index 000000000..3c7fd15e8 --- /dev/null +++ b/searx/templates/simple/result_templates/torrent.html @@ -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 %}{% endif %} +{% if result.torrentfile %}{% endif %} + +{% if result.seed %}

• {{ icon('arrow-swap') }} {{ _('Seeder') }} {{ result.seed }} • {{ _('Leecher') }} {{ result.leech }}

{% endif %} + +{%- if result.filesize %}

{{ icon('floppy-disk') }} {{ _('Filesize') }} + {%- 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 -%} +

+{%- endif -%} + +{%- if result.files %}

{{ icon('file') }} {{ _('Number of Files') }} {{ result.files }}

{% endif -%} + +{%- if result.content %}

{{ result.content|safe }}

{% endif -%} +{{- result_sub_footer(result, proxify) -}} +{{- result_footer(result) }} diff --git a/searx/templates/simple/result_templates/videos.html b/searx/templates/simple/result_templates/videos.html new file mode 100644 index 000000000..be270e932 --- /dev/null +++ b/searx/templates/simple/result_templates/videos.html @@ -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 -%} + +{%- endif %} +{% if result.content %}

{{ result.content|safe }}

{% endif %} +{{- result_sub_footer(result, proxify) -}} +{% if result.embedded -%} + +{%- endif %} +{{ result_footer(result) }} diff --git a/searx/templates/simple/results.html b/searx/templates/simple/results.html new file mode 100644 index 000000000..081118eaf --- /dev/null +++ b/searx/templates/simple/results.html @@ -0,0 +1,151 @@ +{% extends "simple/base.html" %} +{% from 'simple/macros.html' import icon, icon_small %} +{% block title %}{{ q|e }} - {% endblock %} +{% block meta %}{% endblock %} +{% block content %} + +{% include 'simple/search.html' %} +
+ {% if answers %} +

{{ _('Answers') }} :

+ {% for answer in answers -%} +
{{ answer }}
+ {%- endfor %} +
+ {% endif %} + + + + {% if corrections %} +
+

{{ _('Try searching for:') }}

+ {% for correction in corrections %} +
+
+ + + + + + +
+
+ {% endfor %} +
+ {% endif %} + +
+ {% 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 %} +
+ + {% if paging %} + + {% endif %} +
+{% endblock %} diff --git a/searx/templates/simple/search.html b/searx/templates/simple/search.html new file mode 100644 index 000000000..3f48d7fcd --- /dev/null +++ b/searx/templates/simple/search.html @@ -0,0 +1,16 @@ + diff --git a/searx/templates/simple/simple.spec.txt b/searx/templates/simple/simple.spec.txt new file mode 100644 index 000000000..a9724f8ef --- /dev/null +++ b/searx/templates/simple/simple.spec.txt @@ -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 + + diff --git a/searx/templates/simple/stats.html b/searx/templates/simple/stats.html new file mode 100644 index 000000000..462ab4aa9 --- /dev/null +++ b/searx/templates/simple/stats.html @@ -0,0 +1,25 @@ +{% extends "simple/base.html" %} +{% block head %} {% endblock %} +{% block content %} + +

searx

+ +

{{ _('Engine stats') }}

+ +{% for stat_name,stat_category in stats %} +
+ + + + + {% for engine in stat_category %} + + + + + + {% endfor %} +
{{ stat_name }}
{{ engine.name }}{{ '%.02f'|format(engine.avg) }}
 
+
+{% endfor %} +{% endblock %} diff --git a/searx/templates/simple/time-range.html b/searx/templates/simple/time-range.html new file mode 100644 index 000000000..a9fc9f165 --- /dev/null +++ b/searx/templates/simple/time-range.html @@ -0,0 +1,17 @@ +