Greasy Fork is available in English.

Stack Snippets Console

Add a console to "Stack Snippets" executable code on StackExchange

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

  1. // ==UserScript==
  2. // @name Stack Snippets Console
  3. // @namespace http://stackexchange.com/users/3846032/scimonster
  4. // @version 1.1.0
  5. // @description Add a console to "Stack Snippets" executable code on StackExchange
  6. // @include http://*.stackexchange.com/*
  7. // @include http://stackoverflow.com/*
  8. // @include http://*.stackoverflow.com/*
  9. // @include http://stacksnippets.net/*
  10. // @copyright 2014+, Scimonster
  11. // ==/UserScript==
  12.  
  13. if (!window.postMessage) {
  14. console.log('postMessage not supported; Snippets Console cannot work');
  15. return;
  16. }
  17.  
  18. if (location.hostname == 'stacksnippets.net') {
  19. (function(){
  20.  
  21. // define some functions
  22.  
  23. function isSEDomainName(dname) {
  24. return !!~["stackoverflow.com", "stackexchange.com"].indexOf(dname.split('.').slice(-2).join('.'));
  25. }
  26.  
  27. function URLparser(href) {
  28. var p = document.createElement('a');
  29. p.href = href;
  30. return p;
  31. }
  32.  
  33. // listen for the ping
  34.  
  35. this.addEventListener('message', function(ev){
  36. if (isSEDomainName(URLparser(ev.origin).hostname) && ev.data == 'console ping') {
  37. // passes the test
  38. listen(ev);
  39. }
  40. }, false);
  41.  
  42. // listen for console.log()s
  43.  
  44. function listen(ev) {
  45.  
  46. var oldLog = console.log;
  47.  
  48. function log(firstArg) {
  49. var args = [].slice.call(arguments);
  50.  
  51. oldLog.apply(console, args); // use the default console.log()
  52.  
  53. if (typeof firstArg == 'string') { // might require replacing
  54. if (~firstArg.indexOf('%s') || ~firstArg.indexOf('%d') || ~firstArg.indexOf('%i') || ~firstArg.indexOf('%f')) {
  55. // there is something to be replaced
  56. args.shift();
  57. firstArg = firstArg.replace(/%[sdif]/g, function(match){
  58. switch (match) {
  59. case '%s': return args.shift().toString();
  60. case '%d': case '%i': return parseInt(args.shift());
  61. case '%f': return parseFloat(args.shift());
  62. default: return match;
  63. }
  64. });
  65. args.unshift(firstArg);
  66. }
  67. }
  68. // replacements done, ready for concat
  69. var text = args.map(function(a){
  70. if (typeof a == 'object') {
  71. try {
  72. return JSON.stringify(a);
  73. } catch(e) {
  74. return "{bad object}";
  75. }
  76. }
  77. return a.toString();
  78. });
  79.  
  80. postMessage('log', text.join(''));
  81. }
  82.  
  83. this.console.log = log;
  84.  
  85. this.addEventListener('error', function(ev){
  86. postMessage('err', ev.message);
  87. }, false);
  88.  
  89. function postMessage(type, message) {
  90. ev.source.postMessage({
  91. type: type,
  92. message: message,
  93. time: new Date,
  94. snippet: this.name // the iframe
  95. }, ev.origin);
  96. }
  97.  
  98. }
  99.  
  100. })();
  101. } else {
  102. (function(){
  103.  
  104. function padNum(num, length) {
  105. num = num.toString();
  106. return num.length < length ? padNum('0' + num, length) : num;
  107. }
  108.  
  109. $(document).on('click', 'div.snippet-result input[type=button]', function(){
  110. var container = $(this).parent().parent();
  111. container.children('.snippet-console').remove();
  112. if (!this.className) { // the run button
  113. $('<div class="snippet-console"><h6><a href="http://stackapps.com/q/4931/28683" target="_blank">Snippet Console</a> <small>v1.1.0</small></h6><ul></ul></div>').appendTo(container).css({
  114. position: 'relative',
  115. width: '100%',
  116. maxHeight: 200,
  117. borderTopWidth: 1,
  118. borderTopStyle: 'solid',
  119. borderTopColor: 'rgb(170, 170, 170)',
  120. overflow: 'auto',
  121. display: 'none'
  122. }).children('ul').css({
  123. listStyleType: 'none',
  124. fontFamily: 'monospace'
  125. });
  126.  
  127. var snippet = container.find('iframe')[0];
  128.  
  129. snippet.onload = function(){
  130. setTimeout(function(){
  131. snippet.contentWindow.postMessage('console ping', "*");
  132. // need to accept all because the iframe has no URL
  133. }, 100);
  134. };
  135. }
  136. });
  137.  
  138. window.addEventListener('message', function(ev){
  139. if (ev.origin == 'null' && ev.data.snippet) { // seems to be a snippet
  140. var time = padNum(ev.data.time.getHours(),2)+':'+padNum(ev.data.time.getMinutes(),2)+':'+padNum(ev.data.time.getSeconds(),2)+'.'+padNum(ev.data.time.getMilliseconds(),3);
  141. var li = $('<li data-type="'+ev.data.type+'"><span style="color:gray">'+time+':</span> <span></span></li>');
  142. li.find('span').last().text(ev.data.message);
  143. if (ev.data.type == 'err') {
  144. li.find('span').last().css('color', 'red');
  145. }
  146. var snCons = $('iframe[name="'+ev.data.snippet+'"]').parent().siblings('.snippet-console').show();
  147. snCons.children('ul').append(li);
  148. snCons.scrollTop(snCons.children('ul').height()); // scroll to bottom
  149. }
  150. }, false);
  151. })();
  152. }