LINUX.ORG.RU

Сообщения damix9

 

В виджете «Проигрыватель» не работает кнопка пуск/пауза после переключения трека в VLC (2)

В продолжение В виджете «Проигрыватель» не работает кнопка пуск/пауза после переключения трека в VLC

fresa, они похоже наконец-то пофиксили этот баг.
https://code.videolan.org/videolan/vlc/-/issues/26755
Только я не пойму, когда оно у людей на компах будет исправлено? Вроде бы это закрывает вот этот коммит от мая 2022, но актуальная версия - 3.0.20 от октября 2023. И ней этого еще нет?
У кого VLC из гита, у вас воспроизводится баг? Если у вас не KDE и нет аналогичного виджета, проверить можете mpristester.

 , ,

damix9
()

Как закрепить свою тему?

Давайте добавим тему про LORScriptPack в закрепы. Если нужно ее пересоздать или что-то в ней поменять или даже в самом скрипте, я сделаю. Я хочу, чтобы люди, которым нужны эти функции, впредь не повторяли мою работу, не искали по поиску. Чтобы любой новорег мог просто закрепы прочитать и узнать, какие расширения есть для форума.

 , ,

damix9
()

Поднять SSH в chroot

Поставил Debian в chroot на Android 4.4 таким образом. Запускаю контейнер

cd /data
mount -o bind /dev/ debian-atom/dev
mount -o bind /sys/ debian-atom/sys
mount -o bind /proc/ debian-atom/proc
mount -o bind /dev/pts debian-atom/dev/pts
mount -t tmpfs none debian-atom/run
chroot debian-atom/ /bin/login -f root
Внутри поставил SSH из реп, но получаю
root@localhost:~# systemctl start sshd.service
Running in chroot, ignoring request: start
root@localhost:~#
Как починить? Или таким образом можно только дистрибутив без systemd поставить?

 

damix9
()

Запустить скрипт при загрузке Android

Посоветуйте приложение для Android, которое может запустить скрипт или выполнить команду

  1. При включении устройства
  2. По нажатию кнопки в интерфейсе
  3. По времени - ежедневно или по таймеру или как-то еще [желательно]

Желательно свободное.

 

damix9
()

LOR Dark blue

Стиль другого автора, который я немного доделал.

Скриншоты
1.png
2.png
3.png

/* ==UserStyle==
@name         LOR Dark blue
@namespace    USO Archive
@author       ens0
@description  dark blue style for LOR
@version      20151215.12.36
@license      NONE
@preprocessor uso
==/UserStyle== */
@namespace url(http://www.w3.org/1999/xhtml);

@-moz-document domain("www.linux.org.ru") {

    html,
    body,
    .code,
    code {
        background: #0f2330 !important;
        /*color: #b3c5d0 !important;*/
    }

    #sitetitle {
        background: #153041 !important;
    }

    h2 a {
        color: #b3c5d0 !important;
    }

    #hd .menu ul {
        display: flex;
    }
    
    #hd .menu li {
        margin: 0;
    }

    .menu a {
        color: #b3c5d0 !important;
        text-decoration: none;
        display: block;
        padding: 10px;
    }
    
    .menu a:hover {
        background-color: #15618c;
    }

    #loginGreating a {
        color: #b3c5d0 !important;
        text-decoration: none;
    }

    #sitetitle {
        color: #ffffff !important;
    }
    
    #bd {
        padding-left: 0;
        padding-right: 0;
    }
    
    article.news {
        padding: 10px;
        box-shadow: 0 0 1px 1px #70c0ed;
    }
    
    img.photo {
        border-radius: 0;
    }
    
    blockquote {
        background-color: #0f2330;
        border: 1px dotted #234240;
        border-left: 5px solid #15618c;
        color: #b3c5d0;
        font-style: normal;
    }
    
    #realtime a {
        color: #fff;
    }

    .nav-buttons a {
        color: #feedcf !important;
    }

    .messages .msg:target {
        border: 1px solid #dc322f !important;
        margin-top: 5px;
    }

    .menu,
    .infoblock,
    .boxlet,
    .messages .msg,
    .message-table .tag {
        background: #153041 !important;
    }
    
    .messages .by-ts {
        background: #15412E !important;
    }

    .infoblock,
    .boxlet,
    .msg,
    .message-table .tag {
        border-radius: 0 !important;
    }

    .msg {
        border-top: 5px solid #0f2330 !important;
    }

    #bd .forum table th,
    .message-table tr:hover {
        background: #153041 !important;
    }

    .msg {
        padding-left: 15px !important;
        padding-right: 15px !important;
    }

    #bd .btn-default {
        background-color: #173447 !important;
    }

    #bd .btn-selected {
        background-color: #234b64 !important;
        color: #fff !important;
    }

    #bd .btn-primary {
        background-color: #2e6080 !important;
    }

    #bd .forum table tbody td {
        border: 1px solid #234240 !important;
    }

    #bd .forum table th {
        border: 1px solid #234240 !important;
    }

    #bd .forum table tbody td a {
        text-decoration: none !important;
        color: #70c0ed !important;
    }

    .message-table .tag {
        color: #EEEEEC !important;
    }

    /*blockquote {
        border-left-color: #506572 !important;
    }*/

    #bd .sign a {
        color: #1ee056 !important;
        font-weight: bold;
    }
    
    #bd .sign_more a {
        font-weight: normal;
    }

    #whois_userpic {
        background: #153041 none repeat scroll 0% 0% !important;
    }
    
    form#query {
        border: 1px solid #b3c5d0;
        padding: 10px;
    }
    
    form.control-group {
        border: 1px solid #b3c5d0;
        padding: 10px;
        margin-top: 10px;
    }
    
    .msg .reply li::before, .msg .reply li::after {
        display: none;
    }
    
    .msg .reply li a {
        display: inline-block;
        padding-right: 4px;
        padding-left: 4px;
        padding-top: 2px;
        padding-bottom: 2px;
        border: 1px solid #70c0ed;
        border-radius: 2px;
        text-decoration: none;
        color: #b3c5d0 !important;
        background: linear-gradient(to bottom, #15618c 0%, #153041 100%);
    }
    
    textarea {
        background-color: #080814;
        border: 1px solid #8E97BD;
        border-radius: 2px;
        color: #b3c5d0;
    }
    
    input, select {
        background-color: #153041;
        color: #b3c5d0;
        border: 1px solid #70c0ed;
        border-radius: 0;
    }
    
    #markup-panel .btn {
        border-radius: 0;
    }
    
    #whois_userpic {
        border-radius: 0;
    }
    
    div.tags-first-letters {
        padding: 5px;
        background: #153041
    }
    
    :root {
        --text-color: #b3c5d0;
        --link-color: #70c0ed;
        --icon-button-active-color: #ffe746;
        --header-color: #70c0ed;
        --tag-color: #ffe746;
        --button-primary-background: #15618c;
    }
}

 

