Skip to content

Instantly share code, notes, and snippets.

Embed
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
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.