// ==UserScript==
// @id heise.de-8280af0b-4f9b-487e-95b3-45fff377348e
// @name heise.de Easy Reading
// @name:de heise.de Easy Reading
// @version 1.5.2
// @author SpineEyE
// @description Makes reading heise news a little more comfortable
// @description:de Macht heise lesen etwas angenehmer
// @include /https?:\/\/www\.heise\.de/.*$/
// @run-at document-idle
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// @namespace
// @downloadURL none
// ==/UserScript==
// heise.de Easy Reading user script
// Copyright 2011-2017, SpineEyE
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html
//
// -----------------------------------------------------------------------------
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
tags is readable in whole width // v1.1.1 - 16.11.2013: fixed h2-link-construction // (function () { // function wrapper for Opera /* Better for our eyes */ if (document.getElementsByClassName('meldung_wrapper').length > 0) { GM_addStyle( '.easy-reading-serif {'+ 'font-family: Georgia,"Times New Roman",serif;' + 'line-height: 155%;' + //'padding: 0.5em 0;' + //'font-size: 1em !important;' + //'letter-spacing: 0.2px;' + '}' + '#mitte_news ul {' + 'font-size: 1em !important;' + '}'+ /* remove top margin */ '#bannerzone {' + 'display:none'+ '}'+ '#container_content {' + 'margin-top: -95px;'+ '}'+ /* fix to make text intags visible over the whole width */ 'pre {' + 'position: relative;' + 'z-index: 1;' + 'background-color: #FFFFFF;' + '}' + 'pre:hover {' + 'display: table-caption;' + 'margin-top: 0' + '}' ); } /* prevent image popups, rather insert normal hyperlink bild_links, bild_rechts **/ var inlineImages = document.evaluate('//span[starts-with(@class,"bild_")]', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null), i, span, img, a, bigImageURL; for(i = 0; i < inlineImages.snapshotLength; i++) { //console.log("Snapshot item " + i); span = inlineImages.snapshotItem(i); img = span.children[0]; a = document.createElement('a'); bigImageURL = img.getAttribute('data-zoom-src'); if (!bigImageURL) continue; a.href = bigImageURL; // cloning a node removes all event listeners, so the popup as well a.appendChild(img.cloneNode(false)); span.insertBefore(a, img); span.removeChild(img); } /* link to full size picture for aufmacherbild */ var imgAufmacher, aAufmacher; if (document.getElementsByClassName("aufmacherbild")[0]) { aAufmacher = document.getElementsByClassName("aufmacherbild")[0].children[0]; imgAufmacher = aAufmacher.children[0]; } if (imgAufmacher) { a = document.createElement('a'); // class for the zoom overlay image in the bottom right corner a.setAttribute('class', 'image_zoom'); // console.log(imgAufmacher.src.replace(/\/scale.*?\/imgs\//i, "/imgs/")); a.href = imgAufmacher.src.replace(/\/scale.*?\/imgs\//i, "/imgs/"); // cloning a node removes all event listeners, so the popup as well a.appendChild(imgAufmacher.cloneNode(false)); document.getElementsByClassName("aufmacherbild")[0].insertBefore(a, aAufmacher); document.getElementsByClassName("aufmacherbild")[0].removeChild(aAufmacher); } /* gallery fix: enable back button on advertisement slide */ if (document.querySelector(".gallery")) { a = document.createElement("a"); a.setAttribute("data-slide", "prev"); a.setAttribute("class", "gallery-control slide slide-prev greasy-added"); a.innerHTML = ''; // we need two of this, make deep copy var b = a.cloneNode(true); /* Several reasons why this runs as an interval: * 1) I have found no way to hook into the event emitter * 2) Every time changing tabs and returning to the page removes the button * 3) Every time this back button is pressed, it's removed * We could probably use the MutationObserver ... Maybe I'll look into it * to see if it's lower on resources */ var galleryGuard = window.setInterval(function(){ if (document.querySelector('.image-num').innerHTML.indexOf("Zurück zum Start") !== -1 && document.querySelectorAll('.greasy-added').length != 2) { // modal window / fullscreen mode? // probably better to add the button to both views //if (document.querySelector(".gallery .heise-modal").style.display != "none") { document.querySelector(".image-stage").appendChild(a); //} //else { document.querySelector(".gallery-inner").appendChild(b); //} } }, 200); } /* Thread-Anzeige einblenden im Forum */ if (document.querySelector('.thread_view_switch a') && document.querySelector('.thread_view_switch a').textContent == "Thread-Anzeige einblenden") { document.querySelector('.thread_view_switch a').click(); } /* Serif checkbox */ function makeSerif(serifIfTrue) { var articleTextElements = document.querySelectorAll('.meldung_wrapper, .meldung_wrapper p, .meldung_wrapper h5, .artikel_content article p'); var i = 0; for (i = 0; i < articleTextElements.length; i++) { if (serifIfTrue) { articleTextElements[i].classList.add("easy-reading-serif"); } else { articleTextElements[i].classList.remove("easy-reading-serif"); } } } function serifCheckboxHandler(){ var checkbox = document.getElementById('useSerifFont'); // this is already the new value var newValue = checkbox.checked; makeSerif(newValue); console.log("setting to " + newValue); GM_setValue( "serifFont", newValue); console.log("After checkbox: " + GM_getValue( "serifFont", false )); } var articleNode = document.querySelector("article"); if (articleNode) { var label = document.createElement('label'); var serifToggleLabel = document.createTextNode("Serifen-Schrift"); var checkbox = document.createElement('input'); checkbox.setAttribute('type', 'checkbox'); checkbox.setAttribute('id', 'useSerifFont'); label.appendChild(checkbox); label.appendChild(serifToggleLabel); var userSetting = GM_getValue( "serifFont", "init" ); if (userSetting == "init") { GM_setValue( "serifFont", true ); userSetting = true; } checkbox.checked = userSetting; makeSerif(userSetting); checkbox.addEventListener('click', serifCheckboxHandler); articleNode.appendChild(label); } var pagination = document.querySelector('.seitenweise_navigation.paginiert'); if (pagination) { var promises = []; var nextPage = document.querySelector('.pagination b').nextElementSibling; while (nextPage && nextPage.tagName.toLowerCase() === 'a') { promises.push(appendPage(nextPage.getAttribute('href'), nextPage.innerHTML)); nextPage = nextPage.nextElementSibling; } Promise.all(promises) .then(function() { pagination.remove(); }); } function appendPage(url, pageNum) { return new Promise(function(resolve, reject) { console.log("Exe promise"); var loadNotify = document.createElement('div'); loadNotify.innerHTML = "Lade Seite " + pageNum + "..."; articleNode.insertBefore(loadNotify, articleNode.querySelector('.article-footer')); console.log("Loading now..."); GM_xmlhttpRequest({ method: 'GET', url: url, onload: function(response) { console.log("Got response"); var meldung = document.querySelector('.meldung_wrapper'); responseDoc = document.createElement('html'); responseDoc.innerHTML = response.responseText; var meldung_new = responseDoc.querySelector('.meldung_wrapper'); // find chaoter title chapter_title = responseDoc.querySelector('.article__chapter'); if (chapter_title) { chapter_title.className = "subheading"; meldung.appendChild(chapter_title); } // remove ToC meldung_new.removeChild(meldung_new.querySelector('.pre-akwa-toc')); // append to article meldung.insertAdjacentHTML('beforeend', meldung_new.innerHTML); articleNode.removeChild(loadNotify); resolve(); }, onerror: function(response) { loadNotify.innerHTML = "Laden von Seite " + pageNum + " fehlgeschlagen(" + response.statusText + "): " + response.responseText; reject("Seite " + pageNum + " nicht geladen"); } }); }); } })(); // function wrapper for Opera