EnstylerJS

MyDealz Enstyler Frontend and enhanced features

目前为 2016-11-03 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name EnstylerJS
  3. // @namespace Enstyler
  4. // @description MyDealz Enstyler Frontend and enhanced features
  5. // @include http://www.mydealz.de/*
  6. // @include https://www.mydealz.de/*
  7. // @version 2.11.031
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @grant GM_log
  11. // @grant GM_xmlhttpRequest
  12. // @require http://code.jquery.com/jquery-3.1.1.min.js
  13. // @require http://cdnjs.cloudflare.com/ajax/libs/jquery-throttle-debounce/1.1/jquery.ba-throttle-debounce.min.js
  14. // @require http://openuserjs.org/src/libs/sizzle/GM_config.js
  15. // ==/UserScript==
  16.  
  17. // ========== RUN EnstylerJS =====================================
  18. // create object for enstyler "Menu Button"
  19. var input = document.createElement('input');
  20. input.type = 'button';
  21. input.value = 'Enstyler';
  22. input.onclick = showEnstylerConfig;
  23.  
  24.  
  25. function EnstylerInit () {
  26. // hide Enstyler2 CSS (c) text because we have a button now
  27. addStyleString('.threadWidget-footer::after {display: none !important};');
  28.  
  29. // basic config panel formatting, everything else is formatted by enstyler
  30. var enCSS = ['#GM_config {left: 5% !important; top: 9% !important; height: auto !important; max-width: 35em !important;}',
  31. '#GM_config input, #GM_config button { border: 1px solid; margin: 0.5em 0em 0.2em 1em; padding: 0.1em;}',
  32. '#GM_config .reset { font-size: 9pt; padding-right: 1em; }',
  33. ].join(" ");
  34. addStyleString(enCSS);
  35. }
  36.  
  37. function EnstylerJS () {
  38. // add Enstyler Button to ...
  39. var myElement;
  40. if (GM_config.get('enConfBtn') && $(window).width() > GM_config.get('enConfBtnMinWidth')) {
  41. // add button to MainNav
  42. var Elements = document.getElementsByClassName("navMenu-trigger");
  43. myElement = Elements[0];
  44. input.className = 'nav-link-text vAlign--all-m';
  45. } else {
  46. // add button to SubNav
  47. myElement = document.getElementById('tour-filter');
  48. input.className = 'box--all-i subNavMenu-link';
  49. input.setAttribute('style', 'font-size: 1.28571em; font-weight: 700; top: 3px; left: -0.7em');
  50. }
  51. // only if myElement exist
  52. if (myElement !== null) {
  53. myElement.appendChild(input);
  54. }
  55.  
  56. // ============ functions to modify page content =============================
  57.  
  58. // REGEX to detect external URL
  59. var REGEX_THREAD = /^https?:\/\/www\.mydealz\.de\/visit\/thread(image)?\/\d+$/;
  60. var REGEX_DESC = /^https?:\/\/www\.mydealz\.de\/visit\/threaddesc\/\d+\/\d+$/;
  61. var REGEX_COMMENT = /^https?:\/\/www\.mydealz\.de\/visit\/comment\/\d+\/\d+$/;
  62. var REGEX_AMAZONMOB = /^https?:\/\/www\.amazon\..*\/gp\/aw\/.*$/;
  63. //var REGEX_AMAZON = /^https?:\/\/www\.amazon\..*$/;
  64.  
  65. //* GM_xmlhhtpREquest not supported by firefox mobile :-(((
  66. // abfangen aller links mit jQuery
  67. $('a').bind('click', function(){
  68. var url = this.href;
  69.  
  70. // externer Link mit Redirect ...
  71. // Match REDIRECT URLs and open new Window with finalUrl
  72. if (GM_config.get('enConfFilterLink') && url.match(REGEX_THREAD) || url.match(REGEX_DESC) || url.match(REGEX_COMMENT)) {
  73. // Workaround: pre open window because of popup blockers
  74. var asyncWindow = window.open(url, '_blank');
  75. // now lookup redirecd external URL ...
  76. // alert("external URL detected");
  77. GM_xmlhttpRequest({
  78. method: 'GET',
  79. url: url,
  80. // here we get the final URL from redirect
  81. onload: function (response) {
  82. // process final URL
  83. var newUrl = response.finalUrl;
  84. //alert(newUrl);
  85. // lets see ...
  86. if (newUrl.match(REGEX_AMAZONMOB)) {
  87. newUrl = newUrl.replace("/gp/aw/d/", "/dp/");
  88. newUrl = newUrl.replace("/gp/aw/ol/", "/gp/offer-listing/");
  89. //alert("Amazon rewritten URL: " + newUrl);
  90. }
  91. // load processed URL in preopened window
  92. asyncWindow.location = newUrl;
  93. }
  94. });
  95. // return without link processing by Browser
  96. return false;
  97. }
  98. // return with link processing in Browser
  99. return true;
  100. }); // - END GM_xmlhttpRequest */
  101. } // END Enstyler
  102.  
  103. function EnstylerDealActions() {
  104. var enDealAction = ['<ENSTYLER-HREF-HERE>', // pattern to replace by deal link ...
  105. '<a class="link text--color-blue ico ico--type-pencil-blue ico--pos-l space--mr-3"', // edit
  106. '<a class="link text--color-blue ico ico--type-clock-blue ico--pos-l space--mr-3"', // expiried
  107. '<a class="link text--color-blue ico ico--type-bookmark-blue ico--pos-l space--mr-3"', //un-bookmark
  108. 'href=<ENSTYLER-HREF-HERE>/edit" data-handler="track" data-track="{&quot;action&quot;:&quot;goto_thread_edit_form&quot;,&quot;beacon&quot;:true}">Bearbeiten</a>',
  109. 'href=<ENSTYLER-HREF-HERE>/expire" data-handler="track" data-track="{&quot;action&quot;:&quot;expire_thread&quot;,&quot;label&quot;:&quot;contribution&quot;}">Abgelaufen</a>',
  110. 'data-handler="track replace" data-replace="{&quot;endpoint&quot;:&quot;<ENSTYLER-HREF-HERE>/remove&quot;,&quot;method&quot;:&quot;post&quot;}" data-track="{&quot;action&quot;:&quot;save_thread&quot;,&quot;label&quot;:&quot;engagement&quot;}"> Von Liste entfernen</a>',
  111. ];
  112. }
  113.  
  114. function EnstylerAvatarPopup() {
  115. // show popup user info while click on avatar ...
  116. // code used for MyDealz avatar popup, thanks to mydealz :-)
  117. var enPopupUser = ['<button data-handler="track popover" data-track="{&quot;action&quot;:&quot;show_short_user_profile&quot;,&quot;label&quot;:&quot;engagement&quot;}"data-popover="{&quot;endpoint&quot;:&quot;',
  118. '/short&quot;,&quot;target&quot;:&quot;#template-popoverLoader&quot;,&quot;layout&quot;:[{&quot;preset&quot;:&quot;e&quot;,&quot;y&quot;:&quot;50%&quot;,&quot;left&quot;:{&quot;offset&quot;:0},&quot;width&quot;:300,&quot;maxWidth&quot;:&quot;100%&quot;}]}">',
  119. '</button>',
  120. ];
  121. // remove second image from cardview
  122. if (GM_config.get('enConfUser')) { addStyleString('.thread-footer-cell a img.avatar.vAlign--all-m.space--mr-1.thread-avatar {display: none;}'); }
  123.  
  124. // replace every avatar link without popup
  125. $('.thread-footer-cell a.user.linkPlain, .user.linkPlain.thread-user').each(function () {
  126. if (GM_config.get('enConfUser')) {
  127. var Iam = $(this);
  128. // get inner html and link to user profile
  129. var myHtml = $(this).html();
  130. var mysrc = $(this).attr('href');
  131. //GM_log(myHtml);
  132. // seperate user name from image and add class user
  133. var myAvatar1 = myHtml.replace(/<span.*/,'');
  134. var myAvatar2 = myHtml.replace(/.*<span class=".* space--mr-1">/,'<span class=" space--mr-1 user link-plain">');
  135.  
  136. // show small / medium sized Avatar
  137. myAvatar1 = myAvatar1.replace('avatar--type-s','avatar--type-m'); //in Dealz
  138. if (GM_config.get('enConfAvatar')) { myAvatar1 = myAvatar1.replace('thread-avatar','avatar--type-m'); }
  139. // compose popup
  140. var myPopup = enPopupUser[0] + Iam.attr('href') + enPopupUser[1] + myAvatar1 + enPopupUser[2] + '<a href="' + Iam.attr('href') + '">'+ myAvatar2 + '</a>';
  141. //GM_log(myPopup);
  142. Iam.replaceWith(myPopup);
  143. }
  144. });
  145. }
  146.  
  147.  
  148. // ============= GM_config functions =======================================
  149.  
  150. // define GM_config elements
  151. var fieldDefs = {
  152. // Part one: load external content --------
  153. 'enstyler': {
  154. 'section': ['additonal features for Enstyler', ''],
  155. 'label': 'Install / Update CSS...', // Appears on the button
  156. 'type': 'button', // Makes this setting a button input
  157. 'click': function() { // Function to call when button is clicked
  158. showUrl('https://userstyles.org/styles/128262#style-info'); }
  159. },
  160.  
  161. 'dontCookies': {
  162. 'label': 'Mozilla no cookies...', // Appears on the button
  163. 'type': 'button', // Makes this setting a button input
  164. 'click': function() { // Function to call when button is clicked
  165. showUrl('https://addons.mozilla.org/de/addon/i-dont-care-about-cookies/'); }
  166. },
  167.  
  168. //* thhis has to be the last one,display only if internal version is disabled
  169. 'externalMobileRedirect': {
  170. 'label': 'Amazon mobile redirect...', // Appears on the button
  171. 'type': 'button', // Makes this setting a button input
  172. 'click': function() { // Function to call when button is clicked
  173. showUrl('https://greasyfork.org/de/scripts/19700'); }
  174. }, // */
  175.  
  176. // part two: EnstylerJS internal configuration options ------
  177. 'hidden1': { // display next section, dont kow why ...
  178. 'section': ['Configuration', ''],
  179. 'type': 'hidden', // Makes this setting a hidden input
  180. 'value': 'Some hidden value' // Value stored
  181. },
  182.  
  183. // postion of enstyler "button"
  184. 'enConfBtn': {
  185. 'label': 'Show Enstyler in MainNav', // Appears next to field
  186. 'type': 'checkbox', // Makes this setting a checkbox input
  187. 'default': false // Default value if user doesn't change it
  188. },
  189. 'enConfBtnMinWidth': {
  190. 'label': 'only if width is bigger than ', // Appears next to field
  191. 'type': 'int', // Makes this setting a text input
  192. 'min': 600, // Optional lower range limit
  193. 'max': 1200, // Optional upper range limit
  194. 'size': 4, // Limit length of input (default is 25)
  195. 'default': 850 // Default value if user doesn't change it
  196. },
  197.  
  198. // ehanced USerInfo
  199. 'enConfUser': {
  200. 'label': 'Show Popuop Userinfo', // Appears next to field
  201. 'type': 'checkbox', // Makes this setting a checkbox input
  202. 'default': true // Default value if user doesn't change it
  203. },
  204. 'enConfAvatar': {
  205. 'label': 'bigger Avatar for Popuop', // Appears next to field
  206. 'type': 'checkbox', // Makes this setting a checkbox input
  207. 'default': true // Default value if user doesn't change it
  208. },
  209. // enable filtering of external links
  210. 'enConfFilterLink': {
  211. 'label': 'Amazon mobile redirect', // Appears next to field
  212. 'type': 'checkbox', // Makes this setting a checkbox input
  213. 'default': true // Default value if user doesn't change it
  214. }, // */
  215.  
  216. // more Deal actions
  217. 'enConfMoreDeal': {
  218. 'label': 'additional Deal actions', // Appears next to field
  219. 'type': 'checkbox', // Makes this setting a checkbox input
  220. 'default': true // Default value if user doesn't change it
  221. },
  222.  
  223. // display copy message at end of section ...
  224. 'copy': {
  225. '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>'],
  226. 'type': 'hidden', // Makes this setting a hidden input
  227. 'value': 'Some hidden value' // Value stored
  228. },
  229. };
  230.  
  231.  
  232. // display GM_copnfig as div, so we cam apply CSS!!
  233. var enGMOptChange = false;
  234. var enGMFrame = document.createElement('div');
  235. document.body.appendChild(enGMFrame);
  236.  
  237. GM_config.init(
  238. {
  239. id: 'GM_config',
  240. title: 'EnstylerJS - Settings',
  241. fields: fieldDefs,
  242. 'events': // Callback functions object
  243. {
  244. //'init': function() { alert('onInit()'); },
  245. // do not diplay external mobile redirect is internal is activated
  246. 'open': function() { if (GM_config.get('enConfFilterLink')) {GM_config.fields['externalMobileRedirect'].remove();} },
  247. //'reset': function() { enGMOptChange = true; },
  248. // relaod page on close after save
  249. 'save': function() { enGMOptChange = true; if (GM_config.get('enConfFilterLink')) {GM_config.fields['externalMobileRedirect'].remove();} },
  250. 'close': function() { if (enGMOptChange) { location.reload(); enGMOptChange = false;} },
  251. },
  252. 'frame': enGMFrame // Element used for the panel
  253. }
  254. );
  255.  
  256.  
  257. // EnstylerJS Config Panel anzeigen
  258. function showEnstylerConfig() {
  259. GM_config.open();
  260. }
  261.  
  262. //=========== Support functions for actual use =======
  263.  
  264. // display website in external window
  265.  
  266. function showUrl(str) {
  267. var myDeco = "innerheight=800,innerwidth=600";
  268. var myName = "enstyler";
  269. // workaround for not working window.focus(): close an existing window first
  270. var myWindowShow = window.open('', myName, "width=100,height=100").close();
  271. myWindowShow = window.open(str, myName, myDeco);
  272. }
  273.  
  274. // add CSS in to document
  275. function addStyleString(str) {
  276. var node = document.createElement('style');
  277. node.innerHTML = str;
  278. document.body.appendChild(node);
  279. }
  280. // sleep time expects milliseconds, then execute code
  281. // NOTE: code runs in parallel (asnyc)!
  282. // Usage!
  283. // sleepAsync(500).then(() => {
  284. // Do something after the sleep!
  285. // });
  286.  
  287. function sleepAsync (time) {
  288. return new Promise((resolve) => setTimeout(resolve, time));
  289. }
  290.  
  291. // ============== START EnstyerJS =============
  292. EnstylerInit();
  293. EnstylerJS();
  294. EnstylerAvatarPopup();
  295.  
  296. // track DOM change Events, debounce: wait 500ms after mutiple events
  297. // then re-apply (somse) changes to dynamic loaded content,
  298. $('.fGrid-last2, .thread-list--type-card').bind("DOMSubtreeModified",$.debounce( 500, function(){
  299. //GM_log('DOMSubtreeModified detected!!!');
  300. EnstylerAvatarPopup();
  301.  
  302. }));
  303.