damix9
()

Свободы слова у вас нет

Почему www.linux.org.ru/forum/talks/17584266 удалили с 4.2, хотя оригинал этой пасты запостить было можно? Это что получается, на ЛОРе в 2013 была свобода слова, а теперь тут захватили власть жидомасоны, которые установили цензуру?

Почему-то при alpha и Shaman007 шутить про такое было можно, а теперь нельзя.

 

damix9
()

[Решено] W: Failed to fetch http://deb.debian.org/debian/dists/buster/InRelease Temporary failure resolving 'deb.debian.org'

Поставил тогдашний oldstable (т.е. наверное buster) таким образом [Решено] Установить GNU/Linux на Acer A1-840 FHD
Сеть работала, пакеты ставились. Теперь запустил этот же контейнер, и

u0_a5@ducati2fhd:/ $ su
root@ducati2fhd:/ # cd /data
root@ducati2fhd:/data # chroot debian-atom /bin/login -f root
Last login: Thu Apr 11 21:52:50 UTC 2024 on pts/2
Linux localhost 3.10.20+ #1 SMP PREEMPT Thu Dec 4 15:34:06 CST 2014 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@localhost:~# ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=25.3 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=34.5 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=13.2 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=26.8 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=75.0 ms
c64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=11.3 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=68.4 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=30.9 ms
c64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=136 ms
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=31.3 ms
64 bytes from 192.168.1.1: icmp_seq=11 ttl=64 time=25.0 ms
64 bytes from 192.168.1.1: icmp_seq=12 ttl=64 time=60.5 ms
64 bytes from 192.168.1.1: icmp_seq=13 ttl=64 time=111 ms
^C
--- 192.168.1.1 ping statistics ---
13 packets transmitted, 13 received, 0% packet loss, time 31ms
rtt min/avg/max/mdev = 11.335/49.946/135.836/36.973 ms
root@localhost:~#
root@localhost:~# cat /etc/apt/sources.list
deb http://deb.debian.org/debian buster main
root@localhost:~# apt update
Err:1 http://deb.debian.org/debian buster InRelease
  Temporary failure resolving 'deb.debian.org'
Reading package lists... Done
Building dependency tree... Done
All packages are up to date.
W: Failed to fetch http://deb.debian.org/debian/dists/buster/InRelease  Temporary failure resolving 'deb.debian.org'
W: Some index files failed to download. They have been ignored, or old ones used instead.
root@localhost:~#
Пинг по доменному имени тоже идет.

 

damix9
()

Почему в Slackware glibc 2.23?

Slackware Linux is a complete multitasking «UNIX-like» system available in both 32-bit and 64-bit versions. It's currently based around the 4.4 Linux kernel series and the GNU C Library version 2.23.

http://www.slackware.com/info/

Получается, там максимальная версия glibc в актуальном дистрибутиве 2.23? А как оно работает тогда? Это же AppImage, собранный на Ubuntu 18.04 (на которой 2.27) там не пойдет. Телеграму надо 2.28. Или обычно приложения меньше требуют?

 

damix9
()

Как часто в Slackware обновляют пакеты?

И от чего это зависит? Например, в Debian оно зависит от того, чем является в настоящее время релиз - oldstable или stable или testing.

 

damix9
()

По кнопке «Ответить» форма ввода комментария не выезжает, а открывается страница comment-message.jsp

Воспроизводится во всех темах в 100% случаев.

Mozilla/5.0 (Android 4.4.2; Tablet; rv:68.0) Gecko/68.0 Firefox/68.0

 

damix9
()

Браузер для Android 4

