您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
MyDealz Enstyler Frontend and enhanced features
当前为
// ==UserScript== // @name EnstylerJS // @namespace Enstyler // @description MyDealz Enstyler Frontend and enhanced features // @include http://www.mydealz.de/* // @include https://www.mydealz.de/* // @version 2.11.057 // @grant GM_getValue // @grant GM_setValue // @grant GM_log // @grant GM_xmlhttpRequest // @require http://code.jquery.com/jquery-3.1.1.min.js // @require http://cdnjs.cloudflare.com/ajax/libs/jquery-throttle-debounce/1.1/jquery.ba-throttle-debounce.min.js // @require http://openuserjs.org/src/libs/sizzle/GM_config.js // ==/UserScript== // ========== RUN EnstylerJS ===================================== // create object for enstyler "Menu Button" function EnstylerInit () { // hide Enstyler2 CSS (c) text because we have a button now addStyleString('.threadWidget-footer::after {display: none !important};'); EnstylerButtonCreate(); // basic config panel formatting, everything else is formatted by enstyler var enCSS = ['#GM_config {left: 5% !iportant; top: 9% !important; height: auto !important; max-width: 35em !important;}', '#GM_config input, #GM_config button { border: 1px solid; margin: 0.5em 0em 0.2em 1em; padding: 0.1em;}', '#GM_config .reset { font-size: 9pt; padding-right: 1em; }', ].join(" "); addStyleString(enCSS); } function EnstylerStart () { // ============ stuff to modify page content ============================= // REGEX to detect external URL var REGEX_THREAD = /^https?:\/\/www\.mydealz\.de\/visit\/thread(image)?\/\d+$/; var REGEX_DESC = /^https?:\/\/www\.mydealz\.de\/visit\/threaddesc\/\d+\/\d+$/; var REGEX_COMMENT = /^https?:\/\/www\.mydealz\.de\/visit\/comment\/\d+\/\d+$/; var REGEX_AMAZONMOB = /^https?:\/\/www\.amazon\..*\/gp\/aw\/.*$/; //var REGEX_AMAZON = /^https?:\/\/www\.amazon\..*$/; //* GM_xmlhhtpREquest not supported by firefox mobile :-((( // abfangen aller links mit jQuery $('a').bind('click', function(){ var url = this.href; // externer Link mit Redirect ... // Match REDIRECT URLs and open new Window with finalUrl if (GM_config.get('enConfFilterLink') && url.match(REGEX_THREAD) || url.match(REGEX_DESC) || url.match(REGEX_COMMENT)) { // Workaround: pre open window because of popup blockers var asyncWindow = window.open(url, '_blank'); // now lookup redirecd external URL ... // alert("external URL detected"); GM_xmlhttpRequest({ method: 'GET', url: url, // here we get the final URL from redirect onload: function (response) { // process final URL var newUrl = response.finalUrl; //alert(newUrl); // lets see ... if (newUrl.match(REGEX_AMAZONMOB)) { newUrl = newUrl.replace("/gp/aw/d/", "/dp/"); newUrl = newUrl.replace("/gp/aw/ol/", "/gp/offer-listing/"); //alert("Amazon rewritten URL: " + newUrl); } // load processed URL in preopened window asyncWindow.location = newUrl; } }); // return without link processing by Browser return false; } // return with link processing in Browser return true; }); // - END GM_xmlhttpRequest */ } // END EnstylerStart // add actions to tread overview @ some places ================================== function EnstylerDealActions() { // if logged in ... if ($('.avatar--type-nav').length) { // code used for MyDealz Dealz actions, thanks to mydealz :-) var myOuterHtml = [ '<span class="js-options bg--em bRad--a space--h-3 space--v-3 space--mt-3 text--b">', '</span>']; var enDealAction = [ '<a class="link ico ico--pos-l ico--type-comment-blue space--mr-3"', // comment 0+1 'href="<ENSTYLER-HREF-HERE>#comment-form" data-handler="track" data-track="{"action":"scroll_to_comment_add_form","label":"engagement"}">Sag was dazu</a>', '<a class="link text--color-blue ico ico--type-bookmark-blue ico--pos-l space--mr-3"', //un-bookmark 2+3 'data-handler="track replace" data-replace="{"endpoint":"https:\/\/www.mydealz.de\/threads\/<ENSTYLER-THREADID-HERE>/remove","method":"post"}" data-track="{"action":"save_thread","label":"engagement"}"> Von Liste entfernen</a>', '<a class="link text--color-blue ico ico--type-pencil-blue ico--pos-l space--mr-3"', // edit 4+5 'href="<ENSTYLER-HREF-HERE>/edit" data-handler="track" data-track="{"action":"goto_thread_edit_form","beacon":true}">Bearbeiten</a>', '<a class="thread-expire link ico ico--type-clock-blue ico--pos-l space--mr-3"', // expiried not working :-( 'href="<ENSTYLER-HREF-HERE>/expire/report" rel="nofollow" data-handler="track replace" data-track="{"action":"report_expired_thread","label":"contribution"}" data-replace="{"endpoint":"https:\/\/www.mydealz.de\/<ENSTYLER-HREF-HERE>/expire\/report"}">Abgelaufen?</a>', ]; var PATTERN = [ /<ENSTYLER-HREF-HERE>/g, // pattern to replace by deal link ... /<ENSTYLER-THREADID-HERE>/g, // pattern to replace ID ] if (GM_config.get('enConfMoreDeal')) { var parser = location; // parse location var pathname = parser.pathname; var username = pathname.replace(/.*profile\//,''); username = username.replace(/\/.*/,''); // no username ?? if (username == "") { username = "unknown"; } else { pathname = pathname.replace(username + '/',''); // remove username if path is longer } //alert("username:" + username + " pfadname:" +pathname) // default for all Dealz: comment var myAction = enDealAction[0]+ enDealAction[1]; // Action for special locations only ==================== // saved Dealz panel if (pathname.endsWith('profile/saved-deals') ){ // add for user saved-dealz: un-bookmark myAction += enDealAction[2]+ enDealAction[3]; } if (pathname.endsWith('profile/diskussion') || pathname.endsWith(username)){ // add user dealz and discussions: comment edit myAction += enDealAction[4]+ enDealAction[5]; } // we have an Action to add to an Deal! if (myAction != "") { //GM_log('Action:' + myAction); // every thread on page ... $('article').each(function () { // get ThreadID, Link to Deal and DealID var myThread = $(this).attr('id'); var myDealHref = $('#' + myThread + ' .thread-title a').attr('href'); var myDealID = myThread.replace('thread_','') // compose final HTML var newHtml= myOuterHtml[0] + myAction + myOuterHtml[1]; newHtml = newHtml.replace(PATTERN[0], myDealHref); newHtml = newHtml.replace(PATTERN[1], myDealID); // append HTML to Deal $('#' + myThread +' .thread-infoRow').each(function () { $(this).append(newHtml); $(this).removeClass('thread-infoRow'); }); }); } // actions for everywhere ============== // remove unwanted HTML from deal description $('.thread--type-detail .userHtml').each(function () { // userhtml code from mydalz, need to find jafascript to save automatically :-( var enUserhtml = ['<div class="userHtml overflow--wrap-break space--t-3" data-handler="lightbox-xhr" data-lightbox-xhr="{"name":"threads"}">', '</div>', // sourround deal description ]; // get inner html var myHtml = $(this).html(); // remove unwanted Stuff: combined <div><br><br> stuff, created by cut'npaste html // not elegant, but works ... var newHtml = myHtml.replace(/<div>|<div><br>|<\/br>|<\/div>/gi,''); newHtml = newHtml.replace(/<br><br><br>|<br><br><br><br>|<br><br><br><br><br>/gi,'<br><br>'); // replace original with modifyed html $(this).replaceWith(enUserhtml[0] + newHtml + enUserhtml[1]); }); } // END enabled } } // show popup user info while click on avatar ... ============== function EnstylerAvatarPopup() { // if logged in ... if ($('.avatar--type-nav').length) { // code used for MyDealz avatar popup, thanks to mydealz :-) var enPopupUser = ['<button data-handler="track popover" data-track="{"action":"show_short_user_profile","label":"engagement"}"data-popover="{"endpoint":"', '/short","target":"#template-popoverLoader","layout":[{"preset":"e","y":"50%","left":{"offset":0},"width":300,"maxWidth":"100%"}]}">', '</button>', ]; // remove second image from cardview if (GM_config.get('enConfUser')) { addStyleString('.thread-footer-cell a img.avatar.vAlign--all-m.space--mr-1.thread-avatar {display: none;}'); } // replace every avatar link without popup if (GM_config.get('enConfUser')) { $('.thread-footer-cell a.user.linkPlain, .user.linkPlain.thread-user').each(function () { var Iam = $(this); // get inner html and link to user profile var myHtml = Iam.html(); var mysrc = Iam.attr('href'); // seperate user name from image and add class user var myAvatar1 = myHtml.replace(/<span.*/,''); var myAvatar2 = myHtml.replace(/.*<span class=".* space--mr-1">/,'<span class=" space--mr-1 user link-plain">'); // show small / medium sized Avatar myAvatar1 = myAvatar1.replace('avatar--type-s','avatar--type-m'); //in Dealz if (GM_config.get('enConfAvatar')) { myAvatar1 = myAvatar1.replace('thread-avatar','avatar--type-m'); } // compose popup var myPopup = enPopupUser[0] + Iam.attr('href') + enPopupUser[1] + myAvatar1 + enPopupUser[2] + '<a href="' + Iam.attr('href') + '">'+ myAvatar2 + '</a>'; Iam.replaceWith(myPopup); }); } } } // create button for display Config var EnstylerButton = 'EnstylerButton'; //var input = document.createElement('a'); // input.setAttribute('href', 'showEnstylerConfig()'); // input.setAttribute('id', EnstylerButton); var input = document.createElement('input'); input.type = 'button'; input.value = 'Enstyler'; input.setAttribute('id', EnstylerButton) input.onclick = showEnstylerConfig; function EnstylerButtonCreate() { // add Enstyler Button to ... var myElement; if (GM_config.get('enConfBtn') && $(window).width() > GM_config.get('enConfBtnMinWidth')) { // add button to MainNav var Elements = document.getElementsByClassName("nav-link"); myElement = Elements[3]; input.setAttribute('class', 'nvAlign--all-m nav-link-text'); } else { // add button to SubNav myElement = document.getElementById('tour-filter'); input.setAttribute('class', 'box--all-i subNavMenu-link'); input.setAttribute('style', 'font-size: 1.28571em; font-weight: 700; top: 3px; left: -0.7em'); } // only if myElement exist if (myElement !== null) { myElement.appendChild(input); //insertAfter(input, myElement); } } function EnstylerButtonRemove() { // Removes an element from the document var element = document.getElementById(EnstylerButton); element.parentNode.removeChild(element); } // ============= GM_config functions ======================================= // define GM_config elements var fieldDefs = { // Part one: load external content -------- 'enstyler': { 'section': ['additonal features for Enstyler', ''], 'label': 'Install / Update CSS...', // Appears on the button 'type': 'button', // Makes this setting a button input 'click': function() { // Function to call when button is clicked showUrl('https://userstyles.org/styles/128262#style-info'); } }, 'dontCookies': { 'label': 'Mozilla no cookies...', // Appears on the button 'type': 'button', // Makes this setting a button input 'click': function() { // Function to call when button is clicked showUrl('https://addons.mozilla.org/de/addon/i-dont-care-about-cookies/'); } }, //* thhis has to be the last one,display only if internal version is disabled 'externalMobileRedirect': { 'label': 'Amazon mobile redirect...', // Appears on the button 'type': 'button', // Makes this setting a button input 'click': function() { // Function to call when button is clicked showUrl('https://greasyfork.org/de/scripts/19700'); } }, // */ // part two: EnstylerJS internal configuration options ------ 'hidden1': { // display next section, dont kow why ... 'section': ['Configuration', ''], 'type': 'hidden', // Makes this setting a hidden input 'value': 'Some hidden value' // Value stored }, // postion of enstyler "button" 'enConfBtn': { 'label': 'Show Enstyler in MainNav', // Appears next to field 'type': 'checkbox', // Makes this setting a checkbox input 'default': false // Default value if user doesn't change it }, 'enConfBtnMinWidth': { 'label': 'only if width is bigger than ', // Appears next to field 'type': 'int', // Makes this setting a text input 'min': 600, // Optional lower range limit 'max': 1200, // Optional upper range limit 'size': 4, // Limit length of input (default is 25) 'default': 850 // Default value if user doesn't change it }, // ehanced USerInfo 'enConfUser': { 'label': 'Show Popuop Userinfo', // Appears next to field 'type': 'checkbox', // Makes this setting a checkbox input 'default': true // Default value if user doesn't change it }, 'enConfAvatar': { 'label': 'bigger Avatar for Popuop', // Appears next to field 'type': 'checkbox', // Makes this setting a checkbox input 'default': true // Default value if user doesn't change it }, // enable filtering of external links 'enConfFilterLink': { 'label': 'Amazon mobile redirect', // Appears next to field 'type': 'checkbox', // Makes this setting a checkbox input 'default': true // Default value if user doesn't change it }, // */ // more Deal actions 'enConfMoreDeal': { 'label': 'additional Deal actions', // Appears next to field 'type': 'checkbox', // Makes this setting a checkbox input 'default': true // Default value if user doesn't change it }, // display copy message at end of section ... 'copy': { 'section': ['', '(c) Gnadelwartz - <a target="blank" href="https://www.mydealz.de/diskussion/enstyler2-style-your-mydealz-incl-pepper-sites-736219">Enstyler2 - Style your MyDealz</a>'], 'type': 'hidden', // Makes this setting a hidden input 'value': 'Some hidden value' // Value stored }, }; // display GM_copnfig as div, so we cam apply CSS!! var enGMOptChange = false; var enGMFrame = document.createElement('div'); document.body.appendChild(enGMFrame); GM_config.init( { id: 'GM_config', title: 'EnstylerJS - Settings', fields: fieldDefs, 'events': // Callback functions object { //'init': function() { alert('onInit()'); }, // do not diplay external mobile redirect is internal is activated 'open': function() { if (GM_config.get('enConfFilterLink')) { GM_config.fields['externalMobileRedirect'].remove(); } if (!GM_config.get('enConfBtn')) { GM_config.fields['enConfBtnMinWidth'].remove(); } if (!GM_config.get('enConfUser')) { GM_config.fields['enConfAvatar'].remove(); } }, //'reset': function() { enGMOptChange = true; }, // relaod page on close after save 'save': function() { //enGMOptChange = true; if (GM_config.get('enConfFilterLink')) { GM_config.fields['externalMobileRedirect'].remove(); } EnstylerButtonRemove(); EnstylerButtonCreate(); }, //'close': function() { if (enGMOptChange) { location.reload(); enGMOptChange = false;} }, }, 'frame': enGMFrame // Element used for the panel } ); // EnstylerJS Config Panel anzeigen function showEnstylerConfig() { GM_config.open(); } //=========== Support functions for actual use ======= // display website in external window function showUrl(str) { var myDeco = "innerheight=800,innerwidth=600"; var myName = "enstyler"; // workaround for not working window.focus(): close an existing window first var myWindowShow = window.open('', myName, "width=100,height=100").close(); myWindowShow = window.open(str, myName, myDeco); } // add CSS in to document function addStyleString(str) { var node = document.createElement('style'); node.innerHTML = str; document.body.appendChild(node); } // sleep time expects milliseconds, then execute code // NOTE: code runs in parallel (asnyc)! // Usage! // sleepAsync(500).then(() => { // Do something after the sleep! // }); function sleepAsync (time) { return new Promise((resolve) => setTimeout(resolve, time)); } // like .insertBefore but as function function insertAfter(newNode, referenceNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } // ============== START EnstyerJS ============= EnstylerInit(); EnstylerStart(); EnstylerAvatarPopup(); EnstylerDealActions(); // track DOM change Events, debounce: wait 500ms after mutiple events // then re-apply (somse) changes to dynamic loaded content, $('.fGrid-last2, .thread-list--type-card').bind("DOMSubtreeModified",$.debounce( 500, function(){ //GM_log('DOMSubtreeModified detected!!!'); EnstylerDealActions(); EnstylerAvatarPopup(); }));