Module to support autocomplete for movie tags I've just completed a JavaScript module and I've got a strong feeling that this is borderline spaghetti code. My task was to build a tagging form which adds selected tags to hidden outputs to be sent to a server.

var tags = [];
var createdTags;
var addedTags = [];
var isNewTag, selectedTag, i;

$("#created-tags").attr("value", "[]");

$.ajax({

    type: "GET",
    cache: false,
    dataType: 'json',
    url: "/portal/index.php/movies/get_tags",
    success:
        function(response) {
            $("#tags-typealong").autocomplete({
                source: response,
                minLength: 1,
                select: function (event, ui) {
                    event.preventDefault();             
                    selectedTag = ui.item;
                    //tags = current tags
                    tags = $.parseJSON($('#tags').attr('value'));
                    isNewTag = true;
                    //is tag already added?
                    for(i = 0; i &lt; tags.length; i++) {
                        if(selectedTag.id == tags[i].id)
                            isNewTag = false;
                    }
                    //update addedTags if new
                    if(isNewTag) {
                        tags.push(selectedTag);
                        addedTags.push(selectedTag.id);
                        add_tag_render(selectedTag.name);
                    }
                    //update dom for tag_form.js
                    $("#tags").attr("value", JSON.stringify(tags));
                    $("#added-tags").attr("value", JSON.stringify(addedTags));
                    $("#tags-typealong").val('');
                }

            }).data( "autocomplete" )._renderItem = function( ul, item ) {
                return $("&lt;li&gt;&lt;/li&gt;")
                    .data( "item.autocomplete", item )
                    .append( '&lt;a&gt;' + item.name  + '&lt;/a&gt;' )
                    .appendTo(ul);
            }
        }
});

$("#tags-typealong").keyup(function (event) {

    var isNew = true;

    if(event.keyCode == 32) {
        //get updated tag selections
        var tagName = $(this).val();
        tagName = tagName.slice(0, -1);
        createdTags = $.parseJSON($('#created-tags').attr('value'));
        tags = $.parseJSON($('#tags').attr('value'));
        //check tags from db
        for(i = 0; i &lt; tags.length; i++) {
            if(tags[i].name == tagName)
                isNew = false;
        }
        //check existing created tags
        for(i = 0; i &lt; createdTags.length; i++) {
            if(createdTags[i] == tagName)
                isNew = false;
        }
        if(isNew) {
            add_tag_render(tagName);
            createdTags.push(tagName);
            $("#created-tags").attr("value", JSON.stringify(createdTags));
        }
        $("#tags-typealong").val('');
        //TODO!
        //is tagname in db already?

    }

});

function add_tag_render(tagName) {

    $(".tag-container").append('&lt;div class="selected-tag"&gt;&lt;div class="selected-tag-name"&gt;' + tagName + '&lt;/div&gt;&lt;div class="remove-tag"&gt;&lt;/div&gt;&lt;/div&gt;');
    $("#tags-typealong").appendTo(".tag-container");
    $("#tags-typealong").focus();

}
.attr('value') is bad. Always. You should use .val() instead.
var i; can go into the callback function instead of whatever scope you are in at the very beginning.