Есть Acer Iconia Tab A1-840 (https://4pda.to/devdb/acer_iconia_a1_840fhd) FHD с Android 4.4, рутованый. Назовите любой браузер, который на нём пойдет и покажет современные сайты. Или как поставить на него другой андроид, на котором пойдет такой браузер?

Сейчас там есть лиса и хром устаревших версий (могу назвать, если надо), они почти ни на одном сайте не проходят проверку от DDoS, а какие открывают, на тех крашатся через несколько минут.

 

damix9
()

Сайт хранения закладок

Посоветуйте сайт в интернете (а еще лучше self-hosted), где можно залогиниться и хранить свои закладки. Желательно их как-то каталогизировать. Тут структура может быть разная - иерархическая, сетевая, что-то творческое типа «карты интернета» со ссылками в разных местах ...

Для чего-то наиболее часто нужного у меня New tab tools, а это я хочу использовать для вообще всех известных мне сайтов, которые могут понадобиться больше одного раза. Сохраняю обычно главные страницы, но есть исключения. Это не чтобы отложить и прочитать/купить/скачать потом. Для этого у меня закладки в браузере.

 , ,

damix9
()

Почему не удаляют темы-дубликаты?

Почему когда задают вопросы, ответы на которые уже есть в поиске, эти темы не удаляют, как это делают на Stackoverflow? Есть же в правилах пункт 3.1 - точные дубликаты других сообщений.

 

damix9
()

Скачать LOR Classic

Есть юзерстиль от Sadler Разнообразие тем на сайте. (комментарий) требующий скрипт LOR Classic.

Где взять этот скрипт? Я через поиск ни одной действующей ссылки найти не могу.

И еще, остался ли у кого этот код Мрачный ЛОР ? Там не пускает без регистрации.

 ,

damix9
()

Добавил массивам свойство isEmpty - нужен code review

Object.defineProperty(Array.prototype, 'isEmpty', {
    get: function() {
        return Array.isArray(this) && this.length === 0
    },
    set: function() {
    }
})

 

damix9
()

[Решено] Прочитать Nullable<long> из строки

Как написать то же самое понятнее? Пояснил комментариями.

C#

long? catCode = null;
// Если строка val не пустая, 
if (!(String.IsNullOrWhiteSpace(val)))
{
    // распознаем в первых цифрах до пробела целое 64-битное число.
    // Если его там нет, записываем в catCode NULL. 
    // Если его удалось распознать, записываем его в catCode.
    if (!(Int64.TryParse(val.Split(" ")[0], out long cc)))
    {
        catCode = null;
    }
    else 
    {
        catCode = cc;
    }
}

 

damix9
()

Кнопка в стиле Frutiger Aero

Нашел на просторах, немного подредактировал. Может кому пригодится. Ну и можете покритиковать.

CSS

button.aero {
    background-color: #05DE68;
    background: 
        radial-gradient(farthest-corner at bottom center, rgba(255, 255, 255, 0.7), transparent), 
        linear-gradient(to bottom, #04BD59, #05DE68);
    box-shadow: 0 4px 4px rgba(0, 0, 0, 0.4);
    border: 1px solid #05DE68;
    border-radius: 9999px;
    color: rgba(50, 26, 17, 0.8);
    cursor: pointer;
    font-family: "Lucida Grande", "Lucida Sans", sans-serif;
    font-weight: 600;
    margin: 1em 1ex;
    padding: 1ex 1em;
    position: relative;
    text-shadow: 0 2px 0.5em #0003;
    transition: all 300ms;
    min-height: 19px;
    letter-spacing: 1px;
    font-size: 12px;
    text-decoration: none;
    display: inline-block;
    box-sizing: border-box;
}

button.aero::after {
    content: "";
    position: absolute;
    top: 4%;
    height: 40%;
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.1));
    border-radius: 9999px;
    transition: background 400ms;
    left: 5px;
    right: 5px;
}

button.aero:hover, button.aero:focus {
    box-shadow: 0 6px 8px rgba(0, 0, 0, 0.4);
}

button.aero:active {
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
}

HTML

<button class="aero">Button text</button>

 

damix9
()

Автонастройка прокси в RSS-клиенте

Как сделать, чтобы некоторые ленты проверялись через прокси, настраиваемые автоматически - pac-файлом? QuiteRSS 0.18.8, кеды. В «свойствах» ленты такого не нашел. В настройках (F8) тоже.

Или посоветуйте RSS-клиент, в котором можно настроить автонастройку прокси и свои настройки сетевого подключения для каждой ленты.

Попробовал в ОС нажать Прокси-сервер -> Автоматическая настройка по указанному URL и вставить путь до .pac а в настройках клиента «Системные настройки прокси», получаю «Таймаут ленты». Прокси фактически не применяются никогда. И в браузере тоже, если аналогичную опцию выбрать.

Другой предполагаемый способ - настроить PAC как-то на уровне ОС. Но тогда тоже желательна возможность override сетевые настройки на уровне ленты.

 , ,

damix9
()

RSS Youtube-каналов - ленты перестали загружаться

QuiteRSS 0.18.8, сегодня при обновлении лент все ленты Youtube-каналов отметились в интерфейсе зачеркнутыми красными знаками «x». С остальными лентами всё в прежнем режиме. В браузере сайт открывается.

 

damix9
()

LORScriptPack - UserScript, делающий ЛОР удобным

Фичи:

  • Редактор сообщений с графическим интерфейсом из lorify-ng
  • Нормальное цитирование кнопкой
  • Делает поле ввода сообщения широким по умолчанию
  • Возможность ответить одним сообщением на несколько
  • Возможность обратиться к пользователю по нику
  • Возможность скопировать ник пользователя в профиле
  • Копируемый и сворачиваемый код
  • Показывает местное время вместо московского
  • Поиск google помимо внутреннего
  • При внутреннем поиске сортирует от новых к старым по умолчанию [отключаемая фича]
  • В темах, отличных от black, скрывает новости и галерею, добавляет теги и документацию [отключаемые фичи]
  • Нормальный поиск тегов
  • Скрывает облако тегов
  • В темах, отличных от black, делает только технические разделы в трекере по умолчанию [отключаемая фича]
  • Преобразует ссылки на картинки в сами картинки
  • Выделяет комментарии от автора темы классом by-ts, а его ник - классом ts-nick
  • Выделяет нечетные комментарии классом odd, а четные - классом even
  • Кнопка «Пожаловаться» возле каждого сообщения
  • Прокручиваемый в обе стороны код
  • Скрывает звезды и реакции
  • Выделяет комментарии ТСа цветом

Включает коды из других проектов:

  • LORLocalDate 1.0.0 от post-factum, Creative Commons Attribution 3.0 Unported
  • Date Format 1.2.3, MIT
  • Lorify-ng 3.2.0, MIT

Скриншоты

https://images.linuxforum.ru/images/2024/03/23/IZOBRAZENIE1471e033edbdb898.png
https://images.linuxforum.ru/images/2024/03/23/IZOBRAZENIE.png

Установка

  1. Установите расширение Greasemonkey.
  2. Нажмите «Создать пользовательский скрипт».
  3. Нажмите Ctrl+A и вставьте код скрипта, затем нажмите Ctrl+S.

Более простой способ установки

  1. Установите расширение Greasemonkey или Violentmonkey.
  2. Установите LORScriptPack с Greasy Fork.

Установка на телефон

  1. Установите приложение Berry Browser.
  2. Нажмите Settings -> Web -> Userscripts
  3. Нажмите на плюс, затем Edit, вставьте код скрипта, затем нажмите на дискету.

Настройка

Чтобы выключить опцию, поменяйте true на false в строчке с соответствующей опцией:

NEW_TO_OLD_SEARCH_BY_DEFAULT
HIDE_NEWS_AND_GALLERY
ADD_TAGS_AND_DOCS
TECH_ONLY_BY_DEFAULT

Создание юзерстилей

/*Чередующиеся сообщения разных цветов*/

.messages .odd {
    background-color: #FBFCFB;
}

.messages .even {
    background-color: #F0FFF7;
}

