Jump to content

for loop...array


jimfog

Recommended Posts

I am using this code to loop through an array:

var missing = [];               {var fields = ['address', 'city', 'municipality','url'];                                   for (var i = 0; i < fields.length; i++) {                 var f = fields[i];                 if (data[f] === false) {                    missing.push(f);                 }             }                         if (missing.length > 0) {                $('#adrserror').text('You have to fill: ' + missing.join(', '));                      }                 }

I want to make the loop stop at the 3rd array item...namely municipality.

What this code does is that it checks if the user has submitted some input fields in a form(the labels of the inputs are represented by the array items ). Nonetheless the message which informs the user about not submitting data regards only the first 3 elements of the array...for the 4th element(url) I want to show a different message(a message about the validity of the supplied url).

 

That is the reason I want to know how to loop till element 3.

Link to comment
Share on other sites

break should do it.

Link to comment
Share on other sites

I just started reading the "Patterns" book and it suggests this approach, especially for DOM-related arrays...

for (var i=0, len=fields.length ; i < len ; i++){if( i < 3){//test first three items}else{// test url}}
Edited by davej
Link to comment
Share on other sites

 

I just started reading the "Patterns" book and it suggests this approach, especially for DOM-related arrays...

for (var i=0, var len=fields.length ; i < len ; i++){if( i < 3){//test first three items}else{// test url}}

 

I am not so sure about that, I am not saying it is wrong, I am just saying that maybe it is not for my case.

 

In my case the user is presented with 4 input fields, the 3 are obligatory(address,city,municipality) and the one is optional(url).

 

So, it is not that the user has to fill these 3 fields OR the url field(something I think the code you present tries to address).

 

Here we have 2 scenarios:

The user fills the 3 obligatory fields or the 3 obligatory fields AND the url.

 

I hope that I made my point.

 

NONETHELESS MAYBE YOUR CODE DOES THE JOB...WITH SLIGHT MODIFICATIONS.

Edited by jimfog
Link to comment
Share on other sites

 

...for the 4th element(url) I want to show a different message(a message about the validity of the supplied url).

 

This would go into the else area.

 

--EDIT--

 

Oops, I did have an extra var in there that shouldn't be in there... it should be...

 

for (var i=0, len=fields.length ; i<len ; i++) {

Edited by davej
Link to comment
Share on other sites

what you could do is write up an inputvalidator object and just run something like input.validate() command per input element.

	var missing = [];	function input(id_name,check){                //this check is just so you don't have to say "new input()" everytime you                 // want to make a new input class.		if (this instanceof input){			this.id =id_name;			this.field = $("input#"+this.id);                        //if a validating function was passed, set it to validate, otherwise                        // use a default validate function that does nothing			this.validate = (typeof check=="function")					?check					:function(){						//default validate does nothing and returns self						return this					};			return this;		}else{			return new input(id_name,check);		}	};		var requiredcheck = function (){		if(data[this.id] === false)			missing.push(this.id);		return this;	};	var emailcheck = function(){		//Add code to validate the url	};	var fields = [input('address',      requiredcheck),                      input('city',         requiredcheck),                       input('municipality', requiredcheck),                      input('url',          emailcheck)];	for( var inp in fields){		fields[inp].validate();	}	if (missing.length > 0) {		$('#adrserror').text('You have to fill: ' + missing.join(', '));	} 

this way the validate() function worries about all what to do to which elements and you don't have to put in any fancy, inflexible logic like make sure to only require the first 3 elements. (what if later on you add 20 more inputs and they aren't all grouped together by how you want to work on them?). properly encapsulating the logic lets you avoid tons of if/swtich statements (your example was comparatively simple so its nowhere near as bad and it can get.

 

Link to comment
Share on other sites

what you could do is write up an inputvalidator object and just run something like input.validate() command per input element.

	var missing = [];	function input(id_name,check){                //this check is just so you don't have to say "new input()" everytime you                 // want to make a new input class.		if (this instanceof input){			this.id =id_name;			this.field = $("input#"+this.id);                        //if a validating function was passed, set it to validate, otherwise                        // use a default validate function that does nothing			this.validate = (typeof check=="function")					?check					:function(){						//default validate does nothing and returns self						return this					};			return this;		}else{			return new input(id_name,check);		}	};		var requiredcheck = function (){		if(data[this.id] === false)			missing.push(this.id);		return this;	};	var emailcheck = function(){		//Add code to validate the url	};	var fields = [input('address',      requiredcheck),                      input('city',         requiredcheck),                       input('municipality', requiredcheck),                      input('url',          emailcheck)];	for( var inp in fields){		fields[inp].validate();	}	if (missing.length > 0) {		$('#adrserror').text('You have to fill: ' + missing.join(', '));	} 

this way the validate() function worries about all what to do to which elements and you don't have to put in any fancy, inflexible logic like make sure to only require the first 3 elements. (what if later on you add 20 more inputs and they aren't all grouped together by how you want to work on them?). properly encapsulating the logic lets you avoid tons of if/swtich statements (your example was comparatively simple so its nowhere near as bad and it can get.

 

 

Your code seems good(I say "seems" because I am not a very experienced js developer to say for certain "this code is bad or good" ), I just want to point out that I am not concerned about client-side validation here(I have left that to the jquery validate plugin).

 

I am trying to write code here that checks the results sent for server-side validation-with ajax:

 $.ajax({          type: "POST",          dataType:"json",          url: "adrsajax.php",          data: {"address":address,"city":city,"municipality":municipality,"url":url},             success:function(data){                     .....code for checking..... 
Link to comment
Share on other sites

That seems like an interesting idea. You don't bother with duplicate client validation code. You just let the server-code do it thru an Ajax exchange.

 

--EDIT--

 

Except maybe that's not what you're doing?

 

I'm supposing that you sent an array of field names and an array of input data and you got back an associative array of booleans. Then you step through the array of booleans and construct an array of error messages. Then you display the array of error messages, or you display a success message.

Edited by davej
Link to comment
Share on other sites

my code is just as good other suggestions. but each suggestion has their tradeoffs. whenever I code, I usually try to put some degree of decoupling into them. its simply in my nature since I'm a software engineer. decoupling, encapsulation, composition, inheritance, etc. are all just coding principals that provide ways to make certain code more flexible and easier to add to. no code can be 100% decoupled,encapsulated, etc because at some point one variable must be able to interact with another. on the other hand it can't be 0% because its no use that all your strings will always be "Hello world" and nothing else.

 

its like getting a new computer.

1)other suggestions are akin simply buying a new computer:

the process is simple, quick, and straightforward.

but you don't have full control of what your computer starts with.

 

2)my suggestion was more akin to building a custom computer yourself:

you have a lot more control in what goes into your new computer.

But the process is slightly more complex and you have to do more to get the job done.

 

either option has their pros and cons,but both get the job done. if you have no plans to expand/change on this ajax checking (if there's only one place that will make this specific ajax call) then the suggestions most others have provided is more than sufficient (and quicker). my suggestion provides a sort of blueprint if you plan to expand on this later, making it easier to add logic.

Link to comment
Share on other sites

my code is just as good other suggestions. but each suggestion has their tradeoffs. whenever I code, I usually try to put some degree of decoupling into them. its simply in my nature since I'm a software engineer. decoupling, encapsulation, composition, inheritance, etc. are all just coding principals that provide ways to make certain code more flexible and easier to add to. no code can be 100% decoupled,encapsulated, etc because at some point one variable must be able to interact with another. on the other hand it can't be 0% because its no use that all your strings will always be "Hello world" and nothing else.

 

its like getting a new computer.

1)other suggestions are akin simply buying a new computer:

the process is simple, quick, and straightforward.

but you don't have full control of what your computer starts with.

 

2)my suggestion was more akin to building a custom computer yourself:

you have a lot more control in what goes into your new computer.

But the process is slightly more complex and you have to do more to get the job done.

 

either option has their pros and cons,but both get the job done. if you have no plans to expand/change on this ajax checking (if there's only one place that will make this specific ajax call) then the suggestions most others have provided is more than sufficient (and quicker). my suggestion provides a sort of blueprint if you plan to expand on this later, making it easier to add logic.

 

Your views are really VERY interesting,software engineering in all its glory, I avoided doing your code in the first place cause it was many lines of it.

Instead I have concluded in this...which does not solve my problems completely,that being said...I might, after all use your code. I have not decided yet, I am still searching my options.

Here is the code to which I am referring above, as I mentioned it has problems:

   success:function(data){                      var missing = [];          if(url=='')          {            var fields = ['address', 'city', 'municipality'];            for (var i =0; i < fields.length; i++) {                              var f = fields[i];                if (data[f] === false) {                    missing.push(f);                }            }                       if (missing.length > 0) {                $('#adrserror').text('You have to fill in: ' + missing.join(', '));            }          }          else if(url!=='')          {           var fields = ['address', 'city', 'municipality','url'];           for (var i =0; i < fields.length; i++) {                   if(i<3)                   {                        var f = fields[i];                        if (data[f] === false) {                            missing.push(f);                        }                      if (missing.length > 0) {                        $('#adrserror').text('You have to fill in: ' + missing.join(', '));                    }                        }                   if(i>2)                   {                                  if (data.url === false) {                           missing.push('url');                              }                         if (missing.length > 0) {                         $('#adrserror').text('You have to fill in: ' + missing.join(', '));                         }                    }              }           }             },
Link to comment
Share on other sites

a lot of duplicated code....Try this:

$.ajax({	type: "POST",	dataType:"json",	url: "adrsajax.php",	data: {"address":address,"city":city,"municipality":municipality,"url":url},	success:function(){		var missing = [];		//validator constructor		var checkData = function checkData(name,check){			if(false === this instanceof checkData)				return new checkData(name,check);			this.name = name;                        this.value = data[value];			return (typeof check=="function")?check:function(){};		};		//validators		var requiredcheck = function (){			if(this.value == false)				missing.push(this.value);		};		var emailcheck = function(){                        if(this.value === false)                                missing.push(this.value);                };		//map data to validators		var fields = [checkData('address',      requiredcheck),				  checkData('city',         requiredcheck), 				  checkData('municipality', requiredcheck),				  checkData('url',          emailcheck)];		//running checks		for( var inp in fields)			fields[inp]();				//outputting results		if (missing.length > 0) 			$('#adrserror').text('You have to fill: ' + missing.join(', '));			}});

I didn't test it, but it should work. its roughly the same as my 1st code snippet, but alot of it has been minimized and this way can really cut down on your code duplication (notice that you can both define a function and run it inside a function.)

 

EDIT: needed to add a "this.name" property since the wrong thing would be pushed into missing. also I'm looking more at your code and the checks you're making for uri are more or less redundant. I mean

 

if(this.value === false)

 

is equivalent to everything you're going out of your way to do for the uri check. you're mixing === and !== with == and !=. and they are NOT the same thing. with this in mind I changed requiredCheck and emailCheak to reflect what I THINK you want (look closely at their code, they AREN'T identical).

 

could you clarify what type of check you want on uri

1.what values do you expect data.uri to have?

2.what do you want done if a specific thing is set to data.uri?)

Edited by Hadien
Link to comment
Share on other sites

I don't understand if he is running validator functions or merely reporting the results that were obtained from the server-side validation.

I am reporting the results obtained from server-side validation.

Link to comment
Share on other sites

 

 

could you clarify what type of check you want on uri

1.what values do you expect data.uri to have?

2.what do you want done if a specific thing is set to data.uri?)

 

1.data.url, when submitted to the server will pass from PHP url validate filters.

And these will return true(if the tests gets passed) or false.

 

2.Simply, if the server returns false, I want a message displayed saying "You did enter a correct URL", that's it

 

And one last thing...could you make your code more jquery friendly?

If that is possible of course?

Edited by jimfog
Link to comment
Share on other sites

I was going to propose the following, but I don't know where the variable url comes from...

success:function(data){           var fields = ['address','city','municipality','url'];           var missing = [];                      for (var i=0; i < fields.length; i++) {                                   if(i<3){                     var f = fields[i];                     if (data[f] === false) {                          missing.push(f);                     }                }                if(i==3 && url!='') { //?????????? url ??????????????                     if (data.url === false) {                          missing.push('url');                     }                }           }           if (missing.length > 0) {                $('#adrserror').text('You have to fill in: ' + missing.join(', '));           }      }
Link to comment
Share on other sites

 

I was going to propose the following, but I don't know where the variable url comes from...

success:function(data){           var fields = ['address','city','municipality','url'];           var missing = [];                      for (var i=0; i < fields.length; i++) {                                   if(i<3){                     var f = fields[i];                     if (data[f] === false) {                          missing.push(f);                     }                }                if(i==3 && url!='') { //?????????? url ??????????????                     if (data.url === false) {                          missing.push('url');                     }                }           }           if (missing.length > 0) {                $('#adrserror').text('You have to fill in: ' + missing.join(', '));           }      }

The above code(despite, at first it seems right) has some issues:

  • If for example address is not filled(and then the corresponding message appears)...and after that I choose to submit an invalid URL(at which point the server will emit FALSE)...the message that is displayed that informs the user about invalid URL...will overwrite the displayed message about the address.But that can be fixed easily I think.
  • The second and more serious problem is that if I choose to submit the URL first and then submit other data(addres,city etc)...the messages about the other data(if the server returns false) will not be displayed at all.

I made a fiddle with the HTML here http://jsfiddle.net/fiddlehunt/wFmNv/

Link to comment
Share on other sites

I am close in finding a solution(maybe). I will let you know soon...

It seems now that the code is OK, only some minor adjustments must be made so that when the user submits

an invalid url the message must be "You have submit an invalid url"

Edited by jimfog
Link to comment
Share on other sites

I couldn't get Ajax to work in JS fiddle so I merely faked the ajax call in my testing but I got the code to work just fine.

my code "was" jquery friendly, just buggy, I forgot to make the success callback show that it passes a value and that checkData needs to return "this" not the function... anywho here is what I have in success callback:

success:function(data){		data = {"address":false,"city":true,"municipality":false,"url":false};		var missing = [];		var validurl = false;		//validator constructor		var checkData = function checkData(name,check){            if(false === this instanceof checkData)                return new checkData(name,check);			this.name = name;			this.value = data[name];			this.validate = (typeof check=="function")?check:function(){};            return this;		};		//validators		var requiredcheck = function (){			if(this.value == false)				missing.push(this.name);		};		var emailcheck = function(){			validurl = (this.value ===false);						};		//map data to validators		var fields = [checkData('address',      requiredcheck),					  checkData('city',         requiredcheck), 					  checkData('municipality', requiredcheck),					  checkData('url',          emailcheck)];		//running checks		for( var inp in fields)			fields[inp].validate();                //clear previous error messages.		$('#adrserror>').remove()		//outputting results		if (missing.length > 0)			$('#adrserror').append('<p>You have to fill: ' + missing.join(', ')+"</p>");		if (validurl)			$('#adrserror').append("<p>You have submitted an invalid url</p>");}

I'm using .append() instead of .text() so that I could display the messages separately and in tags (I also changed adrserror from span to div, and removed the following br tag).

Link to comment
Share on other sites

The above code(despite, at first it seems right) has some issues:

  • If for example address is not filled(and then the corresponding message appears)...and after that I choose to submit an invalid URL(at which point the server will emit FALSE)...the message that is displayed that informs the user about invalid URL...will overwrite the displayed message about the address.But that can be fixed easily I think.
  • The second and more serious problem is that if I choose to submit the URL first and then submit other data(addres,city etc)...the messages about the other data(if the server returns false) will not be displayed at all.

 

When the user submits a form -- and the form is rejected -- then I would expect the valid fields of the form to be restored for the user to try again and perhaps the invalid or missing fields of the form to be highlighted. Since the form submittal here is via Ajax I can't see why the form would change anyway. If Ajax is not used then the server needs to use other means (such as session variables) to reload the form fields. I can't imagine the server is going to allow a form to be submitted in bits and pieces. It either receives a form that is accepted or it rejects the entire form and the user must correct the invalid or missing fields.

Edited by davej
Link to comment
Share on other sites

 

I'm using .append() instead of .text() so that I could display the messages separately and in tags (I also changed adrserror from span to div, and removed the following br tag).

I am going to have a deeper look at your code,even for learning purposes.

 

One question I have though is why you changed adrserror from being a span element to a div element?

Link to comment
Share on other sites

I wanted the error for the URL to be on a separate line from the other errors and a concise way to do that was to put each error in a block level element like <p> tags. Since it's a very bad idea to put block-level elements inside inline elements, like span, I changed the span (which is usually used to collectively format a some words in a paragraph, like bold or background colors) to a div (which is mainly used to hold a collection of elements, not text).I also try to avoid using the br tag when I can. Only time I would use it is if you want more than one new line after a group of text, like between this and the previous paragraph (depending on the forum, some put each paragraph in p tags and trim all whitespace, others just use br tags for newline, many others vary in-between). Block level elements always add a carriage return after themselves, removing the need to use br tags. Margins can further reduce it's need.jQuery has alot of power in playing with elements, and placing the errors inside tags allows more control if you want to add specific behavior or styling to each element you made. For example, since the first group of errors is required, you can give them specific styling to show that it's important. Using .text wouldn't give you the opportunity to add separate styling and events.The use of remove instead of just recalling .text or .html to overwrite stuff you put in adrserror is just habit I'd get into. Remove() also looks for and deletes event handlers that were attached to the deleted elements. Though you didn't add any events in the current example, it a good habit to get into since events linking to elements that no longer exist can cause serious memory leaks.

Link to comment
Share on other sites

The use of remove instead of just recalling .text or .html to overwrite stuff you put in adrserror is just habit I'd get into. Remove() also looks for and deletes event handlers that were attached to the deleted elements. Though you didn't add any events in the current example, it a good habit to get into since events linking to elements that no longer exist can cause serious memory leaks.

Yes, but the problem with remove() is that it deletes the element completely. That being said,if the checks are re-run there is no element in place to display the error message. The element returns in place if I hit the browser refresh button.

 

Now,I want to mention a last thing about the loop...the fields array contains the items in English...I want though the displayed messages to be in Greek(my native labguage).

 

What can I do?

In other words what gets "pushed" in the missing array must be Greek.

 

What could I do to achieve the above?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...