Versions 4pda

Вывод версий приложений в Избранном 4pda, показ обновленных приложений

01.06.2019 itibariyledir. En son verisyonu görün.

// ==UserScript==
// @name            Versions 4pda
// @namespace       http://4pda.ru/forum/index.php
// @version         1.4.1
// @description:ru  Вывод версий приложений в Избранном 4pda, показ обновленных приложений
// @author          Azat-777
// @icon            http://s.4pda.to/kkRM7z1nbI3gbG5E7r0a561qtdKnE2GlKhz1ipnv.png
// @match           http*://4pda.ru/forum/index.php?act=fav*
// @match           http*://4pda.ru/forum/index.php?showtopic=*
// @grant           GM_xmlhttpRequest
// @history:ru      26.07.2017: допиливание мелочей
// @history:ru      31.07.2017: расширение функционала скрипта: подробная информация о каждом пользователе в топиках
// @history:ru      04.08.2017: добавлено мигание 'NEW'
// @history:ru      02.01.2018: небольшие правки кода
// @history:ru      10.05.2018: изменение списка обновленных приложений
// @history:ru      11.05.2018: мелкие правки и исправления
// @history:ru      20.05.2018: добавлено удаление пробелов в начале и конце названий версий, чтобы из-за пробелов версия не определялась как новая
// @history:ru      16.08.2018: теперь обновления не исчезают с обновлением страницы, для ручного скрытия обновлений добавлена кнопка
// @history:ru      17.08.2018: правка вчерашних ошибок, добавление мелочей (title и переход к последнему непрочитанному сообщению в теме
// @history:ru      17.08.2018: обновленного приложения); реализация скрытия обновлений по одному: убрад мигание NEW для обновлений, т.к. уже неактуально
// @history:ru      20.08.2018: починен показ кнопки скрытия отдельного обновления; в консоли выводится объем загруженого XHR-запросами траффика
// @history:ru      06.05.2019: кроме слова 'версия' другой текст, если он был, не удалялся, поправлено
// @history:ru      01.06.2019: слово 'версия' не заменялось на 'v.', если после него не было пробела. Недоработка в регулярках. Поправлено
// @description Вывод версий приложений в Избранном 4pda, показ обновленных приложений
// ==/UserScript==