/*Кастомизируем вид кнопок редактора сообщений*/

#btn-i {
    font-style: italic;
}

#btn-quote::before {
    content: 'Цитата';
}

#btn-quote span {
    display: none;
}
// ==UserScript==
// @name           LORScriptPack
// @description    Пак скриптов для ЛОРа
// @namespace      linux.org.ru
// @include        http://www.linux.org.ru/*
// @include        https://www.linux.org.ru/*
// @author         damix9
// @license        MIT
// @version        2.0
// ==/UserScript==

/*
MIT License

Copyright (c) 2024 damix9
Copyright (c) 2022 OpenA
Copyright (c) 2007-2009 Steven Levithan <stevenlevithan.com>
Copyright (с) 2013 Oleksandr Natalenko aka post-factum

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

// Настройки
const NEW_TO_OLD_SEARCH_BY_DEFAULT = true;
const HIDE_NEWS_AND_GALLERY = true;
const ADD_TAGS_AND_DOCS = true;
const TECH_ONLY_BY_DEFAULT = true;

// Глобальные константы и переменные
const parser = new DOMParser();
const formats = ['jpeg', 'jpg', 'png', 'webp', 'tif', 'tiff'];
let CommentForm = null;
let tagListWrapper = null;
let divPopup = null; let timer = null;

// Функции

function _setup(el, attrs, events) {

	if (!el)
		return '';

	switch (typeof el) {
		case 'string':
			el = document.createElement(el);
		case 'object':
			for (const key in attrs) {
				attrs[key] === undefined ? el.removeAttribute(key) :
				key === 'html' ? el.innerHTML   = attrs[key] :
				key === 'text' ? el.textContent = attrs[key] :
				key in el    && (el[key]        = attrs[key] ) == attrs[key]
							 &&  el[key]       == attrs[key] || el.setAttribute(key, attrs[key]);
			}
			for (const name in events) {
				if (!events[name])
					continue;
				if (Array.isArray(events[name]))
					events[name].forEach(handler => el.addEventListener(name, handler, false));
				else
					el.addEventListener(name, events[name], false);
			}
	}
	return el;
}

// Возвращает расширение файла, находящегося по адресу url
function _getUrlExt(url) {
  	let oURL = new URL(url);
  	let path = oURL.pathname;
    return path.split('.').pop().toLowerCase();
}

// Возвращает название темы, выбранной в настройках
function getCurrentTheme() {
    let firstLinkNode = document.head.querySelector('link');
    let cssUrl = new URL(firstLinkNode.href);
    return cssUrl.pathname.split('/')[1]
}

// Добавляет CSS к странице
function addCss(sheet) {
  var head = document.head;
  let style = _setup('style', { text: sheet });
  head.appendChild(style);
}

function strContains(str, phrase) {
	return str.indexOf(phrase) !== -1;
}

// В течение 3 секунд показывает всплывающее уведомление с текстом text
function popup(text) {
    clearTimeout(timer);
    divPopup.innerHTML = text;
    divPopup.style.visibility = 'visible';
    divPopup.classList.add('shown');
    timer = setTimeout(() => {
        divPopup.classList.remove('shown');
        timer = setTimeout(() => {
            divPopup.style.visibility = 'hidden';
        }, 1000)
    }, 3000)
}

//******************************************************************************************
//
// A CGI program uses the following syntax to add cookie information to the HTTP header:
// 
// Set-Cookie:   name=value   
// [;EXPIRES=dateValue]   
// [;DOMAIN=domainName]   
// [;PATH=pathName]   
// [;SECURE]
//
// This function sets a client-side cookie as above.  Only first 2 parameters are required
// Rest of the parameters are optional. If no szExpires value is set, cookie is a session cookie.
//
// Prototype : setCookie(szName, szValue [,szExpires] [,szPath] [,szDomain] [,bSecure])
//******************************************************************************************


function setCookie(szName, szValue, szExpires, szPath, szDomain, bSecure)
{
 	var szCookieText = 	   escape(szName) + '=' + escape(szValue);
	szCookieText +=	 	   (szExpires ? '; EXPIRES=' + szExpires.toGMTString() : '');
	szCookieText += 	   (szPath ? '; PATH=' + szPath : '');
	szCookieText += 	   (szDomain ? '; DOMAIN=' + szDomain : '');
	szCookieText += 	   (bSecure ? '; SECURE' : '');
	
	document.cookie = szCookieText;
}

//******************************************************************************************
// This functions reads & returns the cookie value of the specified cookie (by cookie name) 
//
// Prototype : getCookie(szName)
//******************************************************************************************

function getCookie(szName)
{
 	var szValue =	  null;
	if(document.cookie)	   //only if exists
	{
       	var arr = 		  document.cookie.split((escape(szName) + '=')); 
       	if(2 <= arr.length)
       	{
           	var arr2 = 	   arr[1].split(';');
       		szValue  = 	   unescape(arr2[0]);
       	}
	}
	return szValue;
}

//******************************************************************************************
// To delete a cookie, pass name of the cookie to be deleted
//
// Prototype : deleteCookie(szName)
//******************************************************************************************

function deleteCookie(szName)
{
 	var tmp = 	  			 	 getCookie(szName);
	if(tmp) 
	{ setCookie(szName,tmp,(new Date(1))); }
}

// Добавляет к форме отправке сообщения кнопки для редактирования разметки, делает поле ввода сообщения широким
function handleCommentForm(form) {
    const TEXT_AREA    = form.elements.msg, TITLE_AREA = form.elements.title || { value: '' };
	const MARKUP_PANEL = _setup('div', { id: 'markup-panel', class: 'lorcode'});

	for (let attrs of [
		{ lorcode: 'b'  , title: 'Жирный' },
		{ lorcode: 'i'  , title: 'Курсив' },
		{ lorcode: 'u'  , title: 'Подчеркнутый' },
		{ lorcode: 's'  , title: 'Зачеркнутый' },
		{ lorcode: 'em' , title: 'Курсив выделения' },
        { lorcode: 'strong' , title: 'Жирный выделения' },
        { lorcode: 'url' , title: 'Ссылка' },
		{ lorcode: 'list' , title: 'Список' },
		{ lorcode: 'list' , title: 'Нумерованный список', attr: '1' },
        { lorcode: '*'    , title: 'Элемент списка' },
		{ lorcode: 'pre'   , title: 'Преформатированный текст' },
        { lorcode: 'br'    , title: 'С новой строки' },
		{ lorcode: 'code'  , title: 'Код' },
		{ lorcode: 'code'  , title: 'Bash', attr: 'bash' },
		{ lorcode: 'code'  , title: 'HTML', attr: 'html' },
		{ lorcode: 'code'  , title: 'CSS', attr: 'css' },
		{ lorcode: 'code'  , title: 'JavaScript', attr: 'js' },
		{ lorcode: 'code'  , title: 'PHP', attr: 'php' },
		{ lorcode: 'code'  , title: 'SQL', attr: 'sql' },
		{ lorcode: 'code'  , title: 'Си', attr: 'c' },
		{ lorcode: 'code'  , title: 'C++', attr: 'cpp' },
		{ lorcode: 'code'  , title: 'Java', attr: 'java' },
        { lorcode: 'inline', title: 'Код в той же строке' },
		{ lorcode: 'user'  , title: 'Ник пользователя' },
        { lorcode: 'quote' , title: 'Цитата' }
	]) {
		attrs.type  = 'button';
        attrs.id = 'btn-' + attrs.lorcode.toLowerCase();
		attrs.class = 'btn btn-default';
        let label  = _setup('span', { text: attrs.lorcode });
        if (attrs.attr) {
            let a = attrs.attr.toLowerCase();
            attrs.id += `-${a}`;
            label.innerHTML += `=${a}`
        }
        let button = _setup('button', attrs);
        button.appendChild(label);
		MARKUP_PANEL.append(button)
	}
    
    lorcodeMarkup = lorcodeMarkup.bind(TEXT_AREA);

    for (let i = 0; i < MARKUP_PANEL.childNodes.length; i++) {
        let btn = MARKUP_PANEL.childNodes[i];
        btn.addEventListener('click', function(e) {
    		e.preventDefault();
    		const tag  = this.getAttribute('lorcode');
            const attr = this.getAttribute('attr');
            lorcodeMarkup(tag, attr)
    	});
    }
    TEXT_AREA.parentNode.firstElementChild.after(MARKUP_PANEL);
    TEXT_AREA.style = "width: 70em; height: 10em;"
}

// Пишет в поле ввода сообщения текст str, туда, где стоял курсор,
// Ставит курсор в конец добавленного текста и выделяет поле ввода
function injectText(str) {
    const txtArea = CommentForm.elements.msg;
    
    let val = txtArea.value,
        len = txtArea.value.length,
      start = txtArea.selectionStart,
        end = txtArea.selectionEnd;
        
    txtArea.value = val.substring(0, start) + str + val.substring(end);
    
    txtArea.selectionStart = txtArea.selectionEnd = start + str.length;
    
    txtArea.focus()
}

// Берет выделенный текст в указанный тег с указанным аттрибутом
// Если тег br или * то ставит их еще и в начале каждой строки выделенного текста
// Всегда вызывать bind() или call(), передав в них textarea, в которой надо делать разметку
function lorcodeMarkup(tag, attr) {
    const val = this.value,
	      end = this.selectionEnd,
	    start = this.selectionStart,
	    collp = start === end;

	let mtext = '', open = '', close = '', 
        soff = 0, eoff = 0;
        
    mtext = val.substring(start, end);
    
    switch (tag) {
        case 'br':
            open = '[br]';
            if (!collp) 
                mtext = mtext.replace(/\n/gm, '\n'+'[br]');
            break;
        case '*':
            open = '[*]';
            if (!collp)
                mtext = mtext.replace(/\[\/?\*\]/g, '').replace(/\n/gm, '\n'+'[*]');
            break;
        case 'url':
            let uri = prompt('Введите адрес ссылки');
            if (uri) {
                open = `[url=${uri}]`;
                close = '[/url]';
            }
            else {
                return;
            }
            break;
        default:
            open = attr ? `[${tag}=${attr}]` : `[${tag}]`;
            close = `[/${tag}]`;
    }
    
    soff = open.length; eoff = open.length + mtext.length;
    
    this.value = val.substring(0, start) + open + mtext + close + val.substring(end);
    this.focus();
    this.setSelectionRange(start + soff, start + eoff);
    this.dispatchEvent(new InputEvent('input', { bubbles: true }))
}

// Отправлет сообщение с текстом msg в тему c id topic
function sendMessageToTopic(topic, msg) {
    let newTab = open(`https://www.linux.org.ru/add_comment.jsp?topic=${topic}&msg=${msg}`, '_blank');
    newTab.focus()
}

// Обратиться к пользователю по нику
function castUser(nick) {
    injectText('[user]' + nick + '[/user], ')
}

// Цитировать. Аргументы опциональны. Если указаны, то цитировать с ником.
function quote(nick, link) {
    const wSelect = window.getSelection();
    if (wSelect.isCollapsed) {
        return
    }
    let simple = (nick === undefined) && (link === undefined);
    let text = simple ? '' : '[user]' + nick + '[/user] [url=' + link + ']пишет[/url]:\n';
    text += '[quote]' + wSelect.toString().trim() + '[/quote]' + '\n';
    injectText(text)
}

// Отправить модераторам ссылку на сообщение с нарушением правил
function reportHam(link) {
    
    let violation = prompt('Введите текст жалобы');
    
    if (violation == null) {
        return
    }
    
    let specTopicId = getCookie('SPECTOPIC_ID');
    let text = link;
    
    if (violation != "") {
        text += '%0D%0A%5Bbr%5D' + violation; // перенос строки и [br]
    }
    
    if (!(specTopicId)) {
        alert('Не задан спецтопик!\nОткройте его (Форум -> Linux-org-ru -> Ссылки на некорректные сообщения) и нажмите кнопку \"Это спецтопик\".');
        return
    }
    
    sendMessageToTopic(specTopicId, text)
}

// Сохраняет ID текущей темы в cookie SPECTOPIC_ID
function itsSpecTopic() {
    let path = window.location.pathname;
    let topicId = path.split('/')[3];
    let expires = new Date();
    expires.setDate(expires.getDate() + 60);
    setCookie('SPECTOPIC_ID', topicId, expires, '/');
    alert('Спецтопик установлен')
}

let firstLetter = '';

// Обновляет отображаемый список тегов, показывает теги, соответстующие 
// поисковому запросу, т.е. начинающиеся на строку, содержащуюся в поле ввода
async function searchTags(e) {
    let query = e.target.value.trim().toLowerCase();
    let queryFirstLetter = query.charAt(0);
    
    if (queryFirstLetter != firstLetter) {
        
        firstLetter = queryFirstLetter;
        
        if (firstLetter != '') {
            let response = await fetch('https://www.linux.org.ru/tags/' + firstLetter);
            let txt = await response.text();
            let oDoc = parser.parseFromString(txt, 'text/html');
            
            let content = oDoc.getElementById('bd');
            let tagList = content.getElementsByTagName('ul')[0];
            
            let oldTagList = tagListWrapper.firstChild;
            
            if (oldTagList) {
                tagListWrapper.replaceChild(tagList, oldTagList)
            }
            else {
                tagListWrapper.appendChild(tagList);
            }
        }
    }
    
    let tagList = tagListWrapper.firstChild;
    
    if (tagList) {
        for (let i = 0, c = tagList.children.length; i < c; i++) {
            let tag = tagList.children[i];
            let s = tag.children[0].text;
            if (s.startsWith(query)) {
                tag.style.display = 'list-item'
            }
            else {
                tag.style.display = 'none'
            }
        }
    }
}

// Добавляет к сообщению (теме или комментарию) недостающие ссылки внизу.
// Передать DOM Node элемента div.reply сообщения и логин его отправителя.
function addReplyLinks(replyNode, author) {
    
    let links = replyNode.firstElementChild;
    let linkToComment = links.lastElementChild.firstElementChild.href;
    
    let nick = _setup(
        'a',
        { text: 'Ник', href: linkToComment + '#nick' },
        { click: (e) => { e.preventDefault(); castUser(author) } }
    );
    let report = _setup(
        'a',
        { text: 'Пожаловаться', href: linkToComment + '#report' },
        { click: (e) => { e.preventDefault(); reportHam(linkToComment) } }
    );
    let simpleQuote = _setup(
        'a',
        { text: 'Цитировать', href: linkToComment + '#quote' },
        { click: (e) => { e.preventDefault(); quote() } }
    );
    let advancedQuote = _setup(
        'a',
        { text: 'Цитировать с ником', href: linkToComment + '#quote' },
        { click: (e) => { e.preventDefault(); quote(author, linkToComment) } }
    );
    
    let nickLi = _setup('li');          nickLi.appendChild(nick);
    let reportLi = _setup('li');        reportLi.appendChild(report);
    let quoteLi = _setup('li');         quoteLi.appendChild(simpleQuote);
    let advancedQuoteLi = _setup('li'); advancedQuoteLi.appendChild(advancedQuote);
    
    links.firstElementChild.before(nickLi);
    nickLi.after(' ');
    links.appendChild(reportLi);
    reportLi.before(' ');
    links.appendChild(quoteLi);
    quoteLi.before(' ');
    links.appendChild(advancedQuoteLi);
    advancedQuoteLi.before(' ')
}

// Принимает событие клика, копирует в буфер обмена текст поля, на котором кликнули
function copyNick (e) {
    e.target.select();
    if (document.execCommand('copy')) {
      	popup('Текст скопирован в буфер обмена')
    }
}

// Принимает блок с кодом, выделяет его текст
function selectCode (codeNode) {
    let range = document.createRange();
    range.selectNodeContents(codeNode.firstElementChild);
    
    let selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(range)
}

// Принимает блок с кодом, сворачивает/разворачивает его
function toggleCodeSpoiler(codeNode) {
    codeNode.classList.toggle('unspoiled')
}

/*
 * Date Format 1.2.3
 * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
 * MIT license
 *
 * Includes enhancements by Scott Trenda <scott.trenda.net>
 * and Kris Kowal <cixar.com/~kris.kowal/>
 *
 * Accepts a date, a mask, or a date and a mask.
 * Returns a formatted version of the given date.
 * The date defaults to the current date/time.
 * The mask defaults to dateFormat.masks.default.
 */

