PubMed快捷键

高亮Review标签,增加功能按钮,一键收藏PubMed文献到默认收藏夹或导出nbib文件

// ==UserScript==
// @name         PubMed快捷键
// @version      2024.08.08
// @description  高亮Review标签,增加功能按钮,一键收藏PubMed文献到默认收藏夹或导出nbib文件
// @author       SpaceThing
// @license      GPL-3.0-or-later
// @match        https://pubmed.ncbi.nlm.nih.gov/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=nih.gov
// @namespace    https://greasyfork.org/users/916402
// @grant        none
// ==/UserScript==
(function() {
    'use strict';

    function start() {
        var currentPage = window.location.href;
        if (currentPage.includes("https://pubmed.ncbi.nlm.nih.gov/?term=")) {
            searchPage();
            console.log('PubMed快捷键:搜索页')
        } else if (currentPage.match(/https:\/\/pubmed\.ncbi\.nlm\.nih\.gov\/\d+\//)) {
            detailPage();
            console.log('PubMed快捷键:详情页')
        };
    }

    // 创建遮罩层和弹窗
    function createPopup(note, content) {
        // 创建遮罩层
        var overlay = document.createElement('div');
        overlay.className = 'popup-overlay ' + note;
        overlay.style.position = 'fixed';
        overlay.style.width = '100%';
        overlay.style.height = '100%';
        overlay.style.zIndex = '10000';
        document.body.appendChild(overlay);
        // 创建弹窗
        var popup = document.createElement('div');
        popup.className = 'notification';
        popup.innerHTML = '<div class="popup-content noty_type__information uswdsTheme"></div>';
        overlay.appendChild(popup);
        if (content) {
            overlay.querySelector('.popup-content').innerHTML = content;
        };
    };

    // 修改弹窗文本
    function changePopup(note, content) {
        var overlay = document.querySelector('.' + note);
        if (overlay) {
            overlay.querySelector('.popup-content').innerHTML = content;
        };
    };

    // 关闭弹窗
    function closePopup(note) {
        var overlay = document.querySelector('.' + note);
        if (overlay) {
            overlay.remove();
        };
    };

    // 点击关闭弹窗
    function clickClose() {
        var overlay = document.querySelector('.popup-overlay');
        if (overlay) {
            overlay.addEventListener('click',
                                     function() {
                if (event.target.classList.contains('popup-overlay')) {
                    var overlay = document.querySelector('.popup-overlay');
                    if (overlay) {
                        overlay.remove();
                    };
                };
            });
        };
    };

    // 切换点击穿透
    function setPointerEvents(element, allowPointerEvents) {
        if (allowPointerEvents) {
            element.style.pointerEvents = 'none';
        } else {
            element.style.pointerEvents = 'auto';
        };
    };

    function searchPage() {
        // 高亮Review标签
        var publicationType = document.querySelectorAll('.publication-type');
        if (publicationType) {
            for (var i = 0; i < publicationType.length; i++) {
                var element = publicationType[i];
                if (element.textContent.trim() == 'Review.') {
                    element.style.backgroundColor = '#20558A';
                    element.style.borderRadius = '0.5rem';
                    element.style.color = 'white';
                    element.style.marginLeft = '20px';
                    element.style.paddingLeft = '5px';
                    element.style.paddingRight = '5px';
                };
            };
        };

        // 创建Filter out review按钮
        var notReview = document.createElement('div');
        notReview.className = 'form-field filters-field';
        notReview.innerHTML = '<div class="form-field filters-field"><div class="actions-bar" style="margin-top: 0px;"><button id="not-review" type="button" class="reset-btn usa-button-outline" style="width: 100%; margin-top: 10px;">Filter Out Review</button></div></div>';
        document.querySelector('.user-filters').insertAdjacentElement('afterend', notReview);
        document.querySelector("#not-review").addEventListener('click', notReviewFunc);

        // Filter out review按钮点击事件
        function notReviewFunc() {
            var currentUrl = window.location.href;
            var urlParams = new URLSearchParams(window.location.search);
            var termValue = urlParams.get('term');
            var notReview = decodeURIComponent(termValue).includes('NOT (Review[Publication Type])');
            if (!notReview) {
                var originalTerm = termValue.replace(/ /g, '+');
                var modifiedTerm = '(' + originalTerm + ')+NOT+(Review[Publication+Type])';
                var newUrl = currentUrl.replace(originalTerm, modifiedTerm);
                window.location.href = newUrl;
            } else {
                // 显示弹窗
                createPopup('notReview', 'All ready filtered out review.');
                // 启用点击穿透
                var overlay = document.querySelector('.popup-overlay');
                setPointerEvents(overlay, true);
                // 禁用点击穿透
                setTimeout(function() {
                    setPointerEvents(overlay, false);
                }, 250);
                setTimeout(function() {
                    closePopup('notReview');
                }, 10000);
                clickClose();
            };
        };
    };

    function detailPage() {
        // 获取默认收藏夹id
        window.haveId = false;
        // 获取nbib文件
        window.haveNbib = false;
        // 获取PMID
        window.pmid = document.querySelector('.current-id').innerText;
        // 获取标题
        window.title = document.querySelector('.heading-title').innerText;
        // 获取年份
        window.year = document.querySelector('#full-view-heading .cit').innerText.match(/\d+(?= )/);
        // 获取期刊
        window.journal = document.querySelector('#full-view-journal-trigger').innerText;
        // 获取作者
        window.authors = formatAuthors(document.querySelectorAll('#full-view-heading .full-name')[0].textContent);
        // 获取csrfmiddlewaretoken
        window.csrfmiddlewaretoken = document.querySelector('input[name=csrfmiddlewaretoken]').value;

        // 设置通用弹窗提示语
        window.loading = 'Loading...';
        window.timeout = 'Timeout, please try again.';
        window.fail = 'An unexpected error occurred, please try again.';
        window.login = 'Please <a href = ' + document.querySelector("#account_login").href + '>log in</a> first.';

        // 获取默认收藏夹id
        getCollections();
        function getCollections() {
            if (!window.haveId) {
                // 获取收藏夹列表
                var xhrCollections = new XMLHttpRequest();
                xhrCollections.open('GET', 'https://pubmed.ncbi.nlm.nih.gov/list-existing-collections/');
                xhrCollections.send();
                xhrCollections.onreadystatechange = function() {
                    if (xhrCollections.readyState == 4) {
                        if (xhrCollections.status == 200) {
                            // 提取默认收藏夹的id
                            var response = xhrCollections.responseText;
                            var json = JSON.parse(response);
                            json.collections.forEach(function(collection) {
                                if (collection.name == "Favorites") {
                                    window.collection_id = collection.id;
                                    window.haveId = true;
                                    window.success = 'New items were added to your collection. <a href="https://www.ncbi.nlm.nih.gov/myncbi/collections/' + window.collection_id + '/">Edit your collection.</a>';
                                    console.log('Successfully retrieved Favorites id');
                                }
                            });
                        } else {
                            // 请求失败,打印错误信息
                            console.log('There has been a problem fetching favorites id');
                        };
                    };
                };
            };
        };

        // 获取nbib文件
        getNbib();
        function getNbib() {
            if (!window.haveNbib) {
                var xhrNbib = new XMLHttpRequest();
                var nbib = 'https://api.ncbi.nlm.nih.gov/lit/ctxp/v1/pubmed/?format=medline&download=y&id=' + window.pmid;
                xhrNbib.responseType = 'blob';
                xhrNbib.open('GET', nbib);
                xhrNbib.send();
                xhrNbib.onreadystatechange = function() {
                    if (xhrNbib.readyState == 4) {
                        if (xhrNbib.status == 200) {
                            // 储存nbib为blob
                            var blob = xhrNbib.response;
                            window.nibi_blob = window.URL.createObjectURL(blob);
                            var link = document.createElement('a');
                            link.className = 'nbib-link';
                            link.href = window.nibi_blob;
                            link.download = window.year + ', ' + window.authors + ', ' + window.title + '.nbib';
                            document.body.appendChild(link);
                            window.haveNbib = true;
                            console.log('Successfully retrieved nbib');
                        } else {
                            // 请求失败,打印错误信息
                            console.log('There has been a problem fetching nbib');
                            changePopup('nbib', window.fail);
                            setTimeout(function() {
                                closePopup('nbib');
                            }, 10000);
                            clickClose();
                        };
                    };
                };
            };
        };

        // 添加当前文献到默认收藏夹
        function addFavorites() {
            var overlay = document.querySelector('.popup-overlay');
            // 构造请求
            var data = 'article_ids=' + window.pmid + '&csrfmiddlewaretoken=' + window.csrfmiddlewaretoken + '&collection_id=' + window.collection_id;
            // 发送收藏请求
            var xhrFavorites = new XMLHttpRequest();
            xhrFavorites.open('POST', 'https://pubmed.ncbi.nlm.nih.gov/add-to-existing-collection/');
            xhrFavorites.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhrFavorites.send(data);
            // 判断是否收藏成功,并提示任务状态
            xhrFavorites.onreadystatechange = function() {
                if (xhrFavorites.readyState == 4 && xhrFavorites.status == 200) {
                    var response = xhrFavorites.responseText;
                    var answer = '{"collection_id": "' + window.collection_id + '"}';
                    if (response == answer) {
                        changePopup('favorites', window.success);
                        // 禁用点击穿透
                        setTimeout(function() {
                            setPointerEvents(overlay, false);
                        }, 250);
                    } else {
                        changePopup('favorites', window.fail);
                        // 禁用点击穿透
                        setTimeout(function() {
                            setPointerEvents(overlay, false);
                        }, 250);
                    };
                } else {
                    changePopup('favorites', window.fail);
                    // 禁用点击穿透
                    setTimeout(function() {
                        setPointerEvents(overlay, false);
                    }, 250);
                };
                setTimeout(function() {
                    closePopup('favorites');
                }, 10000);
                clickClose();
            };
        }

        // 格式化作者信息
        function formatAuthors(name) {
            // 将名字按空格和连接符分割成数组
            var parts = name.split(/[\s-]+/);
            // 如果只有一个部分,则直接返回
            if (parts.length == 1) {
                return name;
            };
            // 获取最后一个部分作为姓氏
            var lastName = parts.pop();
            // 获取其他部分作为名字,并将它们转换为首字母大写
            var firstName = parts.map(part => part.charAt(0).toUpperCase()).join('');
            return lastName + ' ' + firstName;
        }

        // 创建收藏和nbib按钮
        var place = document.querySelector('.collections-button-container');
        if (place) {
            // 创建收藏按钮
            var favoritesButton = document.createElement('button');
            favoritesButton.className = 'collections-button';
            favoritesButton.setAttribute('id', 'favoritesButton');
            favoritesButton.innerHTML = '<span class="button-label">Favorites</span>';
            place.appendChild(favoritesButton);
            // 创建nbib按钮
            var nbibButton = document.createElement('button');
            nbibButton.className = 'collections-button';
            nbibButton.setAttribute('id', 'nbibButton');
            nbibButton.innerHTML = '<span class="button-label">nbib</span>';
            place.appendChild(nbibButton);
        };
        var inline = document.querySelector('.actions-buttons.inline > .inner-wrap')
        if (inline) {
            // 删除不必要按钮
            inline.querySelector('.citation-button').remove();
            inline.querySelector('.more-actions-button').remove();
            // 创建收藏按钮
            var favoritesButton = document.createElement('button');
            favoritesButton.className = 'citation-button';
            favoritesButton.setAttribute('id', 'favoritesButton-inline');
            favoritesButton.innerHTML = '<span class="button-label">Favorites</span>';
            inline.appendChild(favoritesButton);
            // 创建nbib按钮
            var nbibButton = document.createElement('button');
            nbibButton.className = 'citation-button';
            nbibButton.setAttribute('id', 'nbibButton-inline');
            nbibButton.innerHTML = '<span class="button-label">nbib</span>';
            inline.appendChild(nbibButton);;
        };

        // 收藏按钮点击事件
        function favoritesButtonClick() {
            // 显示弹窗
            createPopup('favorites');
            changePopup('favorites', window.loading);
            // 启用点击穿透
            var overlay = document.querySelector('.popup-overlay');
            setPointerEvents(overlay, true);
            if (!window.haveId) {
                getCollections();
            };
            if (window.haveId) {
                addFavorites();
            } else {
                // 提示登录
                changePopup('favorites', window.login);
                setTimeout(function() {
                    closePopup('favorites');
                }, 10000);
                // 禁用点击穿透
                setTimeout(function() {
                    setPointerEvents(overlay, false);
                }, 250);
                clickClose();
            };
        };

        document.querySelector('#favoritesButton').addEventListener('click', favoritesButtonClick);
        document.querySelector('#favoritesButton-inline').addEventListener('click', favoritesButtonClick);

        // nbib按钮点击事件
        function nbibButtonClick() {
            if (!window.haveNbib) {
                // 显示弹窗
                createPopup('nbib');
                changePopup('nbib', window.loading);
                // 启用点击穿透
                var overlay = document.querySelector('.popup-overlay');
                setPointerEvents(overlay, true);
                getNbib();
                setTimeout(function() {
                    changePopup('nbib', window.timeout);
                    setTimeout(function() {
                        closePopup('nbib');
                    }, 10000);
                }, 3000);
                // 禁用点击穿透
                setTimeout(function() {
                    setPointerEvents(overlay, false);
                }, 250);
                clickClose();
            };
            if (window.haveNbib) {
                var link = document.querySelector('.nbib-link');
                link.click();
            };
        };

        document.querySelector('#nbibButton').addEventListener('click', nbibButtonClick);
        document.querySelector('#nbibButton-inline').addEventListener('click', nbibButtonClick);
    }

    start();
})();