(function() {
    'use strict';
    //============================================================
    // получение ссылки текущей страницы
    var URL = window.document.URL;
    //console.log(URL);
    //============================================================
    // удаляем рекламу и центрируем логотип 4pda
    var tbody = document.getElementsByTagName('tbody')[0],
        td = tbody.getElementsByTagName('td');
    td[1].remove();
    td[0].align = 'center';
    //============================================================
    var favURL = '4pda.ru/forum/index.php?act=fav', i,
        head = document.getElementsByTagName('head')[0];
    //var topicURL = 'http://4pda.ru/forum/index.php?showtopic=';

    // спойлер с объявлениями всегда скрыт
    if(document.querySelector('#gc_1, #go_1')) {
        document.querySelector('#go_1').style.display = 'none';
        document.querySelector('#gc_1').style.display = 'none';
    }
    var l = 0,        // счетчик
        totalKB = 0,
        totalMB = 0;

    // Избранное
    if (~URL.indexOf(favURL))
    {
        //localStorage
        //localStorage.clear();
        //============================================================
        // добавление в строке названий приложений их версий
        var ver;
        // находим таблицу
        var tbl = document.getElementsByClassName('ipbtable')[0];
        var tbody2 = tbl.getElementsByTagName('tbody')[0];
        var _tr = tbody2.getElementsByTagName('tr');
        // запихиваем в tr нужные нам строки таблицы
        var tr = [];
        for(i=0; i<_tr.length; i++)
        {
            if (_tr[i].hasAttribute('data-item-fid')) // отсортировываем из таблицы только темы
                tr.push(_tr[i]);                      // запихиваем в массив tr
        }
        var trLength = tr.length
        var name = [];                                // названия тем
        for (i=0; i<trLength; i++)
        {
            var tmp = tr[i].getElementsByTagName('td')[1].getElementsByTagName('span')[0].getElementsByTagName('a')[0];
            getVersion(tmp.getAttribute('href'), i);
            //getVersion(tmp.href, i);
            name.push(tmp);
        }
        //=====================================================
        // добавление счетчика с количеством новых версий приложений
        var count = 0,
            _span = document.createElement('span');
        _span.id = 'count';
        _span.style.color = 'black';
        var navstrip = document.getElementById('navstrip');
        //=====================================================
        var app_name,
            saveToHideName = [],
            saveToHideVer = [];
        /*_new = ' <mytag class="new" style="color: red"><b>NEW</b></mytag>',*/

        function getVersion(link, i)
        {
            var XHR = ("onload" in new XMLHttpRequest()) ? XMLHttpRequest : XDomainRequest;
            var xhr = new XHR();
            xhr.open('GET', link, true);
            xhr.send();
            xhr.onload = function()
            {
                if(this.readyState === 4)
                {
                    if (this.status === 200)
                    {
                        var response = xhr.responseText;
                        var parser = new DOMParser();
                        var doc = parser.parseFromString(response, 'text/html');
                        var tbl = doc.getElementsByClassName('ipbtable');
                        for (var j=0; j<tbl.length; j++)
                        {
                            if (tbl[j].hasAttribute('data-post'))
                            {
                                var tbody = tbl[j].getElementsByTagName('tbody')[0],
                                    tr2 = tbody.getElementsByTagName('tr')[1],
                                    td = tr2.getElementsByTagName('td')[1],
                                    div = td.getElementsByClassName('postcolor')[0],
                                    span = div.getElementsByTagName('span');
                                for (var k=0; k<span.length; k++)
                                {
                                    // версии приложений
                                    if (span[k].getAttribute('style') == 'font-size:12pt;line-height:100%')
                                    {
                                        if (~span[k].innerHTML.toLowerCase().indexOf('верси'))
                                        {
                                            // замена
                                            var replace_ver = span[k].innerHTML,
                                                alt_ver;
                                            // если тема не была открыта
                                            if (~name[i].innerHTML.indexOf('<strong>'))
                                            {
                                                replace_ver = replace_ver.toLowerCase().replace(/[А-Яа-я\s]*верси[ия]:[\s]*/, 'v.').replace(/<[\/]*b[r]*>/g, '').trim();
                                                alt_ver = replace_ver;
                                                var alt_name;
                                                alt_name = name[i].innerHTML.replace(/<[\/]*strong>/g, '');
                                                // сравнение версий: текущей полученной и сохраненной в локальном хранилище
                                                if (alt_ver.localeCompare(localStorage.getItem(alt_name)) !== 0) {
                                                    showNotif(alt_name, alt_ver);
                                                }
                                            }
                                            // если тема была открыта и просмотрена
                                            else
                                            {
                                                replace_ver = replace_ver.toLowerCase().replace(/<b>[А-Яа-я\s]*верси[ия]:[\s]*/, 'v.').replace(/<[\/]*b>/g, '').trim();
                                                alt_ver = replace_ver;
                                                if (replace_ver.localeCompare(localStorage.getItem(name[i].innerHTML)) !== 0) {
                                                    showNotif(name[i].innerHTML, alt_ver);
                                                }
                                            }
                                            // вывод обновленных приложений вверху
                                            function showNotif(alt_name, alt_ver) {
                                                hideBtn.style.display = 'inline';    // показываем скрытую кнопку, если есть обновления
                                                //replace_ver += _new;               // прибавляем тэг 'NEW' для новой версии
                                                count++;
                                                var goto = '<a href="'+link+'&amp;view=getnewpost"><img src="//s.4pda.to/kkRMw9H6PDJH2O7aOGE4gWJpHLz0xXN6ymhvGxkFLXM.gif" alt=">N" title="Перейти к первому непрочитанному" border="0"></a> '
                                                app_name = goto + '<a href="'+link+'" title="Перейти к первому сообщению">'+alt_name + '</a>';
                                                saveToHideName.push(alt_name);
                                                saveToHideVer.push(alt_ver);
                                                showUpdates(app_name, alt_ver);
                                            }
                                            replace_ver = '<font color="#8A2BE2"> ' + replace_ver + '</font>'; // добавление цвета для наглядности
                                            name[i].innerHTML += replace_ver;
                                        }
                                        break;
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
            };
            xhr.onerror = function() {
                console.log('onerror');
                alert('Ошибка');
            };
            xhr.onloadend = function(event) {
                //console.log('onloadend');
                totalKB += (event.loaded/1024); // подсчет загруженного траффика
                totalMB += (event.loaded/1024/1024);
                if(++l === trLength) {
                    addEvent(); // вешаем обработчик событий строки (появление/скрытие кноки "Скрыть")
                    hideApp();  // скрытие строки с обновленным приложением
                    console.log('Скачано XHR-запросами:', totalKB.toFixed(2), 'КБ |', totalMB.toFixed(2), 'МБ'); // вывод объема скачанного
                }
            };
            xhr.onprogress = function(event) {
                //console.log('onprogress');
            };
        }
        // переопределяем стиль для кнопок
        var btnStyle = document.createElement('style');
        btnStyle.type = 'text/css';
        var _s = `
.myBtn {
display: inline-block;
font-family: arial,sans-serif;
font-size: 10px;
font-weight: bold;
color: rgb(68,68,68);
text-decoration: none;
user-select: none;
padding: .1em 1.2em;
outline: none;
border: 1px solid rgba(0,0,0,.1);
border-radius: 2px;
background: rgb(245,245,245) linear-gradient(#f4f4f4, #f1f1f1);
transition: all .218s ease 0s;
}
.myBtn:hover {
color: rgb(24,24,24);
border: 1px solid rgb(198,198,198);
background: #f7f7f7 linear-gradient(#f7f7f7, #f1f1f1);
box-shadow: 0 1px 2px rgba(0,0,0,.1);
}
.myBtn:active {
color: rgb(51,51,51);
border: 1px solid rgb(204,204,204);
background: rgb(238,238,238) linear-gradient(rgb(238,238,238), rgb(224,224,224));
box-shadow: 0 1px 2px rgba(0,0,0,.1) inset;
}`;
        var _st = document.createTextNode(_s);
        btnStyle.appendChild(_st);
        head.appendChild(btnStyle);

        navstrip.appendChild(_span);
        _span.innerHTML = '<br/><br/> Обновлений: ' + '<font id="_cnt" color="red">' + count + '</font> <input id="hideBtn" class="myBtn" type="button" value="Скрыть обновления" style="display: none;" /> <br/>' +
            `<table id="_tbl" style="border-collapse: collapse; border: 0px">
<thead> <tr> <th class="one">#</th> <th class="two">Название</th> <th>Версия</th> </tr> </thead>
<tbody> </tbody>
</table>`;
        var _tbl = document.querySelector('#_tbl'),
            _tbody = _tbl.querySelector('tbody'),
            _cnt = document.querySelector('#_cnt'),
            n = 0;
        _tbl.style.display = 'none';

        var tblStyle = document.createElement('style');
        tblStyle.type = 'text/css';
        var s = `
#_tbl th {
color: brown; background-color: white; text-align: center; padding: 2px; letter-spacing: 0px;
}
#_tbl td {
font-size: 10px; padding: 0 5px;
}
#_tbl .one, .two {
border-right: 1px solid
}`;
        var st = document.createTextNode(s);
        tblStyle.appendChild(st);
        head.appendChild(tblStyle);

        // кнопка скрытия обновлений вручную
        var hideBtn = document.querySelector('#hideBtn');
        hideBtn.onclick = function() {
            hideBtn.style.display = 'none';
            // сразу сохраняем обновленные версии в память, чтобы при следующем обновлении не всплыли в таблице обновлений
            for(var i=0; i<saveToHideName.length; i++) {
                localStorage.setItem(saveToHideName[i], saveToHideVer[i]);
            }
            // скрываем таблицу с обновлениями и обнуляем счетчик
            _tbl.style.display = 'none';
            count = 0;
            _cnt.innerHTML = count;
            for(; _tbody.querySelectorAll('tr').length > 0;) {
                _tbl.deleteRow(1);
            }
        }

        // показ количества обновлений и вывод их в таблице
        function showUpdates(app_name, ver)
        {
            _tbl.style.display = 'block';
            n++;
            var row = _tbody.insertRow(-1),
                cell1 = row.insertCell(-1),
                cell2 = row.insertCell(-1),
                cell3 = row.insertCell(-1),
                cell4 = row.insertCell(-1);
            row.className = 'myTr';
            cell1.className = 'one';
            cell2.className = 'two';
            cell1.innerHTML = n; _cnt.innerHTML = count;
            cell2.innerHTML = app_name;
            cell3.innerHTML = ver;
            cell4.innerHTML = '<input class="myBtn hidden" type="button" value="Скрыть" style="display: none;">';
        }

        function addEvent() {
            var myTr = document.querySelectorAll('.myTr');
            for(var i=0; i<myTr.length; i++) {
                myTr[i].addEventListener('mouseover', function showButton() {
                    this.querySelector('.hidden').style.display = 'block';
                });
                myTr[i].addEventListener('mouseout', function hideButton() {
                    this.querySelector('.hidden').style.display = 'none';
                });
            }
        }

        function hideApp() {
            var hBut = document.querySelectorAll('.myBtn.hidden');
            for(var i=0; i<hBut.length; i++) {
                hBut[i].onclick = function() {
                    var n = this.parentNode.parentNode.firstChild.innerHTML,
                        name = this.parentNode.parentNode.children[1].children[1].innerHTML,
                        ver = this.parentNode.parentNode.children[2].innerHTML;
                    localStorage.setItem(name, ver);
                    // сброс # таблицы и удаление строк(и)
                    _tbl.deleteRow(n);
                    var num = _tbl.querySelectorAll('td.one');
                    // если было скрыто последнее обновление, скрываем шапку таблицы и кнопку "Скрыть обновления"
                    if(num.length === 0) {
                        _tbl.style.display = 'none';
                        hideBtn.style.display = 'none';
                    }
                    for(var j=0; j<num.length; j++) {
                        //console.log(num[j].innerHTML);
                        num[j].innerHTML = j+1;
                    }
                    _cnt.innerHTML = j;
                }
            }
        }
        //==========================================================================
        // мигание 'NEW' // уже неактуально
        /*function mig()
        {
            var isRed = true;
            var nw = document.querySelectorAll('.new');
            var dln = nw.length;
            if (dln !== 0)
            {
                var morganie = setInterval(function() {
                    if (isRed)
                    {
                        for (i=0; i<dln; i++)
                        {
                            nw[i].style.color = 'blue';
                        }
                        isRed = false;
                    }
                    else
                    {
                        for (i=0; i<dln; i++)
                        {
                            nw[i].style.color = 'red';
                        }
                        isRed = true;
                    }
                }, 300);
            }
        }*/
    }
    else
    {
        // Топики
        var post = document.querySelectorAll('.postdetails > center'),
            userLink = document.getElementsByClassName('normalname'),
            link = [], // собираем все ссылки на профили
            ulLength = userLink.length;

        for (i=0; i<ulLength; i++)
        {
            getUserData(userLink[i].querySelector('a').getAttribute('href'), i);
        }
        //==========================================================================
        var data0, data1, data2, data3; // пол, город, дата рождения, местное время
        // создание области для новых данных
        var div = document.createElement('div');
        div.style.border = '1px solid lightblue';
        div.style.padding = '5px';
        div.id = 'myDiv';

        // Стиль для новой области
        var style = document.createElement('style');
        style.type = 'text/css';
        var h = '#myDiv:hover {background: PaleTurquoise; color: blue; font-size: 10pt;}';
        var hover = document.createTextNode(h);
        style.appendChild(hover);
        //head = document.getElementsByTagName('head')[0];
        head.appendChild(style);

        function getUserData(link, i) {
            var XHR = ("onload" in new XMLHttpRequest()) ? XMLHttpRequest : XDomainRequest;
            var xhr = new XHR();
            xhr.open('GET', link, true);
            xhr.send();
            xhr.onload = function()
            {
                if(this.readyState === 4)
                {
                    if (this.status === 200)
                    {
                        var response = xhr.responseText;
                        var parser = new DOMParser();
                        var doc = parser.parseFromString(response, 'text/html');
                        var main = doc.getElementsByClassName('info-list width1 black-link')[0];
                        main.style.marginLeft = 0;
                        main.style.paddingLeft = 0;
                        main.style.display = 'block';
                        main.style.listStyle = 'none';
                        var t = main.querySelectorAll('li'),
                            tt = '';
                        for (var l=0; l<t.length; l++)
                        {
                            tt += t[l].innerHTML.replace(/<[^>]+>/g,'').replace(/(Город:)/, '$1 ').replace(/(юзера:)/, '$1 ').replace(/(рождения:)/, '$1 ') + '<br/>';
                        }
                        insertData(tt, i);
                    }
                }
            };
            xhr.onerror = function() {
                console.log('error');
                alert('Ошибка');
            };
            xhr.onloadend = function(event) {
                //console.log('onloadend');
                totalKB += (event.loaded/1024); // подсчет загруженного траффика
                totalMB += (event.loaded/1024/1024);
                if(++l === ulLength) {
                    console.log('Скачано XHR-запросами:', totalKB.toFixed(2), 'КБ |', totalMB.toFixed(2), 'МБ'); // вывод объема скачанного
                }
            };
        }

        //==========================================================================
        function insertData(data0, i) {
            div.innerHTML = data0;
            post[i].appendChild(div.cloneNode(true));
        }
    }
})();
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元