var dateFormat = function () {
	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
		timezoneClip = /[^-+\dA-Z]/g,
		pad = function (val, len) {
			val = String(val);
			len = len || 2;
			while (val.length < len) val = "0" + val;
			return val;
		};

	// Regexes and supporting functions are cached through closure
	return function (date, mask, utc) {
		var dF = dateFormat;

		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
		if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
			mask = date;
			date = undefined;
		}

		// Passing date through Date applies Date.parse, if necessary
		date = date ? new Date(date) : new Date;
		if (isNaN(date)) throw SyntaxError("invalid date");

		mask = String(dF.masks[mask] || mask || dF.masks["default"]);

		// Allow setting the utc argument via the mask
		if (mask.slice(0, 4) == "UTC:") {
			mask = mask.slice(4);
			utc = true;
		}

		var	_ = utc ? "getUTC" : "get",
			d = date[_ + "Date"](),
			D = date[_ + "Day"](),
			m = date[_ + "Month"](),
			y = date[_ + "FullYear"](),
			H = date[_ + "Hours"](),
			M = date[_ + "Minutes"](),
			s = date[_ + "Seconds"](),
			L = date[_ + "Milliseconds"](),
			o = utc ? 0 : date.getTimezoneOffset(),
			flags = {
				d:    d,
				dd:   pad(d),
				ddd:  dF.i18n.dayNames[D],
				dddd: dF.i18n.dayNames[D + 7],
				m:    m + 1,
				mm:   pad(m + 1),
				mmm:  dF.i18n.monthNames[m],
				mmmm: dF.i18n.monthNames[m + 12],
				yy:   String(y).slice(2),
				yyyy: y,
				h:    H % 12 || 12,
				hh:   pad(H % 12 || 12),
				H:    H,
				HH:   pad(H),
				M:    M,
				MM:   pad(M),
				s:    s,
				ss:   pad(s),
				l:    pad(L, 3),
				L:    pad(L > 99 ? Math.round(L / 10) : L),
				t:    H < 12 ? "a"  : "p",
				tt:   H < 12 ? "am" : "pm",
				T:    H < 12 ? "A"  : "P",
				TT:   H < 12 ? "AM" : "PM",
				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
			};

		return mask.replace(token, function ($0) {
			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
		});
	};
}();

