Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Show JSFiddle revisions for each fiddle v2
// ==UserScript==
// @name           Show JSFiddle revisions for each fiddle v2
// @namespace      webapps.se
// @author 		   brasofilo
// @include        http://jsfiddle.net/user/*
// @description    Add revision history.
// ==/UserScript==

/* Stores the API list result */
jsf_titles = [];

jquery_url = '//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js'

/**
 * Sometimes the Revision URL is anonymous, without /username/
 * this function tests the URL before navigating
 * if it is a 404, we strip the username from the URL
 * 
 * http://stackoverflow.com/a/22097991/1287812
 */
testRevisionURL = function( url ) 
{
    var request;
    if(window.XMLHttpRequest)
        request = new XMLHttpRequest();
    else
        request = new ActiveXObject("Microsoft.XMLHTTP");
    request.open('GET', url, false);
    request.send();
    if (request.status === 404) {
        window.location = url.replace( dashboardPage() + '/', '' );
    } else {
        window.location = url;
    }
}

/**
 * Build the Revisions links
 */
appendRevisionLinks = function( $div, $entry ) {
    if( parseInt( $entry.latest_version ) > 0 ) {
        
        var start = 1;
        var total = parseInt( $entry.latest_version );
        if( total > 50 ) start = total - 50;
        console.log($div.parent().next('p.info').text());
        $div.parent().next('p.info').append( ' - Revisions: | ' );
        for (i = start; i <= total; i++) { 
            var click_url = ' onClick="testRevisionURL(\'' + $entry.url + i + '\')"';
            $div.parent().next('p.info').append( '<a href="javascript:void(0)" ' + click_url + ' title="Title: ' + $entry.title + " | URL: " + $entry.url + i + '"><b style="font-size:.8em">' + i + '</b></a> | ' );
        }
    } else {
        $div.parent().next('p.info').append( ' - No revisions ' );
    }
}

/**
 * Callback for jQuery loaded
 * Search all fiddle titles on the page and compare with the API list
 */
function jqueryCallback() {
    
    var createCookie = function(name,value,days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime()+(days*24*60*60*1000));
            var expires = "; expires="+date.toGMTString();
        }
        else var expires = "";
        document.cookie = name+"="+value+expires+"; path=/";
    }
    
    var readCookie = function(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for(var i=0;i < ca.length;i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
        }
        return null;
    }
    
    var eraseCookie = function(name) {
        createCookie(name,"",-1);
    }

    var $allFiddles = jQ('#body .fiddleList');
    
    // Read cookie
    var $hasCookie = readCookie('hide-pubs');
    
    var hideSlides = function( how ) {
        var $cookieVal = how ? 'yes' : 'no';
        createCookie( 'hide-pubs', $cookieVal, 9999 );
        
        jQ('.fiddleList .item h3 a:first-child').each(function() { 
            var $parent = jQ(this).parent().parent();
            var tit = jQ(this).text(); 
            if( tit.length != 8 ) {
                // Set anim vars
                var $speed = how ? 35 : 166;
                var $randi = ( Math.floor(Math.random() * 6) + 1 ) * $speed;
                
                // Show or hide fiddles
                if( how ) {
                    $parent.slideUp($randi).animate(
                        { opacity: 0 },
                        { queue: false, duration: $randi }
                    );
                    jQ('#hide-pubs').text('(show public)');
                    $allFiddles.addClass('hide-pubs');
                }
                else {
                    $parent.slideDown($randi).animate(
                        { opacity: 1 },
                        { queue: false, duration: $randi }
                    );
                    jQ('#hide-pubs').text('(hide public)');
                    $allFiddles.removeClass('hide-pubs');
                }
            }
        });
    }
    
    // Do user page
    if( dashboardPage() ) {
        var start_page = ( actualPage() - 1 ) * 10;
        jQ.ajax({
            url: 'http://jsfiddle.net/api/user/' + dashboardPage() + '/demo/list.json',
            data: { order: 'desc', start: start_page, limit: '10' },
            type: 'get',
            dataType: 'jsonp',
            jsonpCallback: 'revisionsHistory',
            cache: false,
            success: function(data) 
            {
                jQ('.fiddleList .item h3 a:first-child').each(function() { 
                    var $this = jQ(this);
                    var $url = $this.attr('href');
                    
                    data.list.forEach(function( entry ) {
                        if( entry.url.indexOf( $this.attr('href') ) > -1 ) {
                            appendRevisionLinks( $this, entry );
                            data.list.remove( entry );
                        }
                    });
                });
            }
        });
	// Do dashboard page
    } else {
        jQ('#main-nav li:nth-child(2)').append('&nbsp;&nbsp; <a style="font-size:.7em;color:#666" id="hide-pubs" href="javascript:void(0)"><small>(hide public)</small></a>');
        jQ('#hide-pubs').click(function(){
            if( $allFiddles.hasClass('hide-pubs') ) 
                hideSlides( false );
            else
                hideSlides( true );
        });
    }
    
    // Add original height
    jQ('.fiddleList .item').each(function(){
        jQ(this).attr('data-o-height', jQ(this).height() + 'px' );
    });
    
    // Duplicate paginator
    jQ('#body .paginator').clone().prependTo( jQ('#body') ).hide().slideDown();
    
    // Start up
    if( $hasCookie !== 'yes' ) {
        $allFiddles.addClass('hide-pubs');
        hideSlides( false );
    } else {
        hideSlides( true );
    }
}

/**
 * Load jQuery and do callback when jQuery has finished loading
 * Note, jQ replaces $ to avoid conflicts.
 * 
 * http://stackoverflow.com/a/3550261/1287812
 */
function addJQuery( callback ) 
{
    var script = document.createElement( 'script' );
    script.setAttribute( 'src', jquery_url );
    script.addEventListener( 'load', function() 
    {
        var script = document.createElement('script');
        script.textContent = 'window.jQ=jQuery.noConflict(true);(' + callback.toString() + ')();';
        document.body.appendChild( script );
    }, false );
    document.body.appendChild( script );
}


/**
 * Remove element from array
 * http://www.simonewebdesign.it/how-to-remove-element-from-array/
 */
Array.prototype.remove = function(value) {
    var idx = this.indexOf(value);
    if (idx != -1) {
        return this.splice(idx, 1); // The second parameter is the number of elements to remove.
    }
    return false;
}

/**
 * Which page of the Dashboard we're in
 */
actualPage = function(){
    var pathname = window.location.pathname.split('/');
    if( pathname[pathname.length-2] == "dashboard" )
        return 1;
    else {
        var pagenum = parseInt( pathname[pathname.length-2] );
        return isNaN( pagenum ) ? 1 : pagenum;
    }
}

/**
 * Public page or dashboard
 */
dashboardPage = function(){
    var pathname = window.location.pathname.split('/');
    if( pathname[2] == "dashboard" )
        return false;
    else
        return pathname[2];
}

/**
 * Start up
 */
//if( dashboardPage() ) {
	addJQuery( jqueryCallback );
    // alert('user name: ' + dashboardPage() + "\n page:" + actualPage() );
//}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment