I adapted the script to add an arrow before any <pre>
that contains scrollbars, using the following function modified to account for horizontal and vertical scrollbars.
Here's the script in action in some innocent code blocks that have lots of hidden stuff.
GIF recorded before moving the arrows to the right.
It only runs when viewing a question or doing some review task.
// ==UserScript==
// @name Expand code blocks on Stack Exchange sites
// @namespace stackapps
// @description Click a code block with scroll bars and it automatically expands
// @match *://*.askubuntu.com/questions*
// @match *://*.askubuntu.com/review*
// @match *://*.mathoverflow.net/questions*
// @match *://*.mathoverflow.net/review*
// @match *://*.serverfault.com/questions*
// @match *://*.serverfault.com/review*
// @match *://*.stackapps.com/questions*
// @match *://*.stackapps.com/review*
// @match *://*.stackexchange.com/questions*
// @match *://*.stackexchange.com/review*
// @match *://*.stackoverflow.com/questions*
// @match *://*.stackoverflow.com/review*
// @match *://*.superuser.com/questions*
// @match *://*.superuser.com/review*
// @exclude *://chat.*
// @exclude *://blog.*
// @exclude *://api.*
// @exclude *://data.*
// @grant none
// @author Alconja
// @contributor brasofilo
// ==/UserScript==
/**
* Adapted from https://stackoverflow.com/a/8971716/1287812
*/
$.fn.has_scrollbar = function() {
var divnode = this.get(0);
if(divnode.scrollHeight > divnode.clientHeight || divnode.scrollWidth > divnode.clientWidth )
return true;
}
/**
* Expand <pre>
*/
function expando( pre ) {
var maxHeight = null;
pre.css("z-index", 1000);
var code = pre.children("code");
if (maxHeight === null) {
maxHeight = pre.css("max-height");
if( pre.attr('max-height') === undefined )
pre.attr('max-height',maxHeight);
}
var oldWidth = pre.width();
var codeWidth = Math.max(code.width(), oldWidth);
var maxWidth = $(window).width() - 20;
var width = Math.min(maxWidth, codeWidth);
var maxLeft = (-1 * pre.offset().left) + 5;
var idealLeft = (oldWidth - width) / 2.0;
var left = Math.max(maxLeft, idealLeft);
pre.css({width: width + "px", position: "relative", left: left + "px", maxHeight: "inherit"});
if (width < codeWidth) { //last ditch attempt to fit...
var pc = 100 * width / codeWidth;
pc = Math.max(pc, 70); //any smaller & you can't read it...
pre.css("font-size", pc + "%");
}
}
/**
* Contract <pre>
*/
function contracto( pre ) {
pre.css({width: "auto", position: "static", maxHeight: pre.attr('max-height'), fontSize: "100%"});
}
/**
* Check page and add arrows
*/
function addArrows() {
var count_pre = 1;
$('pre').each(function(){
if( $(this).has_scrollbar() ) {
$(this).before('<span class="expander-arrow-small-hide" id="expander-id-' + count_pre + '" style="float:right"></span>');
$('#expander-id-'+count_pre).click(function(){
if( $(this).hasClass('expander-arrow-small-hide') ){
expando( $(this).next() );
$(this).removeClass('expander-arrow-small-hide').addClass('expander-arrow-small-show');
}
else {
contracto( $(this).next() );
$(this).removeClass('expander-arrow-small-show').addClass('expander-arrow-small-hide');
}
}).css('cursor','pointer');
count_pre++;
}
});
}
/**
* Run when reviewing
*/
if( StackExchange.options.routeName === 'Review/Task' ) {
$(document).ajaxComplete(function( event, xhr, settings ){
if( settings.url.indexOf('review/task-reviewed') !== -1 || settings.url.indexOf('review/next-task') !== -1 ) {
addArrows();
}
});
}
/**
* Run when viewing a question
*/
if( StackExchange.options.routeName == "Questions/Show" ) {
// Only SO has this property as visible, which is needed to fully expand the blocks
if( location.host !== 'stackoverflow.com' && location.host !== 'meta.stackoverflow.com' ) {
if( $('#content').css('overflow') === 'auto' )
$('#content').css('overflow','visible');
}
addArrows();
}
Install
.click(
to.dblclick(
if you wanted it to expand on double click instead.