frisch's Utilities

Combines several userscripts. Includes Shift-Copy, Image Transformation, Html Element Deletion, Mousegrab for Link selection

  1. // ==UserScript==
  2. // @name frisch's Utilities
  3. // @namespace http://null.frisch-live.de/
  4. // @version 0.35
  5. // @description Combines several userscripts. Includes Shift-Copy, Image Transformation, Html Element Deletion, Mousegrab for Link selection
  6. // @author frisch
  7. // @grant GM_openInTab
  8. // @include *
  9. // ==/UserScript==
  10. console.log("Initializing frisch Utilities...");
  11.  
  12. var jq = document.fExt.jq;
  13. var ctxUtil = document.fExt.ctxMenu.addCtxSub("Utilities");
  14.  
  15. // #################### Shift-Copy - Start
  16. var cpyText = '';
  17.  
  18. function clickOverride(e){
  19. var retVal = true;
  20. if(e.shiftKey){
  21. e.preventDefault();
  22. var src = document.fExt.getSelection() || document.fExt.getSource(e.target);
  23. switch(e.which){
  24. case 1:
  25. document.fExt.clipboard("Copy", src);
  26. retVal = false;
  27. break;
  28. case 2:
  29. cpyText += src + '\n';
  30. retVal = false;
  31. break;
  32. case 3:
  33. break;
  34. default:
  35. break;
  36. }
  37. }
  38.  
  39. return retVal;
  40. }
  41.  
  42. jq(document).on("auxclick", clickOverride);
  43. jq(document).on("click", clickOverride);
  44.  
  45. jq(document).keyup(function(e) {
  46. if (e.which === 16){ // Shift
  47. if(cpyText.length > 0)
  48. document.fExt.clipboard("Copy", cpyText);
  49.  
  50. cpyText = '';
  51. }
  52. });
  53. // #################### Shift-Copy - End
  54.  
  55. // #################### Html Elements Deleter - Start
  56.  
  57. var ctxDelHtml = document.fExt.ctxMenu.addCtxItem("Delete Element", ctxUtil);
  58. ctxDelHtml.Action = function(event, sender, actor) {
  59. if(delHtmlTarget !== undefined) {
  60. jq(delHtmlTarget).remove();
  61. delHtmlTarget = undefined;
  62. }
  63. };
  64. var delHtmlTarget;
  65.  
  66.  
  67. // #################### Html Elements Deleter - End
  68.  
  69. // #################### GENERAL CTX HANDLING - Start
  70. jq("#fExtContextMenu").on("fExtContextMenuOpening", function(event, actor){
  71. delHtmlTarget = actor;
  72. });
  73. // #################### GENERAL CTX HANDLING - End
  74.  
  75. // #################### Image Rotation - Start
  76.  
  77. var subTransf = document.fExt.ctxMenu.addCtxSub("Transformation", ctxUtil);
  78.  
  79. document.fExt.ctxMenu.addCtxItem("Rotate left", subTransf).Action = function(event, sender, actor){
  80. document.fExt.rotate(actor, -90);
  81. };
  82.  
  83. document.fExt.ctxMenu.addCtxItem("Rotate right", subTransf).Action = function(event, sender, actor){
  84. document.fExt.rotate(actor, 90);
  85. };
  86.  
  87. document.fExt.ctxMenu.addCtxItem("Zoom in", subTransf).Action = function(event, sender, actor){
  88. document.fExt.zoomIn(actor, 20);
  89. };
  90.  
  91. document.fExt.ctxMenu.addCtxItem("Zoom out", subTransf).Action = function(event, sender, actor){
  92. document.fExt.zoomOut(actor, 20);
  93. };
  94.  
  95. // #################### Image Rotation - End
  96.  
  97. // #################### Cloud Converter - Start
  98. var allowedExtensions = ["webm", "gif"];
  99. var cApiKey = 'pUrKocUqgi32gMrbsDNgqhfTu6leQzBhpI5PhqgzWkdOoysidU892f0M9AvjJUBW5gVpgWWhTQdybz54ygK3cQ'; // Enter your API-Key here, get it at https://cloudconvert.com/
  100.  
  101. if(cApiKey.length > 0) {
  102. var jq = document.fExt.jq;
  103. var ccContainer = jq("<div id='ccContainer' style='display:none;' ><a href='#' id='ccLink' style=''>Convert</a></div>");
  104. document.fExt.createStyle("#ccContainer { width: 60px; height: 18px; border: 2px solid black; font-weight: bold; text-align: center; padding: 2px 4px; position: absolute; background-color: #fff; }");
  105.  
  106. ccContainer.appendTo("body");
  107.  
  108. var ctxItemConv = document.fExt.ctxMenu.addCtxItem('Convert to MP4', ctxUtil);
  109. ctxItemConv.Action = function(event, sender){
  110. document.fExt.message("Starting conversion...");
  111. var src = jq("#ccLink").attr("href");
  112. var ext = grabExtension(src);
  113.  
  114. jq.ajax({
  115. url: "https://api.cloudconvert.com/process",
  116. beforeSend: function(xhr) {
  117. xhr.setRequestHeader("Authorization", cApiKey);
  118. },
  119. type: 'POST',
  120. dataType: 'json',
  121. data: {
  122. "apikey": cApiKey,
  123. "inputformat" : ext,
  124. "outputformat": "mp4"
  125. },
  126. success: function (data) {
  127. var convertLnk = "https:" + data.url;
  128. startConversion(src, convertLnk);
  129. console.log("Process URL = " + convertLnk);
  130. },
  131. error: function(data){
  132. document.fExt.message("Error converting file: " + data.responseText);
  133. }
  134. });
  135. return false;
  136. };
  137.  
  138. jq("#fExtContextMenu").on("fExtContextMenuOpening", function(event, actor){
  139. var src = document.fExt.getSource(actor.get(0));
  140. var ext = grabExtension(src);
  141.  
  142. ctxItemConv.Toggle(jq.inArray(ext, allowedExtensions) >= 0);
  143. jq("#ccLink").attr("href",src);
  144. });
  145. }
  146. else {
  147. console.log("No CloudConverter APIKey found.");
  148. }
  149.  
  150. function startConversion(srcLnk, convLnk){
  151. document.fExt.message("Processing item...");
  152.  
  153. jq.ajax({
  154. url: convLnk,
  155. type: 'POST',
  156. dataType: 'json',
  157. data: {
  158. "wait": true,
  159. "input": "download",
  160. "file": srcLnk,
  161. "outputformat": "mp4"
  162. },
  163. success: function(data){
  164. var url = "https:" + data.output.url;
  165. GM_openInTab(url, true);
  166. document.fExt.message();
  167. },
  168. error: function(data){
  169. document.fExt.message("Error converting " + srcLnk + ": " + data.responseText);
  170. }
  171. });
  172. }
  173.  
  174. function grabExtension(src){
  175. var start, end;
  176.  
  177. start = src.lastIndexOf(".") + 1;
  178. if(src.lastIndexOf("?") >= 0)
  179. end = src.lastIndexOf("?");
  180. else
  181. end = src.length;
  182.  
  183. return src.substring(start, end);
  184. }
  185.  
  186. // #################### Cloud Converter - End
  187.  
  188. // #################### Image Info - Start
  189. /*
  190. document.fExt.ctxMenu.addCtxItem("View Image Info", ctxUtil).Action = function(event, sender, actor){
  191. $.getImageData({
  192. url: actor.get(0).src,
  193. success: function(image){
  194. // Do something with the now local version of the image
  195. },
  196. error: function(xhr, text_status){
  197. // Handle your error here
  198. }
  199. });
  200. };
  201. */
  202. // #################### Image Info - End
  203. // #################### YouTubeInMP4 - Start
  204. var ytimp4Url = "http://youtubeinmp4.com/youtube.php?video=";
  205. document.fExt.ctxMenu.addCtxItem("Download on Youtubeinmp4.com", ctxUtil).Action = function(event, sender, actor){
  206. var src = window.location.href;
  207. if(src.indexOf("/watch") < 0)
  208. src = document.fExt.getSource(actor.get(0));
  209.  
  210. var url = encodeURI(ytimp4Url + src);
  211. GM_openInTab(url);
  212. };
  213. // #################### YouTubeInMP4 - End
  214.  
  215. // #################### Mousegrab for Link - Start
  216. var holdInfo = {
  217. id: 0,
  218. actor: undefined,
  219.  
  220. display: undefined,
  221. height: 0,
  222. width: 0,
  223. offset: undefined,
  224. value: undefined,
  225.  
  226. set: function(actor){
  227. this.id++;
  228. this.actor = actor;
  229. this.display = jq(actor).css("display");
  230.  
  231. this.height = jq(actor).outerHeight();
  232. this.width = jq(actor).outerWidth();
  233. this.offset = jq(actor).offset();
  234. this.value = jq(actor).text();
  235.  
  236. return this.id;
  237. },
  238. reset: function(){
  239. this.hide();
  240. this.id++;
  241. this.actor = undefined;
  242. this.display = undefined;
  243. this.height = undefined;
  244. this.width = undefined;
  245. this.offset = undefined;
  246. this.value = undefined;
  247. },
  248. show: function(){
  249. if(this.actor) {
  250. /*
  251. jq(this.actor).hide();
  252. */
  253. selectorBox.show(0)
  254. .text(this.value)
  255. .offset(this.offset)
  256. .val(this.value)
  257. .width(this.width)
  258. .height(this.height)
  259. .focus();
  260. }
  261. },
  262. hide: function(){
  263. /*
  264. if(this.actor){
  265. if(this.display)
  266. jq(this.actor).css("display", this.display);
  267. else
  268. jq(this.actor).show();
  269. }
  270. */
  271. if(selectorBox.is(":visible")) {
  272. selectorBox.hide();
  273. selectorBox.val('');
  274. }
  275. },
  276. };
  277. var msNeededToHold = 350; // Time needed to hold mousebutton in milliseconds
  278. var selectorBox = jq("<input type='text' style='display: none;' id='fExtUtilSelectorBox' value=''></input>");
  279. document.fExt.createStyle("#fExtUtilSelectorBox { font-size: 14px !important; background-color: white !important; color: black !important; z-index: " + document.fExt.TopZIndex() + " !important; padding: 6px !important; position: absolute; }");
  280.  
  281. selectorBox.focusout(function(){
  282. holdInfo.reset();
  283. });
  284.  
  285. selectorBox.appendTo("body");
  286.  
  287. jq(document).on("mousedown", "a", function(e) {
  288. if(e.which === 1){
  289. holdInfo.reset();
  290. var holdID = holdInfo.set(e.target);
  291. jq(document).on("mousemove", cancelAtDrag);
  292.  
  293. setTimeout(function(){
  294. if(e.target === holdInfo.actor && holdID === holdInfo.id) {
  295. holdInfo.show();
  296. }
  297. }, msNeededToHold);
  298. }
  299.  
  300. return true;
  301. });
  302.  
  303. function cancelAtDrag(e){
  304. if(e.which === 1){
  305. holdInfo.reset();
  306. }
  307. jq(document).off("mousemove", cancelAtDrag);
  308. }
  309.  
  310. jq(document).on("mouseup", "a", function(e) {
  311. if(e.target === holdInfo.actor) {
  312. holdInfo.reset();
  313. }
  314. else return true;
  315. });
  316. // #################### Mousegrab for Link - End
  317.  
  318.  
  319. // #################### Copy links from Domain - Start
  320. var ctxSubCpyDom = document.fExt.ctxMenu.addCtxSub("Copy Domain Links", ctxUtil);
  321. var objCpyDom = [];
  322. var cpyLnks = [];
  323.  
  324. jq("a[href]").each(function(ind, itm) {
  325. var hnSplit = itm.hostname.split(".");
  326.  
  327. var domainName;
  328. if(hnSplit.length === 3)
  329. domainName = hnSplit[1];
  330. else
  331. domainName = hnSplit[0];
  332.  
  333. if(domainName) {
  334. var dictCpyDom;
  335. for (var i in objCpyDom) {
  336. var currCpyDom = objCpyDom[i];
  337. if (currCpyDom.Domain === domainName) {
  338. dictCpyDom = currCpyDom;
  339. break;
  340. }
  341. }
  342.  
  343. if (dictCpyDom !== undefined) {
  344. if(jq.inArray(itm.href, dictCpyDom.Links) < 0)
  345. dictCpyDom.Links.push(itm.href);
  346. } else {
  347. dictCpyDom = {
  348. Domain: domainName,
  349. Links: [itm.href],
  350. };
  351. objCpyDom.push(dictCpyDom);
  352. }
  353. }
  354. });
  355.  
  356. objCpyDom.sort(function(a, b) {
  357. return a.Domain.localeCompare(b.Domain);
  358. });
  359.  
  360. for(var i = 0; i < objCpyDom.length; i++) {
  361. var objDomain = objCpyDom[i];
  362. var ctxCpyDom = document.fExt.ctxMenu.addCtxItem(objDomain.Domain + "(" + objDomain.Links.length + ")", ctxSubCpyDom);
  363. ctxCpyDom.ClickCloses = false;
  364. ctxCpyDom.Domain = objDomain;
  365. ctxCpyDom.Action = function() {
  366. cpyLnks = cpyLnks.concat(this.Domain.Links);
  367. };
  368. }
  369.  
  370. jq("#fExtContextMenu").on("fExtContextMenuClosing", function(event, actor){
  371. if(cpyLnks.length > 0) {
  372. if(document.fExt.clipboard("Copy", cpyLnks.join('\n') + '\n'))
  373. document.fExt.popup("Copied " + cpyLnks.length + " links.");
  374.  
  375. cpyLnks = [];
  376. }
  377. });
  378.  
  379. jq("#fExtContextMenu").on("fExtContextMenuOpening", function(event, actor){
  380. cpyLnks = [];
  381. });
  382. // #################### Copy links from Domain - End