Greasy Fork is available in English.

Dribbble Extender

Shows who follows you on your following list

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Tendrás que instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Tendrás que instalar una extensión como Tampermonkey antes de poder instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Dribbble Extender
// @description  Shows who follows you on your following list
// @author       Kos
// @namespace    http://tampermonkey.net/
// @version      0.5
// @license      CC BY-SA 2.0
// @homepage     https://greasyfork.org/scripts/22003-dribbble-extender
// @include      https://dribbble.com/*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
// @grant        GM_addStyle
// ==/UserScript==

;(function() {
    'use strict';
    
    // styles for checkmark
    GM_addStyle(
        '.us-follows-you-mark {color:#b3e3bd;font-weight:200}\
        .us-fetch-ready {color:#2cff5a;font-weight:900}'
    );

    var ACCESS_TOKEN = '9eafaa85aba0e22cdd7b7ddaa23181b59c29989dbd27000c78db21f5609110f4',
        followers = [],
        // username
        username = $('.has-sub .profile-name').parent().attr('href').replace('/', ''),
        cacheKey = username,
        curPage = 1,
        perPage = 100,
        repaintDelay = 500,
        waitForAllFetch = false,
        requestPerIteration = 15,
        requestsResponseLeftCount = 0,
        mainIntervalStopped = true,
        lastIntervalFoundFollowers = null,
        justCache = false;

    // if not recognized logged in user, exit
    if (username == '')
    {
        return;
    }
    
    // functions for working with localStorage

    function lsTest()
    {
        var test = 'test';
        try
        {
            localStorage.setItem(test, test);
            localStorage.removeItem(test);
            return true;
        }
        catch(e)
        {
            return false;
        }
    }

    function getLocalStorageArray(name)
    {
        var list = localStorage.getItem(name);
        if (!list)
        {
            return [];
        }
        return JSON.parse(list);
    }

    function saveUpdatedFollowersList(list)
    {
        localStorage.setItem(cacheKey+'_followers_latest', JSON.stringify(list));
    }

    function addFollowerLocalStorage(id)
    {
        var list = getLocalStorageArray(cacheKey+'_followers_latest');

        if (list.indexOf(id) == -1)
        {
            list.push(id);
        }

        saveUpdatedFollowersList(list);
    }

    function saveFinishedAmountOfFollowers()
    {
        var list = getLocalStorageArray(cacheKey+'_followers_latest');

        localStorage.setItem(cacheKey+'_followers', JSON.stringify(list));
        saveUpdatedFollowersList([]);

        // update on page
        followers = list;
        paintFollowed();
    }

    var localStorageAvailable = lsTest();

    $(document).ready(function(){

        if (localStorageAvailable)
        {
            followers = getLocalStorageArray(cacheKey+'_followers');

            // if have previously saved followers, increase delay,
            // update on page only when all users parsed
            if (followers.length)
            {
                waitForAllFetch = true;
                
                // cache results for 5 minutes
                if (localStorageAvailable)
                {
                    var lastFetchTime = localStorage.getItem(cacheKey+'_last_followers_fetch');
                    if (lastFetchTime && new Date().getTime() - lastFetchTime < 5*60*1000)
                    {
                        justCache = true;
                        waitForAllFetch = false;
                    }
                }
            }

            // clear previously parsed data, to parse all new
            saveUpdatedFollowersList([]);
        }

        function finishParse()
        {
            if (mainIntervalStopped)
            {
                return;
            }

            clearInterval(mainInterval);
            mainIntervalStopped = true;
            
            if (localStorageAvailable)
            {
                localStorage.setItem(cacheKey+'_last_followers_fetch', new Date().getTime());
            }
        }
        
        if (!justCache)
        {
            mainIntervalStopped = false;
            
            var mainInterval = setInterval(function(){
                // if there are request we wait to finish, exit
                if (requestsResponseLeftCount > 0)
                {
                    return;
                }
                // if not found any users on last interval
                if (lastIntervalFoundFollowers !== null && lastIntervalFoundFollowers === 0)
                {
                    finishParse();
                    return;
                }
                requestsResponseLeftCount = requestPerIteration;
                lastIntervalFoundFollowers = 0;
                for (var i = 0; i < requestPerIteration; i++)
                {
                    $.ajax({
                        type: 'GET',
                        url: 'https://api.dribbble.com/v1/users/'+username+'/followers/?page='+(curPage++)+'&per_page='+perPage,
                        beforeSend: function(jqxhr)
                        {
                            jqxhr.setRequestHeader('Authorization', 'Bearer ' + ACCESS_TOKEN);
                        },
                        success: function(res)
                        {
                            if (res.length === 0)
                            {
                                finishParse();
                                return;
                            }

                            for (var i = 0; i < res.length; i++)
                            {
                                setFollowed(res[i].follower.id);
                                lastIntervalFoundFollowers++;
                            }

                            // if not full page, assume it last one
                            if (res.length < perPage)
                            {
                                finishParse();
                            }
                        },
                        complete: function(){
                            requestsResponseLeftCount--;
                            // if this is last response of last iteration, save ids for page
                            // in this 'if' fetch ends
                            if (requestsResponseLeftCount === 0 && mainIntervalStopped)
                            {
                                if (localStorageAvailable)
                                {
                                    saveFinishedAmountOfFollowers();
                                }
                            }
                        }
                    });
                }
            }, 100);
        }

        // paint then set repaint with delay
        paintFollowed();
        setInterval(paintFollowed, repaintDelay);
    });
    
    function setFollowed(id)
    {
        id = Math.round(id);

        if (!waitForAllFetch && followers.indexOf(id) == -1)
        {
            followers.push(id);
        }

        if (localStorageAvailable)
        {
            addFollowerLocalStorage(id);
        }
    }

    function paintFollowed()
    {
        paintOnFollowingPage();
        paintOnShotPage();
        paintOnShotsListPage();
        paintOnCommentsPage();
        paintOnUserPage();
    }
    
    function paintOnFollowingPage()
    {
        var following = $('ol.list-of-scrolling-rows').find('.scrolling-row');
        
        if (following.length == 0)
        {
            return;
        }

        for (var i = 0; i < following.length; i++)
        {
            var userId = parseInt(following[i].className.match(/.*?user-row-(\d+).*/)[1]),
                userBlock = $(following[i]),
                title = userBlock.find('.hover-card-parent');

            // if not followed, remove mark if has one
            if (followers.indexOf(userId) == -1)
            {
                userBlock.removeClass('us-follows-you');
                userBlock.find('.us-follows-you-mark').remove();
                continue;
            }

            // if already marked as follower do nothing until all fetched
            if (userBlock.hasClass('us-follows-you'))
            {
                if (mainIntervalStopped)
                {
                    userBlock.find('.us-follows-you-mark').addClass('us-fetch-ready');
                }
                continue;
            }

            // set mark of follower
            userBlock.addClass('us-follows-you');
            title.html('<span title="Follows you" class="us-follows-you-mark'+(mainIntervalStopped ? ' us-fetch-ready' : '')+'">✓ </span>'+title.html());
        }
    }
    
    function paintOnShotsListPage()
    {
        var dribbbles = $('ol.dribbbles > li');
        
        if (dribbbles.length == 0)
        {
            return;
        }

        for (var i = 0; i < dribbbles.length; i++)
        {
            var userBlock = $(dribbbles[i]);
            if (userBlock.find('.attribution-team').length)
            {
                continue;
            }
            
            var avatar = userBlock.find('.attribution-user img');

            // avatar is not loaded yet
            if (!avatar || !avatar.attr('src'))
            {
                return;
            }
            
            
            var userId = parseInt(avatar.attr('src').match(/users\/(\d+)/)[1]),
                title = userBlock.find('.attribution-user a').first();

            // if not followed, remove mark if has one
            if (followers.indexOf(userId) == -1)
            {
                userBlock.removeClass('us-follows-you');
                userBlock.find('.us-follows-you-mark').remove();
                continue;
            }

            // if already marked as follower do nothing until all fetched
            if (userBlock.hasClass('us-follows-you'))
            {
                if (mainIntervalStopped)
                {
                    userBlock.find('.us-follows-you-mark').addClass('us-fetch-ready');
                }
                continue;
            }

            // set mark of follower
            userBlock.addClass('us-follows-you');
            title.html('<span title="Follows you" class="us-follows-you-mark'+(mainIntervalStopped ? ' us-fetch-ready' : '')+'">✓ </span>'+title.html());
        }
    }
    
    function paintOnCommentsPage()
    {
        var dribbbles = $('ol.comments > li');
        
        if (dribbbles.length == 0)
        {
            return;
        }

        for (var i = 0; i < dribbbles.length; i++)
        {
            var userBlock = $(dribbbles[i]),
                userId = parseInt(userBlock.attr('data-user-id')),
                title = userBlock.find('h2');

            // if not followed, remove mark if has one
            if (followers.indexOf(userId) == -1)
            {
                userBlock.removeClass('us-follows-you');
                userBlock.find('.us-follows-you-mark').remove();
                continue;
            }

            // if already marked as follower do nothing until all fetched
            if (userBlock.hasClass('us-follows-you'))
            {
                if (mainIntervalStopped)
                {
                    userBlock.find('.us-follows-you-mark').addClass('us-fetch-ready');
                }
                continue;
            }

            // set mark of follower
            userBlock.addClass('us-follows-you');
            title.html('<span title="Follows you" class="us-follows-you-mark'+(mainIntervalStopped ? ' us-fetch-ready' : '')+'">✓ </span>'+title.html());
        }
    }
    
    function paintOnShotPage()
    {
        var userBlock = $('.user');
        
        if (userBlock.length == 0)
        {
            return;
        }

        var userId = parseInt($('.user > a[rel=contact] img.photo').attr('src').replace(/.*users\/(\d+).*/, '$1')),
            title = userBlock.find('.shot-byline-user a');

        // if not followed, remove mark if has one
        if (followers.indexOf(userId) == -1)
        {
            userBlock.removeClass('us-follows-you');
            userBlock.find('.us-follows-you-mark').remove();
            return;
        }

        // if already marked as follower do nothing until all fetched
        if (userBlock.hasClass('us-follows-you'))
        {
            if (mainIntervalStopped)
            {
                userBlock.find('.us-follows-you-mark').addClass('us-fetch-ready');
            }
            return;
        }

        // set mark of follower
        userBlock.addClass('us-follows-you');
        title.html('<span title="Follows you" class="us-follows-you-mark'+(mainIntervalStopped ? ' us-fetch-ready' : '')+'">✓ </span>'+title.html());
    }
    
    function paintOnUserPage()
    {
        var userBlock = $('.profile-head');
        
        if (userBlock.length == 0)
        {
            return;
        }

        var avatar = $($('.profile-head img.photo')[0]);
        
        // avatar is not loaded yet
        if (!avatar || !avatar.attr('src'))
        {
            return;
        }
        
        var userId = parseInt(avatar.attr('src').replace(/.*users\/(\d+).*/, '$1')),
            title = userBlock.find('.profile-name a');

        // if not followed, remove mark if has one
        if (followers.indexOf(userId) == -1)
        {
            userBlock.removeClass('us-follows-you');
            userBlock.find('.us-follows-you-mark').remove();
            return;
        }

        // if already marked as follower do nothing until all fetched
        if (userBlock.hasClass('us-follows-you'))
        {
            if (mainIntervalStopped)
            {
                userBlock.find('.us-follows-you-mark').addClass('us-fetch-ready');
            }
            return;
        }

        // set mark of follower
        userBlock.addClass('us-follows-you');
        title.html('<span title="Follows you" class="us-follows-you-mark'+(mainIntervalStopped ? ' us-fetch-ready' : '')+'">✓ </span>'+title.html());
    }
})();