5

JSFiddle uses urls in the form of http://jsfiddle.net/<user>/<script>/<revision>/ where revision is an incremental number. Is there any way to see other revisions of a script easily via a GUI interface or is the only way to manipulate the URL?

Is there any easy way to know how many revisions a script has without needing to manually increment the variable and check to see if a script exists there?

0

3 Answers 3

5

If it's one of your own fiddles it displays on your dashboard. There you'll see latest revision with a link.

EDIT: The GUI is updated but the functionality seems the same in this matter.

3

One way to know how many versions of a script you have is to press the delete button near the script in your dashboard. It will warn you with a message such as the following:

You're about to permanently delete <script>, and <num> of its revisions.

Another way is to update the script which will cause the script to use the latest revision number available in the URL.

0

We can query JSFiddle API to get an user's fiddles, it returns a JSONP with a latest_version (the number of revisions) for each fiddle. Add your user name to the following URL to see the results:

http://jsfiddle.net/api/user/{USERNAME}/demo/list.json?start=0&limit=10

As I was missing easy access to my revisions, I made a userscript to show them on the Public fiddles page of any user, it runs on all http://jsfiddle.net/user/* URLs that are not the dashboard (/user/dashboard/).


user public fiddles

Note that the API only returns public fiddles, the ones that have a name set on Fiddle Options. After setting this name, it takes a while before it appears on the API.


Observations:

  • While testing, I found fiddles with two thousand revisions, so I'm limiting the total revisions shown to the latest 50. To remove this feature, delete line 43 as can be seen in this Gist copy of the script bellow.

  • The script is Chrome only (I use Tampermonkey). I don't know how to use it on Firefox, tried but failed.

// ==UserScript==
// @name           Show JSFiddle revisions for each fiddle
// @namespace      webapps.se
// @author         brasofilo
// @include        http://jsfiddle.net/user/*
// @description    Add revision history to all JSFiddle public user pages 
// @require       //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js
// ==/UserScript==

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

/**
 * 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 Revision links
 */
appendRevisionLinks = function( $div, $entry ) {
    if( parseInt( $entry.version ) > 0 ) {
        var start = 1;
        var total = parseInt( $entry.version );
        if( total > 50 ) start = total - 50;
        $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 + '><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() {
    jQ('.fiddleList .item h3 a:first-child').each(function() { 
        var $this = jQ(this);
        var $url = $this.attr('href');
        jsf_titles.forEach(function(entry) {
            if( entry.url.indexOf($this.attr('href')) > -1 ) {
                appendRevisionLinks( $this, entry );
                jsf_titles.remove(entry);
            }
        });
    });
}

/**
 * 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", "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js");
    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);
}

/**
 * JSFiddle API callback function
 * Builds jsf_titles custom array with JSONP result
 */
fiddleObjects = function( json ){
    json.list.forEach(function(entry) {
        jsf_titles.push({'title': entry.title, 'version': entry.latest_version, 'url': entry.url });
    });
    addJQuery( jqueryCallback );
};

/**
 * Call API
 * 
 * http://stackoverflow.com/a/2887218/1287812
 */
callApi = function( user, page )
{
    var elm = document.createElement("script");
    elm.setAttribute("type", "text/javascript");
    var start = (page - 1) * 10;
    elm.src = "http://jsfiddle.net/api/user/" + user + "/demo/list.json?callback=fiddleObjects&order=desc&start=" + start + "&limit=10";
    document.body.appendChild(elm);
}

/**
 * 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
 * not used yet, but useful if start and limit are to be used on the API request
 */
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() ) {
    callApi( dashboardPage(), actualPage() );
    // alert('user name: ' + dashboardPage() + "\n page:" + actualPage() );
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.