Twitter atSuggest (Fluid / Webkit)

By Nate Eagle Last update Jan 30, 2010 — Installed 82 times.

There are 3 previous versions of this script.

// ==UserScript==
// @name		Twitter atSuggest (for Fluid / Webkit)
// @namespace		twitter_atsuggest
// @author		http://nateeagle.com
// @homepage		http://github.com/neagle/atSuggest
// @include		http://twitter.com/*
// ==/UserScript==

(function(){

var REGEX = /^@/;

function onReady(){
    // console.debug('Loaded!');
    loadTwitterUserNames(initializeEvents);
}

var Cookie = { 
    load: function() {
        Cookie.cookies = {}; 
        var rawCookies = document.cookie.split('; ');
        jQuery(rawCookies).each(function(i, item){
            var thisCookie = item.split('=');
            Cookie.cookies[thisCookie[0]] = thisCookie[1];
        }); 
    },  
    get: function(key) {
        return Cookie.cookies[key];
    },  
    set: function(key, value, expires) {
        var expires = expires || Cookie.expiry(1*24*60*60*1000);
        Cookie.cookies[key] = value;
        var setCookie = []; 
        setCookie.push(key + '=' + value);
        setCookie.push('expires=' + expires);
        setCookie.push('path=/');
        document.cookie = setCookie.join('; ');
    },  
    del: function(key) {
        Cookie.set(key, '', Cookie.expiry(-10000));
        delete Cookie.cookies[key];
    },  
    expiry: function(delta) {
        var now = new Date().getTime();
        var expires = new Date(now + delta); 
        return expires.toGMTString();
    }   
};

Cookie.load();

function uniquify(myArray) {
    result = []; 
    for(var i=myArray.length-1;i>=0;i--) {
        var val = myArray[i];
        if (result.indexOf(val) == -1) {
            result.push(val);
        }   
    }   
    return result.reverse();
}

function loadTwitterUserNames(callback) {
	// console.debug('Load Twitter User Names...');
    var TWITTER_USERNAMES = [];
    function loadFromAPI(cursorPosition, callback) {
		// console.debug('Loading from API...');
        var isFirstRequest = cursorPosition==-1;
        var remainingNames;
        // Get usernames
        jQuery.getJSON('/statuses/friends.json?lite=true&cursor='+cursorPosition,
            function(data) {
                remainingNames = data.next_cursor;
                jQuery.each(data.users, function(i, item) {
                    TWITTER_USERNAMES.push(this.screen_name);
                });//, completeTwitterUserNames(cursorPosition, remainingNames, callback));
                if (remainingNames == 0) {
                    TWITTER_USERNAMES = uniquify(TWITTER_USERNAMES);
                    TWITTER_USERNAMES.sort();
                    Cookie.set('TwitterAutoComplete', TWITTER_USERNAMES.toString());
                    callback(TWITTER_USERNAMES);
                } else {
                   cursorPosition--;
                   loadFromAPI(cursorPosition, callback);
                }
            });
    }
    function loadFromCookie(callback) {
		// console.debug('Loading from Cookie...');
        return Cookie.get('TwitterAutoComplete').split(',');
    }
    var cookieNames = Cookie.get('TwitterAutoComplete');
    if (cookieNames) {
        callback(cookieNames.split(','));
    } else {
        loadFromAPI(-1, callback);
    }
}

function initializeEvents(names) {
	// console.debug('Initialize Events...');
    var statusInput = jQuery('#status');
	var nameAppend = '';
	// If user hits enter and there are suggested names displayed, complete with the first name displayed
	statusInput.bind('keypress', function(e) {
		if(e.keyCode == 13 && jQuery('#suggestedNames').length > 0) {
			nameAppend = ' ';
			jQuery('#suggestedNames li:first').click();
			nameAppend = '';
			return false;
		}	
		if((e.charCode == 39 || e.charCode == 58 || e.charCode == 59 || e.charCode == 33 || e.charCode == 44 || e.charCode == 45 || e.charCode == 46 || e.charCode == 63) && jQuery('#suggestedNames').length > 0) {
			jQuery('#suggestedNames li:first').click();
		}
	});
	// Attach autocompletion actions to keyup event
    statusInput.bind('keyup', function(e) {
        var ta = e.currentTarget;
        var taPreceedingWords = ta.value.slice(0, ta.selectionStart).split(' ');
        var taPreceedingWord = taPreceedingWords[taPreceedingWords.length - 1];
        if (taPreceedingWord.length > 1) {
            if(taPreceedingWord.match(REGEX)) {
                autoComplete(taPreceedingWord, ta.selectionStart, names);
                var cursorLocation = ta.selectionStart;
                jQuery('#suggestedNames li').click(function(){
                    var remainingName = jQuery(this).text();
                    remainingName = remainingName.substring(taPreceedingWord.length - 1);
                    ta.value = ta.value.substring(0, cursorLocation) + remainingName + nameAppend + ta.value.substring(cursorLocation);
                    cursorLocation += remainingName.length + 1;
                    statusInput.focus().attr({'selectionStart' : cursorLocation, 'selectionEnd' : cursorLocation});
                    removePanel();
                });
            } else {
                removePanel();
            }

        } else {
            removePanel();
        }
    });
}

function autoComplete(word, index, names) {
    var name = word.substring(1);
    var r = new RegExp('^'+name, 'i');
    var matchList = [];
    jQuery.each(names, function(i, n){
        if(n.match(r)) {
			 matchList.push(n);
        }
    });
    if(matchList.length > 0) {
        showNames(matchList);
    } else {
        removePanel();
    }

}

function showNames(names) {
    // Styles for the AutoComplete Panel
    function stylePanel() {
        jQuery('#suggestedNames').css({
                'background-color' : '#fff',
                'border-right' : '1px solid #aaa',
                'border-bottom' : '1px solid #aaa',
                'border-left' : '1px solid #aaa',
                'cursor' : 'pointer',
                'left' : '76px',
                'margin-top' : '-1px',
                'padding' : '10px',
                'position' : 'absolute',
                'z-index' : '9999'
        });
    }
    var statusInput = jQuery('#status');
    if (jQuery('#suggestedNames').length == 0) {
        statusInput.after('<ul id="suggestedNames"></ul>');
        stylePanel();
    }
    var suggestedNames = jQuery('#suggestedNames');
    suggestedNames.empty();
    jQuery(names).each(function(i, n){
        suggestedNames.append('<li>' + n + '</li>');
    });
}

function removePanel() {
    jQuery('#suggestedNames').remove();
}

jQuery(document).ready(function() {
	onReady();
});

})();