|
/gi,'
');
newHtml = newHtml.replace(/
|
|
/gi,'
');
// replace original with modifyed html
$(this).replaceWith(enUserhtml[0] + newHtml + enUserhtml[1]);
});
} // END enabled
}
}
// show popup user info while click on avatar ... ======================
function EnstylerAvatarPopup() {
// login needed ... (Error in Popup without login ...)
if (enUserLogin) {
// code used for MyDealz avatar popup, thanks to mydealz :-)
var enPopupUser = ['',
];
// 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(/
.*/gi,'');
//alert(myResponse);
if (versionCompare(enEnVersion, myResponse) <0) {
//showPopup('New CSS availible: ' + enEnVersion + '\n\nPlease update!');
} else { myResponse='no'; }
GM_config.setValue('enEnVersion', myResponse);
enUpdateChecked=true;
}
});
}
// 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.setAttribute('id', EnstylerButton)
input.onclick = showEnstylerConfig;
function EnstylerButtonCreate() {
// add Enstyler Button to ...
var myElement;
var myMain=false;
input.value = 'Enstyler';
EnstylerButtonRemove();
// MainNav selected or Deal
if (GM_config.get('enConfBtn'))
{ myMain=true; }
if ($('.voteBar').length)
{ myMain=true; }
// only if space left
if ($(window).width() < GM_config.get('enConfBtnMinWidth'))
{ myMain=false; }
if (myMain) {
// add button to MainNav
var Elements = document.getElementsByClassName("nav-link");
myElement = Elements[3];
input.setAttribute('class', 'vAlign--all-m nav-link-text');
input.setAttribute('style', '');
} 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);
}
}
// needed for Enstyler Homepage
function EnstylerHomeButton() {
// add Enstyler Button to ...
input.value = 'Options';
var myElement = document.getElementById('style-settings');
input.setAttribute('style', 'font-size: 1.28571em; padding: 0.8em;');
// only if myElement exist
if (myElement !== null) {
//myElement.appendChild(input);
insertAfter(input, myElement);
}
}
function EnstylerButtonRemove() {
// Removes button from the document
$('#'+ EnstylerButton).remove
}
// ============= GM_config functions =======================================
// define EnstylerJS GM_config elements
var enJSfieldDefs = {
// Part one: load external content --------
'enstyler': {
'section': ['additonal features for Enstyler', ''],
'label': 'Update CSS...', // Appears on the button
'type': 'button', // Makes this setting a button input
'click': function() { // Function to call when button is clicked
GM_config.setValue('enEnVersion', 'no');
GM_config.save();
GM_config.open();
showUrl('https://userstyles.org/styles/128262#style-info');
}
},
'enstylerJS': {
'label': 'Update UserScript...', // Appears on the button
'type': 'button', // Makes this setting a button input
'click': function() { // Function to call when button is clicked
GM_config.setValue('enJSVersion', 'no');
GM_config.save();
GM_config.open();
showUrl('https://greasyfork.org/de/scripts/24243');
}
},
'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
},
'enConfNavFixed': {
'label': 'Display FIXED MainNav', // Appears next to field
'type': 'checkbox', // Makes this setting a checkbox input
'default': false // 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
},
// Page picker
'enConfPagePicker': {
'label': 'Enable Page Picker', // Appears next to field
'type': 'checkbox', // Makes this setting a checkbox input
'default': false // Default value if user doesn't change it
},
// check for Updates
'enConfCheckEnUpdate': {
'label': 'Check for Updates', // Appears next to field
'type': 'checkbox', // Makes this setting a checkbox input
'default': true // Default value if user doesn't change it
},
'enLastUpdateCheck': {
'type': 'hidden', // Makes this setting a text input
'default': '0' // Default value if user doesn't change it
},
'enJSVersion': {
'type': 'hidden', // Makes this setting a text input
'value': 'no' // Value stored
},
'enEnVersion': {
'type': 'hidden', // Makes this setting a text input
'value': 'no' // Value stored
},
// Black/Whitelist input
'enConfBlackEnable': {
'label': 'Enable Black- / Whitelist', // Appears next to field
'type': 'checkbox', // Makes this setting a checkbox input
'default': true // Default value if user doesn't change it
},
'enConfHideColder': {
'label': 'Blacklist if colder then', // Appears next to field
'type': 'int', // Makes this setting a text input
'min': -9999, // Optional lower range limit
'max': -9, // Optional upper range limit
'size': 4, // Limit length of input (default is 25)
'default': -999 // Default value if user doesn't change it
},
'enConfBlacklist': {
'label': 'Blacklist - deals, categories, @users', // Appears next to field
'type': 'text', // Makes this setting a text input
'size': 70, // Limit length of input (default is 25)
'default': 'Nutella, Bangood, @Admin' // Default value if user doesn't change it
},
'enConfWhitelist': {
'label': 'Whitelist', // Appears next to field
'type': 'text', // Makes this setting a text input
'size': 70, // Limit length of input (default is 25)
'default': '' // Default value if user doesn't change it
},
'enConfUnblacklist': {
'label': 'UnBlacklist', // Appears on the button
'type': 'button', // Makes this setting a button input
'click': function() { // Function to call when button is clicked
EnstylerBlacklistRemove(); }
},
// display copy message at end of section ...
'copy': {
'section': ['', '(c) Gnadelwartz - Enstyler2 - Style your MyDealz'],
'type': 'hidden', // Makes this setting a hidden input
'value': 'Some hidden value' // Value stored
},
};
// define EnstylerJS GM_config elements
var enHomefieldDefs = {
// Part one: load external content --------
'saveOpt': {
'section': ['save your CSS options for next visit', ''],
'label': 'Select your CSS on main page then come back and klick "Save" ', // Appears near textarea
'type': 'textarea', // Makes this setting a button input
'size': 70,
//'click': function() { // Function to call when button is clicked
// showUrl('https://userstyles.org/styles/128262#style-info'); }
},
// display copy message at end of section ...
'copy': {
'section': ['', '(c) Gnadelwartz - Enstyler2 - Style your MyDealz'],
'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');
enGMFrame.setAttribute('class','GM_config');
document.body.appendChild(enGMFrame);
// 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, .GM_config textarea { border: 1px solid; margin: 0.5em 0em 0.2em 1em; padding: 0.1em;}',
'.GM_config .reset { font-size: 9pt; padding-right: 1em; }',
'#GM_config_enstyler_var:after {content: ". <- please install CSS!"; font-weight: bold;}',
'.enClassHidden {display: none;}',
].join(" ");
addStyleString(enCSS);
var En_Popup = new GM_configStruct(
{
'id': 'EnPopup', // You need to use a different id for each instance
'title': 'EnstylerJS - Info',
'fields': // Fields object
{
'Text': // This is the id of the field
{
'label': '', // Appears next to field
'type': 'textarea', // Makes this setting a text field
'default': '' // Default value if user doesn't change it
}
},
'events':
{
'open': function (doc) {
// translate the buttons
var config = this;
doc.getElementById(config.id + '_saveBtn').textContent = ' OK ';
//doc.getElementById(config.id + '_closeBtn').textContent = 'Cancel';
doc.getElementById(config.id + '_resetLink').textContent = '';
},
},
'frame': enGMFrame // Element used for the panel
}
);
function showPopup(text) {
En_Popup.fields['Text'].value = text;
En_Popup.fields['Text'].reload();
En_Popup.open();
}
var enGMConfigOpen=false;
// EnstylerJS Config Panel anzeigen
function showEnstylerConfig() {
if(!enGMConfigOpen) {
enGetHome();
GM_config.open();
enGMConfigOpen=true;
} else {
GM_config.close();
}
}
// EnstylerJS START ========================
if (!window.location.hostname.endsWith('userstyles.org')) {
var enFixedNav=false;
GM_config.init(
{
id: 'GM_config',
title: 'EnstylerJS - Settings',
fields: enJSfieldDefs,
'events': // Callback functions object
{
//'init': function() { alert('onInit()'); },
// remove elements ich switch is checked or not
'open': function() {
var enRemoveConfig = [
{ check: true, switch: 'enConfFilterLink', remove: 'externalMobileRedirect'},
{ check: false, switch: 'enConfBtn', remove: 'enConfBtnMinWidth'},
{ check: false, switch: 'enConfUser', remove: 'enConfAvatar'},
{ check: false, switch: 'enConfBlackEnable', remove: 'enConfWhitelist'},
{ check: false, switch: 'enConfBlackEnable', remove: 'enConfBlacklist'},
{ check: false, switch: 'enConfBlackEnable', remove: 'enConfHideColder'},
{ check: false, switch: 'enConfBlackEnable', remove: 'enConfUnblacklist'}
];
enFixedNav=GM_config.get('enConfNavFixed');
// remove unneeded controls
$(enRemoveConfig).each(function() {
if (GM_config.get(this.switch) == this.check) {
GM_config.fields[this.remove].remove();
}
});
// remove / display update dialog
if (GM_config.get('enConfCheckEnUpdate')&& enUpdateChecked) {
var myUpdate
if ((myUpdate=GM_config.getValue('enJSVersion')) =='no')
{GM_config.fields['enstylerJS'].remove();}
else {showPopup('New EnstylerJS availible: ' + myUpdate + '\n\nPlease update!');}
if ((myUpdate=GM_config.getValue('enEnVersion')) =='no')
{GM_config.fields['enstyler'].remove();}
else {showPopup('New CSS availible: ' + myUpdate + '\n\nPlease update!');}
}
},
//'reset': function() { alert('reset') },
// relaod page on close after save
'save': function() {
if (!GM_config.get('enConfNavFixed') && GM_config.get('enConfNavFixed')!=enFixedNav) {window.location.reload(false);}
EnstylerButtonCreate();
EnstylerPagePickerCreate();
EnstylerBlacklistRemove()
EnstylerBlacklist();
EnstylerFixedNav();
enCheckUpdates();
GM_config.close()
GM_config.open()
},
'close': function() { enGMConfigOpen=false;},
},
'frame': enGMFrame // Element used for the panel
}
);
// dummy, do not delete
function enGetHome() {;}
// ============== START EnstyerJS =============
EnstylerInit();
EnstylerProcessLinks();
EnstylerBlacklist();
EnstylerAvatarPopup();
EnstylerDealActions();
EnstylerFixedNav();
// delay Pagepicker and repaeting actions after finishing everything else
function EnstylerDelayedInit() {
// don't know why, but works only if called with delay ...
EnstylerButtonCreate();
EnstylerPagePickerCreate();
enCheckUpdates();
// track DOM change Events, debounce: wait 1000ms after mutiple events
// then re-apply (somse) changes to dynamic loaded content,
$('.fGrid-last2, .thread-list--type-card').bind("DOMSubtreeModified",$.debounce( 1000, function(){
EnstylerBlacklist();
EnstylerDealActions();
EnstylerAvatarPopup();
EnstylerPagePickerCreate();
}));
}
// wait until page is loaded completely
if (USI) { // USI -> runs script on page load -> give some time to finish rendering
sleepAsync(Date.now()-EnstylerDelay).then(() => { EnstylerDelayedInit(); });
}
else { // Greasemonkey and Tampermonky -> runs script on DOM ready -> wait for load
$(window).bind("load", function() { EnstylerDelayedInit(); });
}
// ============= EnStyler UserScript Homepage functions =======
// experimental support for EnStyler2 export / import
} else {
// we are on ujserstyle
function enGetHome() {
var myOptions='';
$('#style-settings select').each(function() {
var myID = $(this).attr('id');
var myValue = $('#'+myID).val();
var myText = $('option[value='+ myValue +']').text();
myOptions +='#' + myID + ':' + myValue +':' + myText +';\n';
});
$('#style-settings input:checked').each(function() {
var myID = $(this).attr('id');
var myValue = $('#'+myID).val();
var myText = $('label[for='+ myID +']').text();
myOptions +='#' + myID + ':' + myValue +':' + myText +';\n';
});
GM_config.set('saveOpt', myOptions);
}
function enSetHome() {
// get saved options,remove newlines and split to settings array
var myOptions=GM_config.get('saveOpt');
myOptions=myOptions.replace(/\n/g,'');
var mySettings = myOptions.split(';');
// abort if no options found
if (myOptions=='' || !myOptions.startsWith('#')) {return;}
for (var i=0; i< mySettings.length; i++) {
// each Setting has 3 fields seperated by :, but only 2 used
var myField=mySettings[i].split(':');
if (myField[0].match(/^#setting/i)) {
// select
$(myField[0]).val('');
$(myField[0]).val(myField[1]);
} else if (myField[0].startsWith('#option')) {
// option
$(myField[0]).prop('checked', true);
} else {
if (myField[0] != '') {alert('unkown option: "' + myField +'"');}
}
}
}
// activate config for Enstyler Homepage
GM_config.init(
{
id: 'GM_config',
title: 'Enstyler2 - Settings',
fields: enHomefieldDefs,
'events': // Callback functions object
{
//'init': function() { alert('onInit()'); },
// remove elements ich switch is checked or not
//'open': function() { enGetHome(); },
//'reset': function() { enGMOptChange = true; },
// relaod page on close after save
'save': function() { enSetHome(); GM_config.close()},
'close': function() { enGMConfigOpen=false; },
},
'frame': enGMFrame // Element used for the panel
}
);
// START Enstyler 2 Homepage
EnstylerHomeButton();
// set saved options
enSetHome();
}
//=========== Support functions for actual use ======
// display website in external window
function showUrl(str) {
var myDeco = "innerheight=780,innerwidth=550";
var myName = "enstyler";
// workaround for not working window.focus(): close an existing window first
// not working on mobile :-(
//var myWindowShow = window.open('', myName, "width=100,height=100").close();
var 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);
}
// insertAfter like .insertBefore but as support function
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
// from https://gist.github.com/TheDistantSea/8021359
// returns 0 on equal, 1 on v1 newer, -1 on v2 newer
function versionCompare(v1, v2) {
var lexicographical = false,
zeroExtend = true,
v1parts = v1.split('.'),
v2parts = v2.split('.');
function isValidPart(x) { return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x); }
if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {return NaN; }
if (zeroExtend) {
while (v1parts.length < v2parts.length) v1parts.push("0");
while (v2parts.length < v1parts.length) v2parts.push("0");
}
if (!lexicographical) {
v1parts = v1parts.map(Number);
v2parts = v2parts.map(Number);
}
for (var i = 0; i < v1parts.length; ++i) {
if (v2parts.length == i) { return 1; }
if (v1parts[i] == v2parts[i]) { continue; }
else if (v1parts[i] > v2parts[i]) { return 1; }
else { return -1; }
}
if (v1parts.length != v2parts.length) { return -1; }
return 0;
}
// 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));
}