// Some common format strings
dateFormat.masks = {
	"default":      "ddd mmm dd yyyy HH:MM:ss",
	shortDate:      "m/d/yy",
	mediumDate:     "mmm d, yyyy",
	longDate:       "mmmm d, yyyy",
	fullDate:       "dddd, mmmm d, yyyy",
	shortTime:      "h:MM TT",
	mediumTime:     "h:MM:ss TT",
	longTime:       "h:MM:ss TT Z",
	isoDate:        "yyyy-mm-dd",
	isoTime:        "HH:MM:ss",
	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};

// Internationalization strings
dateFormat.i18n = {
	dayNames: [
		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
	],
	monthNames: [
		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
	]
};

// Принимает событие отправки формы поиска в Google.
// Перенаправляет пользователя на страницу поиска Google по сайту
function searchByGoogle(event) {
    event.preventDefault();
    let term = document.getElementById('qg').value;
    let redirect = 'https://www.google.com/search?q=' + term + ' site:linux.org.ru';
    window.location.href = redirect
}


// Основной код

const LOR_CSS = `
    .code {
        overflow: scroll;
    }

    .code.spoiled {
        overflow-y: scroll;
    }

    .code pre {
        overflow-x: unset;
        overflow-y: unset;
        word-wrap: initial;
    }

    pre code {
    	white-space: pre;
    }

    .code .spoiler-open {
        display: none;
    }

    .stars {
        display: none;
    }

    .reactions {
        display: none;
    }

    #markup-panel .btn {
        margin: 2px;
    }

    .tag-cloud {
        display: none;
    }

    #qg {
        margin-right: 5px;
    }

    a img.lorpic {
        max-width: 700px;
    }

    @media (max-width: 900px) {
        a img.lorpic {
            max-width: 60vw;
            height: auto;
        }
        
        .popup-message {
            width: 90vw;
        }
    }

    .user-tag {
        display: none;
    }

    .popup-message {
        visibility: hidden;
        opacity: 0;
        position: fixed;
        right: 20px;
        bottom: 20px;
        padding: 10px;
        width: 300px;
        border-style: solid;
        transition-property: opacity;
        transition-duration: 1s;
        transition-timing-function: linear;
    }

    .shown {
        visibility: visible;
        opacity: 1;
    }
`;
const LOR_DARK = `
    .messages .by-ts {
        background-color: #3d2300;
    }

    a img.lorpic {
        background-color: #FFC;
    }

    .popup-message {
        border-width: thin;
        border-color: #8ae234;
        background-color: #033;
    }
`;
const LOR_LIGHT = `
    .messages .by-ts {
        background-color: #FFC;
    }

    .popup-message {
        border-width: medium;
        border-color: #000;
        background-color: #FC6;
    }
    
    div.code {
        background-color: #FFF;
    }
`;

