jquery how to pass an array to a function?

JavaScript and client side scripting.

Moderator: General Moderators

hybris
Forum Contributor
Posts: 172
Joined: Wed Sep 25, 2013 4:09 am

Re: jquery how to pass an array to a function?

Post by hybris »

Hmm I can't get the function to set the current list when pressing enter... also for some reason everytime i press enter it automatically add another input field (ingredient: (inputfield) remove) just like when i click the add new ingredient button.

I don't know why it does that when i have one of the inputfields in focus and added e.preventDefault() on keypress enter... (I would maybe understand why it did so if the add new ingredient button was in focus when pressing enter but it is not)..


I still use the ean autocomplete function. I have 5 eans starting with 7 and 1 starting with 8.

Now the program behaves like this:

* if i type something not in db (I dont get a list suggestion) and hit enter it just clear the input field and add a new row (which it shouldnt add).

* if i type 7 it display list of eans starting with 7 and if i hit enter it set the inputbox to the first ean (say 7654) in the list which it should. but adds another input field which it shouldnt.

* if i click on the next inputfield and type in 8 it display 8989 in the list which it should but when i press enter it sets the first ean 7654 again instead of 8989. and add another row which it shouldnt..

So how do i do to update the list because it show the correct list when i type in the number but always sets from the first list created..

if i reload page and press 8 in the first field and hit enter it set 8989 as it should.
if i in the next field press 7 it shows all ean starting with 7 but when i hit enter it sets 8989... so it always set the first list it loads?

Code: Select all

$(function() {
    
    
    /* Function to add or remove ingredient or allergen input fields*/
    
        var i = 1;
        var j = 1;
        var k = 2; // gives a unique ID to each added field (does not decrement as i and j)
        $('#add_ingredient').click(function() {
               $('#Ingredient_table').append('<tr><td><p>Ingredient</p></td><td><div class="input_container"><input type="text"  size="20" name="ingredient[]" value="" placeholder="Input Value" /><ul id="ingredient_list_id_'+k+'" tabindex="-1"></ul></div></td><td><a href="#" class="remove_field"><p style="font-size:50%;">Remove</p></a></td></tr>');
                i++; k++;
                return false;
        });
        
        $('#Ingredient_table').on("click",".remove_field",function(e){
            e.preventDefault();    
            $(this).parents('tr').remove();  //parents could be switched with closest
            i--;
        })
        
        $('#add_allergen').click(function() {
               $('#Allergen_table').append('<tr><td><p>Allergen</p></td><td><input type="text" id="allergenid_'+k+'" size="20" name="allergen['+k+']" value="'+k+'" placeholder="Input Value" /></td><td><a href="#" class="remove_field"><p style="font-size:50%;">Remove</p></a></td></tr>');
                j++; k++;
                return false;
        });
        
        $('#Allergen_table').on("click",".remove_field",function(e){
            e.preventDefault();    
            $(this).parents('tr').remove();  //parents could be switched with closest
            j--;
        })
        
        $('#ingredient_wrapper').on("keyup", ".input_container", function(e){
            if(e.which == 13) {
             e.preventDefault();          
             //$(this).children().val($('li').first().text());
             $(this).children().val($('li').first().text());
             $(this).children("ul").hide();
             return;
            }
            
            var thislist = $(this).children("ul");
            var min_length = 0;    
            var keyword = $(this).children().val();
            if (keyword.length >= min_length) {
        		$.ajax({
        			url: 'ajax_php/ajax_browserefresh.php',
        			type: 'POST',
        			data: {keyword:keyword},
        			success:function(data){
        			    var result = JSON.parse(data);
        			    var $nodes = $([]);
        			    
                        $.each(result, function(key, value) {
                            var $li = $("<li></li>").text(value.ean);
                            $li.click(function() {
                                set_item_in(thislist, value.ean);
                            }); 
                            $nodes=$nodes.add($li); 
                        });
                        
                        if (result[0] == -1) {
                            thislist.hide();
                        } else {
                            thislist.empty().append($nodes).show();    
                        }
        			}                                       /* Close on sucess */
        		});                                         /* Close ajax      */
    	    } else {
    		    thislist.hide();
    	    }
    	    
    	    
        }) // end of on keyup
        
        
        
});

function set_item_in(elem, item) {
   // $("#"+elem).val(item);   /*For inputboxes textareas and so on else text*/
    //elem.hide();
    //elem.text(item);
    elem.parent().children().val(item);
    elem.hide();
}
EDIT
I fixed the add row thing by prevent default on keydown instead.. but I still can't get it to set the correct list instead of the first list it loads....
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: jquery how to pass an array to a function?

Post by requinix »

Okay, this sort of thing I know.

Fortunately you only have one field to add/remove at a time. That's easy: with more than one you have to coordinate information so that all pieces arrive at PHP in sync with each other.

1. Name the inputs with array syntax but don't bother with a key. Just "[]".
2. Put each input and remove button somewhere within the same parent that's unique to the pair: typically

Code: Select all

