NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Sankaku Recommendations loader // @name:ru Sankaku Recommendations loader // @description Loads next page of recommendations to current one without removing the last // @description:ru Загружает очередную страницу рекомендаций в текущую без удаления последней // @namespace https://openuserjs.org/users/Se7en // @include *://chan.sankakucomplex.com/* // @include *://idol.sankakucomplex.com/* // @author Se7en // @version 1.0.3 // @grant GM_xmlhttpRequest // ==/UserScript== /* What does it do: + loads next page of recommendations to current page without removing the last one + loads pack of pages - by default 5 pages are loaded + removes adverts + removes share buttons ***************************** Что делает: + Загружает очередную страницу рекомендаций в текущую без удаления последней. + Загружает сразу несколько страниц - по умолчанию 5 шт. + Удаляет рекламу + Удаляет кнопку шары */ (function(){ var clog = function(){}; //clog = console.log; var href = window.location.href, isPost = href.indexOf('post') != -1; removeAdverts(); removeShare(); if( !isPost ) return; var recommend = initRecommend(5), pageData = initPageData(); //loadNextPack(); newCssClasses(); function initRecommend( n ) { var ret = { page: 1,// current recommendation page pack: n,// number of pages in one pack packN: 0, pageEnd: -1, }; return ret; } function initPageData( d ) { var ret = { data: { recommend: { val: null, init: function( doc ){ this.doc = doc || document; this.val = this.doc.querySelector('#recommendations'); }, fix: function(){ var recs = this.val.querySelectorAll('#recommendations'); [].forEach.call( recs, function(item){ try{ item.outerHTML = item.innerHTML; }catch(e){} }); // remove extra paginators var pags = this.val.querySelectorAll('#recommendations-paginator'); [].forEach.call( pags, function(item, i, arr){ if( i != (arr.length - 1) ){ remove(item); } }); }, add: function(s){ this.val.innerHTML += s; } }, paginator: { val: null, init: function( doc ){ this.doc = doc || document; this.val = last( this.doc.querySelectorAll('#recommendations-paginator') ); }, fix: function(){ var prv = this.get('prev'), nxt = this.get('next'), pck = this.get('pack'); prv.innerHTML = '<<'; nxt.innerHTML = '>>'; if( !nxt.classList.contains('sce-recommended-next') ){ prv.classList.add('sce-recommended-prev'); nxt.classList.add('sce-recommended-next'); nxt.addEventListener('click', loadNextRecommendedPage, false ); } if( !pck ){ pck = this.doc.createElement('span'); pck.setAttribute('class', 'sce-recommended-pack recommended-pack'); pck = this.val.appendChild( pck ); pck.innerHTML = '' + '(' + (recommend.page+1) + '-' + (recommend.page+recommend.pack+1) + ')'; pck.addEventListener('click', loadNextRecommendedPack, false ); } }, get: function( dir ){ return this.val.querySelector('.recommended-' + dir ); }, }, postID: { val: null, init: function( doc ){ this.doc = doc || document; this.val = getPostID(this.doc); clog("postID: " + this.val); } }, }, get postID(){ return this.data.postID.val; }, get: function( prop ) { if( this.data[prop] ) return this.data[prop]; }, init: function( prop, doc ){ if( this.data[prop] ) this.data[prop].init( doc ); }, fix: function( prop ){ if( this.data[prop] ) this.data[prop].fix(); }, fixAll: function(){ this.data.recommend.fix(); this.data.paginator.fix(); }, initAll: function( doc ){ for( var key in this.data ) this.data[key].init( doc ); }, }; ret.initAll(d); ret.fixAll(); return ret; } function getPostID( doc ) { doc = doc || document; try{ return doc.querySelector('#hidden_post_id').innerHTML; }catch(e){ return doc.querySelector('meta[content^="Post"]').getAttribute('content').replace('Post ', ''); } } function recommendURL( page ) { return '/post/recommend/' + pageData.postID + '?page=' + page; } function loadNextPack() { // load next ${recommend.pack} pages of recommendations pageData.get('paginator').get('pack').click(); } function loadNextRecommendedPage( event ) { if( recommend.pageEnd > 0 ) return; recommend.packN = 0; GM_xmlhttpRequest({ url: recommendURL( ++recommend.page ), method: 'GET', onload: addRecommended, }); } function loadNextRecommendedPack( event ) { if( recommend.pageEnd > 0 ) return; var recURL = recommendURL(''); recommend.packN = 1; for( var i = 0; i < recommend.pack; ++i ) { GM_xmlhttpRequest({ url: recURL + (++recommend.page), method: 'GET', onload: addRecommended, }); } } function addRecommended( xhr ) { var pageN = this.url.match(/\?page\=(\d+)/)[1], respLen = xhr.response.length; if( respLen > 0 ){ pageData.get('recommend').add( xhr.response ); pageData.fix('recommend'); }else if( recommend.pageEnd < 0 ) recommend.pageEnd = pageN; else recommend.pageEnd = Math.min( recommend.pageEnd, pageN ); if( recommend.packN === 0 || recommend.packN == recommend.pack ) { pageData.init('paginator'); pageData.fix('paginator'); if( recommend.pageEnd > 0 ){ pageData.get('paginator').get('pack').innerHTML = '(' + recommend.pageEnd + ')'; pageData.get('paginator').get('next').innerHTML = 'End'; } }else ++recommend.packN; } function addCssClass( cssClass ) { var head = document.querySelector('head'), style = document.createElement('style'); style.type = 'text/css'; if( style.styleSheets ) style.styleSheets.cssText = cssClass; else style.appendChild(document.createTextNode(cssClass)); head.appendChild(style); } function newCssClasses() { addCssClass(` #recommendations-paginator > span.recommended-prev { margin-left: 30%; } #recommendations-paginator > span.sce-recommended-next, #recommendations-paginator > span.sce-recommended-pack { color: #ff761c; font-weight: bold; cursor: pointer; } #recommendations-paginator > span.recommended-pack { font-size: 2.5em; float: left; margin: 0.1em 0.25em 0.1em 1%; padding: 2px 6px; border: 1px solid rgb(234, 234, 234); } `); } function removeAdverts() { var timerID = setInterval( removeAds, 500 ); function removeAds(){ this.count = this.count || 0; var scads = document.getElementsByClassName('scad'), i; for( i = 0; i < scads.length; ++i ) remove( scads[i] ); scads = document.querySelectorAll('[class*="scad"]'); for( i = 0; i < scads.length; ++i ) remove( scads[i] ); var iframes = document.getElementsByTagName('iframe'); for( i = 0; i < iframes.length; ++i ) remove( iframes[i] ); ++this.count; clog("> removeAds: ", this.count); if( this.count > 10 && isPost ) clearInterval( timerID ); else if( this.count > 600 ) clearInterval( timerID ); } } function removeShare() { var share = document.getElementById('share'); if( share ) share.innerHTML = ''; } function remove( elm ){ return elm.parentNode.removeChild( elm ); } function last( arr ){ return arr[arr.length - 1]; } })();