0

Take two :) I have a jquery's autocomplete texbox and, upon a click of a button, I need to check if the value entered has come from the autocomplete or is it a completely new value.

The problems is that 'cache' is some sort of an array of JSON objects, but to be able to use if ( input in cache ) { ... } I need to convert it to a simple javascript array. What would be the best way to do that?

P.S. FireBug says 'cache=[object Object]'

//////////////////////////////////////////// autocomplete code //////////////////
    var cache = {},
        lastXhr;
    $( "#inputV" ).autocomplete({
        minLength: 2,
        source: function( request, response ) {
            var term = request.term;
            if ( term in cache ) {
                response( cache[ term ] );
                return;
            }

            lastXhr = $.getJSON( "search.php", request, function( data, status, xhr ) {
                cache[ term ] = data;
                if ( xhr === lastXhr ) {
                    response( data );
                }
            });
        }
    });


////////////////////////// check if input comes from autocomplete  //////////////////
    $('#btn_check').click(function()        {

        var input = $("#inputV").val();
        alert(input);

        console.log('cache='+cache); 
        /// FireBug says 'cache=[object Object]'

        if ( input in cache ) 
            {
                alert("yes");
             }  
            else
            {
                alert("no");
            }   
    });

Here's that a response looks like.

[
    {
        "id": "Podiceps nigricollis",
        "label": "Black-necked Grebe",
        "value": "Black-necked Grebe"
    },
    {
        "id": "Nycticorax nycticorax",
        "label": "Black-crowned Night Heron",
        "value": "Black-crowned Night Heron"
    },
    {
        "id": "Tetrao tetrix",
        "label": "Black Grouse",
        "value": "Black Grouse"
    },
    {
        "id": "Limosa limosa",
        "label": "Black-tailed Godwit",
        "value": "Black-tailed Godwit"
    },
    {
            "id": "Chlidonias niger",
        "label": "Black Tern",
        "value": "Black Tern"
    },
    {
        "id": "Larus marinus",
        "label": "Great Black-backed Gull",
        "value": "Great Black-backed Gull"
    },
    {
        "id": "Larus fuscus",
        "label": "Lesser Black-backed Gull",
        "value": "Lesser Black-backed Gull"
    },
    {
        "id": "Larus ridibundus",
        "label": "Black-headed Gull",
        "value": "Black-headed Gull"
    },
    {
        "id": "Turdus merula",
        "label": "Common Blackbird",
        "value": "Common Blackbird"
    },
    {
        "id": "Sylvia atricapilla",
        "label": "Blackcap",
        "value": "Blackcap"
    },
    {
        "id": "Rissa tridactyla",
        "label": "Black-legged Kittiwake",
        "value": "Black-legged Kittiwake"
    },
    {
        "id": "Aegypius monachus",
        "label": "Eurasian Black Vulture",
        "value": "Eurasian Black Vulture"
    }
]
5
  • "The problems is that 'cache' is some sort of an array of JSON objects" JavaScript objects. JSON is a notation. Commented May 31, 2011 at 10:26
  • You defined it as object var cache = {}. I don't understand your problem... You should provide an example of cache and what you want to transform it into. I think if ( input in cache ) will work fine. Commented May 31, 2011 at 10:27
  • if(x in y) would work if x is a string and y is an array of strings. yet in my case x is a string, but y is an array of JavaScript objects. Therefor I first need to convert this object array into a string array. Commented May 31, 2011 at 10:31
  • 1
    You have a misunderstanding of the in operator. It does not test whether an element is in an array, it tests whether a property is set on an object: developer.mozilla.org/en/JavaScript/Reference/Operators/Special/… . If you use it with an array, you test whether a particular index is set. Commented May 31, 2011 at 10:37
  • Formatting is really important in questions. Posting the JSON as a wall of undifferentiated text isn't ideal. I've taken it, run it through jsonlint.com to format it, and then used the "{}" button in the StackOverflow editor to mark the result as code so it's more readable. Commented May 31, 2011 at 10:45

2 Answers 2

2

(Replacement answer, I hadn't meant the last one to be a CW.)

The problems is that 'cache' is some sort of an array of JSON objects

Actually, it's not an array. It's an object. (It's created via var cache = {};, which is how we can tell.)

...but to be able to use if ( input in cache ) { ... } I need to convert it to a simple javascript array.

Actually, no. The in operator in this context tests to see if an object contains a property with the name you give it. Example:

var obj = {foo: 1};  // An object with a property called "foo"
alert('foo' in obj); // alerts true, `obj` has a "foo" property
alert('bar' in obj); // alerts false, there is no "bar" property in `obj`

Note that the left-hand side of the in operator must be a string (it can be a literal, as above, or any expression that results in a string, such as a variable reference).

The code in your click handler is taking the value of the "inputV" field and seeing if that value is the name of a property in the cache object.

You probably want to check if it's the value of one of the properties of the cache object. If so:

$('#btn_check').click(function()        {

    var input = $("#inputV").val();
    var found, propName;

    alert(input);

    console.log('cache='+cache); 
    /// FireBug says 'cache=[object Object]'

    found = false;
    for (propName in cache ) {
        if (cache[propName] == input) {
            found = true;
            break;
        }
    }
    alert(found);
});

Since we know cache is a boring old object (from the fact it's created with var cache = {};), we can pretty safely use a raw for..in loop as above. But if you wanted to be more careful, you would use hasOwnProperty to make sure that you only checked propeties that cache has its own copy of (as opposed to ones it inherits from its prototype):

    for (propName in cache ) {
        if (cache.hasOwnProperty(propName) && cache[propName] == input) {
            found = true;
            break;
        }
    }

Again, though, it's not really necessary in this case, because we know that cache is a plain object, and barring someone doing something really silly like extending Object.prototype (which Thou Shalt Not Do), all of its enumerable properties (the things that for..in enumerates) are its own properties.

Sign up to request clarification or add additional context in comments.

4 Comments

I would say the OP's code should work as expected. The search term is set as property of the cache object, and if(input in cache) tests whether the term was searched before...
@Felix: Could be. :-) I honestly couldn't tell. I started out just addressing the misconception, but then thought perhaps the value-vs-name thing might help.
Hmm... the concept looks right, but its still not working! :/ For example I start typing "black", it returns me "[ { "id": "Podiceps nigricollis", "label": "Black-necked Grebe", "value": "Black-necked Grebe" }", I click on the "Black-necked Grebe" and when it test it against this cache, I still get a false...
@Roger: You'll have to walk through the code with a debugger (I think you said you have Firebug, that'd work) and look at the actual value, what's in cache, etc.
0

It's hard to tell without seeing what the JSON looks like. It's possible that you could substitute if ( input in cache ) with if(cache.hasOwnProperty(input)) and not bother converting it to an array, but it depends what the cache object contains.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.