<tr><td>(input)></td><td>(remove)</td></tr> <!-- same parent tr -->

Code: Select all

<li>(input) (remove)</li> <!-- same parent li -->
3. Make the remove button remove the entire parent (tr or li).
4. Make the add button add a new blank entry to the parent's parent (table or ul/ol).

Here's an example showing how I deal with dynamically adding and removing inputs:

Code: Select all

<ul id="ingredients">
	<li class="template"><input type="text" name="ingredient[]" placeholder="Ingredient"> <button type="button">Remove</button></li>
</ul>
<button id="#ingredients-add" type="button">Add Ingredient</button>
Putting the template in the HTML is really convenient.

Code: Select all

$(function() {
	var $ingredients = $("#ingredients");
	var $template = $("#ingredients > .template").remove(); // remove the template
	$template.removeClass("template");

	// if the list is empty then add the template back in
	if ($ingredients.children().length == 0) {
		$ingredients.append($template.clone());
	}

	// add the template
	$("#ingredients-add").on("click", function() {
		$ingredients.append($template.clone());
	});
	// remove the input
	$ingredients.on("click", "> li button", function() {
		$(this).closest("li").remove();
	});
});
Untested, of course.

What you've done... I'm not sure but there's a lot of code and it looks fairly complicated.
hybris
Forum Contributor
Posts: 172
Joined: Wed Sep 25, 2013 4:09 am

Re: jquery how to pass an array to a function?

Post by hybris »

I think you answered some previous question that I solved already.. I just needed some more lines of code to achieve it..

I have it working adding and removing fields as it is supposed to, I also have it working in each field i add when i type something i get the correct autocomplete list to show up.

If I click with the mouse on an item in the autocomplete list it sets the inputfield with the correct value.

the only remaining thing i have to fix is that if i try to set the first list item when pressing ENTER it sets the first value of the first autocomplete list I loaded and not the current list Im watching..
requinix wrote:What you've done... I'm not sure but there's a lot of code and it looks fairly complicated.
Coming from you I <b><u>really</u></b> take that as a compliment Hahaha
I almost don't know what I did myself but after lots of trial and error and lots of cursing I got it all to work.. almost anyway... I guess the next step will be to polish the code... atm its more like bruteforcing haha

I like your template solution, very nice code.

Edit:

its only this part im having trouble with
$('#ingredient_wrapper').on("keyup", ".input_container", function(e){
if(e.which == 13) {
e.preventDefault();
$(this).children().val($('li').first().text());
$(this).children("ul").hide();
return;
}
or more specific: $('li').first().text()
this gives me the first $('li') item in the first list I load on the page but I need to get the first $('li') item in the current list...


EDIT
I need something like this:
var tmp = $(this).children("ul").$('li').first().text();
$(this).children().val(tmp);

Edit: Ok I almost found it ... i think..

var tmp = $(this).children("ul").first().text();
$(this).children().val(tmp);

this returns the entire list not just the first li item


I'd need something like
var tmp = $(this).children("ul").filter('li').first().text();
or
var tmp = $(this).children("ul").$('li').first().text();
but its not working.. i need to find the first $('li').text() in $(this).children("ul")
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: jquery how to pass an array to a function?

Post by requinix »

In that callback, this will be the #ingredient_wrapper. If you want to start from the .input_container that [contains the element that] triggered the event then

Code: Select all

var $container = $(e.target /* the input */).closest(".input_container");
Then you can navigate from there.
hybris
Forum Contributor
Posts: 172
Joined: Wed Sep 25, 2013 4:09 am

Re: jquery how to pass an array to a function?

Post by hybris »

OMFG I got it to work.. had to involve the grandchildren :)

tmp = $(this).children("ul").children("li").first().text();

Damn, I'm good ;)
I even got a comment my code looks complicated haha, I think that is the first time I hear that (yeah, i know it's probably not a good thing but as someone wrote before me: if it was hard to write it should be hard to read :D)

requinix wrote:In that callback, this will be the #ingredient_wrapper. If you want to start from the .input_container that [contains the element that] triggered the event then

Code: Select all

var $container = $(e.target /* the input */).closest(".input_container");
Then you can navigate from there.
Just saw you answered. Yeah thats what I do with the $(this).children("ul") I go to the wrapper and select the ul but I couldnt figure out how to get to the first li from there but i just repeated to find the li children of ul and then use first().


You are an excellent teacher, before I started this thread I never did anything with jquery or javascript before this and now I can do most things i like even if i need some trial and error first the code is pretty ugly from time to time

I went from
alert("Hello, World!");
to create a form with buttons to add label, inputbox, and remove rows in a table where each inputfield get its own autocomplete list that you can navigate either by mouse or arrowkeys + enter that recieve its information through ajax (whitch I thought was a brand for cleaning liquid before I started this thread)...

I'd say atleast for me (43 yo ... you know how it is to learn old dogs to sit...) its beyond fantastic accomplishment to learn all that in such short time (I can only code for a few hours now and then so really from the thread start to now I haven't had many hours coding..). So hats of to my teacher!!!
Post Reply