const LOR_BLACK = `
    .ts-nick::after {
        content: '[ТС]';
        color: #F30;
        font-weight: bold;
    }

    a img.lorpic {
        background-color: #FFC;
    }

    .popup-message {
        border-width: thin;
        border-color: #8ae234;
        background-color: #033;
    }
`;

const theme = getCurrentTheme();

addCss(LOR_CSS);

if (theme == 'tango') {
    addCss(LOR_DARK)
}
else if (theme == 'waltz') {
    addCss(LOR_LIGHT)
}
else if (theme == 'black') {
    addCss(LOR_BLACK)
}

CommentForm = document.forms.commentForm || document.forms.messageForm;

if (CommentForm) {
    handleCommentForm(CommentForm);
}

let firstSign = document.querySelector('footer div.sign');
let TS = firstSign ? firstSign.firstElementChild.textContent : null;
if (TS) {
  	let nextBlock = firstSign.parentElement.nextElementSibling;
    if (nextBlock.className == "reply") {
    	addReplyLinks(nextBlock, TS)
    }
}

let comments = document.getElementById('comments') && document.getElementById('comments').getElementsByClassName('msg-container');

if (comments) {

    for (let i = 0, c = comments.length; i < c; i++) {
        
        let sign  = comments[i].getElementsByClassName('sign')[0];
        let reply = comments[i].getElementsByClassName('reply')[0];
        
        let author = sign.firstElementChild.textContent;
        let parentNode = comments[i].parentElement;
        
        if (author == TS) {
            parentNode.classList.add('by-ts');
            sign.classList.add('ts-nick')
        }
        
        // Если индекс комментария в массиве comments четный,
        if ((i % 2) == 0) {
            // то по счету комментарий нечетный
            parentNode.classList.add('odd')
        }
        else {
            parentNode.classList.add('even')
        }
        // Первый комментарий имеет индекс 0
        
        addReplyLinks(reply, author)
    }
}


// Делаем местное время

let times = document.getElementsByTagName("time");
let c = times.length;

for (i = 0; i < c; i++) {
    let attrTime = new Date(times[i].getAttribute("datetime", 0));
	let nowTime = new Date();
	let diff = Math.round(nowTime.getTime() / 1000) - Math.round(attrTime.getTime() / 1000);
    
    let attrDay = new Date(attrTime.getTime()); 
    let nowDay = new Date(nowTime.getTime());
    attrDay.setHours(0, 0, 0, 0);
    nowDay.setHours(0, 0, 0, 0);
    let today = attrDay.getTime() == nowDay.getTime();
    let yesterday = (attrDay.getTime() + 86400000) == nowDay.getTime();
    let timeText;
    
    if ((strContains(document.URL, "/tracker") || strContains(document.URL, "/notifications"))) { 
        let minutes = Math.ceil(diff / 60);
        if (minutes < 60) {
            timeText = minutes + " мин."
        }
        else if (today) {
            timeText = dateFormat(attrTime.getTime(), "HH:MM:ss")
        }
        else if (yesterday) {
            timeText = "вчера " + dateFormat(attrTime.getTime(), "HH:MM:ss")
        }
        else {
            timeText = dateFormat(attrTime.getTime(), "dd.mm.yy HH:MM")
        }
    }
    else {
        if (today) {
            timeText = "сегодня " + dateFormat(attrTime.getTime(), "HH:MM")
        }
        else if (yesterday) {
            timeText = "вчера " + dateFormat(attrTime.getTime(), "HH:MM")
        }
        else {
            timeText = dateFormat(attrTime.getTime(), "dd.mm.yyyy HH:MM")
        }
    }
    times[i].innerHTML = timeText
}


// Настраиваем меню

if (theme == 'tango' || theme == 'waltz') {
    let menu = document.getElementsByClassName('menu')[0].getElementsByTagName('ul')[0]; // Главное меню

    if (TECH_ONLY_BY_DEFAULT) {
        menu.children[4].firstElementChild.href = '/tracker/?filter=tech';
    }

    if (HIDE_NEWS_AND_GALLERY) {
        // Убираем первые два раздела - новости и галерею
        menu.firstElementChild.remove();
        menu.firstElementChild.remove();
    }

    if (ADD_TAGS_AND_DOCS) {
        let itmTags = _setup('li');  let itmWiki = _setup('li');
        let linkTags = _setup(
            'a',
            { href: '/tags/', text: 'Теги' }
        );
        let linkWiki = _setup(
            'a',
            { href: 'http://lorwiki.zhbert.ru/', text: 'Документация', target: '_blank' }
        );
        itmTags.appendChild(linkTags); itmWiki.appendChild(linkWiki);

        menu.appendChild(itmTags);
        menu.appendChild(itmWiki);
        itmWiki.before(' ');
    }
}

// =================================================================================

let related = document.getElementById('related-topics');
if (related) {
    let btnItsSpectopic = _setup(
        'input',
        { type: 'button', value: 'Это спецтопик' },
        { click: itsSpecTopic }
    );
    related.before(btnItsSpectopic);
}

// Добавляем всплывающее уведомление
divPopup = _setup(
    'div',
    { class: 'popup-message' }
);
document.body.appendChild(divPopup);


// Сворачиваемый и копируемый код

let codes = document.querySelectorAll('div.code');

for (let i = 0, c = codes.length; i < c; i++) {
    let code = codes[i];
    let linkToggleCodeSpoiler = _setup(
        'a',
        { href: '#toggleCodeSpoiler', text: 'Развернуть/Свернуть' },
        { click: (e) => { e.preventDefault(); toggleCodeSpoiler(code) } }
    );
    let linkSelectCode = _setup(
        'a',
        { href: '#selectCode', text: 'Выделить' },
        { click: (e) => { e.preventDefault(); selectCode(code) } }
    );
  	let codeControls = _setup(
      	'div',
      	{ class: 'code-controls' }
     );
  	codeControls.appendChild(linkToggleCodeSpoiler);
  	codeControls.appendChild(linkSelectCode);
  	
    linkToggleCodeSpoiler.before('[');
    linkSelectCode.before('] [');
    linkSelectCode.after(']');
  
  	code.before(codeControls)
}


// Картинки

let links = document.getElementsByTagName('a');

for (i = 0, c = links.length; i < c; i++) {
    let link = links[i];
    if (!link.getAttribute('itemprop')) {
        let url = link.href;
        let ext = _getUrlExt(url);
        if (formats.includes(ext)) {
            let content = link.textContent;
            if (content != 'Просмотр') {
                let image = _setup(
                    'img',
                    { class: 'lorpic', src: url, title: content, alt: url },
                );
                link.innerHTML = '';
                link.target = '_blank';
                link.appendChild(image)
            }
        }
    }
}

// ================================================================================

if (window.location.pathname == '/tags/') {
    tagSearchBar = _setup('div', { style: 'margin: 20px 0' });
    let tagSearchInput = _setup(
        'input', 
        { placeholder: 'Поиск меток ...', size: 30, autofocus: true }, 
        { keyup: searchTags }
    );
    tagSearchBar.appendChild(tagSearchInput);
    let tagsFirstLetters = document.getElementsByClassName('tags-first-letters')[0];
    tagsFirstLetters.after(tagSearchBar);
    tagListWrapper = _setup('span');
    tagSearchBar.after(tagListWrapper);
  	
  	document.getElementsByTagName('section')[0].className = 'tag-cloud'
}

if (window.location.pathname.startsWith('/people')) {
    let profile = document.getElementsByClassName('vcard')[0]
    
    if (profile) {
        let nick = profile.getElementsByClassName('nickname')[0];
        let nickName = '[user]' + nick.textContent.trim() + '[/user]';
        
      	profile.appendChild(_setup('br'));
        profile.appendChild(_setup('b', { text: 'Копировать ник: ' }));
        let copyInput = _setup(
            'input', 
            { value: nickName, size: nickName.length, readOnly: true },
            { click: copyNick }
        );
        profile.appendChild(copyInput);
        profile.appendChild(_setup('br'))
    }
}

if ((window.location.pathname == '/search.jsp') && (window.location.search == '')) {
    let searchContainer = document.getElementById('bd');
    let hdrGoogle = _setup(
        'h1',
        { text: 'Поиск в Google' }
    );
    let inpGoogle = _setup(
        'input',
        { id: 'qg', size: 50, class: 'input-lg', type: 'search', maxlength: 250 }
    );
    let btnGoogle = _setup(
        'button',
        { class: 'btn btn-primary', text: 'Поиск' }
    )
    let googleSearchBar = _setup(
        'form', 
        { class: 'control-group' },
        { submit: searchByGoogle }
    );
    googleSearchBar.appendChild(hdrGoogle);
    googleSearchBar.appendChild(inpGoogle);
    googleSearchBar.appendChild(btnGoogle);
    
    searchContainer.appendChild(googleSearchBar);
    
    let defaultSortOrder = _setup(
        'input',
        { type: 'hidden', name: 'sort', value: 'DATE' }
    );
    
    if (NEW_TO_OLD_SEARCH_BY_DEFAULT) {
        searchContainer.getElementsByTagName('form')[0].appendChild(defaultSortOrder)
    }
}

 

damix9
()

RSS подписка на новые темы