From ad0491c9018d0dd3f65bdc5159231d4a9c46fb10 Mon Sep 17 00:00:00 2001
From: Cameron <e107inc@gmail.com>
Date: Mon, 6 Oct 2014 17:32:36 -0700
Subject: [PATCH] Issue #539 - validation of user-extended elements will
 automatically switch tabs when an error is found.

---
 .../batch/usersettings_shortcodes.php         |  4 +-
 e107_handlers/form_handler.php                | 10 +++
 e107_handlers/user_extended_class.php         | 15 ++--
 e107_web/js/core/front.jquery.js              | 70 +++++++++++++------
 4 files changed, 69 insertions(+), 30 deletions(-)

diff --git a/e107_core/shortcodes/batch/usersettings_shortcodes.php b/e107_core/shortcodes/batch/usersettings_shortcodes.php
index d1075a0dc..9287a8a98 100755
--- a/e107_core/shortcodes/batch/usersettings_shortcodes.php
+++ b/e107_core/shortcodes/batch/usersettings_shortcodes.php
@@ -267,6 +267,8 @@ class usersettings_shortcodes extends e_shortcode
 	{
 		$sql = e107::getDb();
 		$tp = e107::getParser();
+		$frm = e107::getForm();
+		
 		
 		$qry = "
 		SELECT * FROM #user_extended_struct
@@ -428,7 +430,7 @@ class usersettings_shortcodes extends e_shortcode
 			if(defined($fname)) $fname = constant($fname);
 			$fname = $tp->toHTML($fname, "", "emotes_off, defs");
 			
-			if($fInfo['user_extended_struct_required'] == 1)
+			if($fInfo['user_extended_struct_required'] == 1 && !deftrue('BOOTSTRAP'))
 			{
 				$fname = str_replace("{FIELDNAME}", $fname, $REQUIRED_FIELD);
 			}
diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php
index 3b81ad848..78ff2ef05 100644
--- a/e107_handlers/form_handler.php
+++ b/e107_handlers/form_handler.php
@@ -208,6 +208,11 @@ class e_form
 		$c = 0;
 		foreach($array as $key=>$tab)
 		{
+			if(is_numeric($key))
+			{
+				$key = 'tab-'.$this->name2id($tab['caption']);
+			}
+			
 			$active = ($c == 0) ? ' class="active"' : '';
 			$text .= '<li'.$active.'><a href="#'.$key.'" data-toggle="tab">'.$tab['caption'].'</a></li>';
 			$c++;
@@ -222,6 +227,11 @@ class e_form
 		$c=0;
 		foreach($array as $key=>$tab)
 		{
+			if(is_numeric($key))
+			{
+				$key = 'tab-'.$this->name2id($tab['caption']);
+			}
+			
 			$active = ($c == 0) ? ' active' : '';
 			$text .= '<div class="tab-pane'.$active.'" id="'.$key.'">'.$tab['text'].'</div>';
 			$c++;
diff --git a/e107_handlers/user_extended_class.php b/e107_handlers/user_extended_class.php
index 61641f923..b2b6bebfd 100644
--- a/e107_handlers/user_extended_class.php
+++ b/e107_handlers/user_extended_class.php
@@ -676,6 +676,7 @@ class e107_user_extended
 		$regexfail 	= $tp->toText($parms[2]);
 		$fname 		= "ue[user_".$struct['user_extended_struct_name']."]";
 		$required	= vartrue($struct['user_extended_struct_required']) ? "required"  : "";
+		$fid		= $frm->name2id($fname);
 		
 		if(strpos($include, 'class') === FALSE)
 		{
@@ -687,7 +688,7 @@ class e107_user_extended
 		{
 			case EUF_TEXT :  //textbox
 			case EUF_INTEGER :  //integer
-		 		$ret = "<input name='{$fname}' value='{$curval}' {$include} {$required} />";
+		 		$ret = "<input id='{$fid}' name='{$fname}' value='{$curval}' {$include} {$required} />";
 			
 		  		return $ret;
 		  	break;
@@ -722,7 +723,7 @@ class e107_user_extended
 					else 
 					{
 						$chk = ($curval == $val)? " checked='checked' " : "";
-						$ret .= "<input {$include} type='radio' name='{$fname}' value='{$val}' {$chk} {$required} /> {$label}";	
+						$ret .= "<input id='{$fid}' {$include} type='radio' name='{$fname}' value='{$val}' {$chk} {$required} /> {$label}";	
 					}
 					
 				}
@@ -766,7 +767,7 @@ class e107_user_extended
 		break;
 
 		case EUF_DROPDOWN : //dropdown
-		  $ret = "<select {$include} name='{$fname}' {$required} >\n";
+		  $ret = "<select {$include} id='{$fid}' name='{$fname}' {$required} >\n";
 		  $ret .= "<option value=''>&nbsp;</option>\n";  // ensures that the user chose it.
 		  foreach($choices as $choice)
 		  {
@@ -790,7 +791,7 @@ class e107_user_extended
 			if (!method_exists($className, 'getValue')) return '???-???';
 			$temp->pointerReset();
 			
-			$ret = "<select {$include} name='{$fname}' {$required} >\n";
+			$ret = "<select id='{$fid}' {$include} name='{$fname}' {$required} >\n";
 			$ret .= "<option value=''>&nbsp;</option>\n";  // ensures that the user chooses it.
 			while (FALSE !== ($row = $temp->getValue(0, 'next')))
 			{
@@ -810,7 +811,7 @@ class e107_user_extended
 
 				if($sql->db_Select($tp -> toDB($choices[0], true), $tp -> toDB($choices[1], true).",".$tp -> toDB($choices[2], true), "1 $order")){
 					$choiceList = $sql->db_getList('ALL',FALSE);
-					$ret = "<select {$include} name='{$fname}' {$required}  >\n";
+					$ret = "<select id='{$fid}' {$include} name='{$fname}' {$required}  >\n";
 					$ret .= "<option value=''>&nbsp;</option>\n";  // ensures that the user chose it.
 					foreach($choiceList as $cArray)
 					{
@@ -827,7 +828,7 @@ class e107_user_extended
 				break;
 
 			case EUF_TEXTAREA : //textarea
-				return "<textarea {$include} name='{$fname}'  {$required} >{$curval}</textarea>";
+				return "<textarea id='{$fid}' {$include} name='{$fname}'  {$required} >{$curval}</textarea>";
 				break;
 
 			case EUF_DATE : //date
@@ -844,7 +845,7 @@ class e107_user_extended
 				$lanlist = e107::getLanguage()->installed();
 				sort($lanlist);
 				
-            	$ret = "<select {$include} name='{$fname}' {$required} >\n";
+            	$ret = "<select {$include} id='{$fid}' name='{$fname}' {$required} >\n";
 				$ret .= "<option value=''>&nbsp;</option>\n";  // ensures that the user chose it.
 				foreach($lanlist as $choice)
 				{
diff --git a/e107_web/js/core/front.jquery.js b/e107_web/js/core/front.jquery.js
index 623fb7351..a1be14ec9 100644
--- a/e107_web/js/core/front.jquery.js
+++ b/e107_web/js/core/front.jquery.js
@@ -1,4 +1,4 @@
-
+/* global $ */
 
 $(document).ready(function()
 {
@@ -37,8 +37,8 @@ $(document).ready(function()
 	
 		$(".e-comment-submit").live("click", function(){
 			
-			var url 	= $(this).attr("data-target");
-			var sort 	= $(this).attr("data-sort");
+			var url		= $(this).attr("data-target");
+			var sort	= $(this).attr("data-sort");
 			var pid 	= parseInt($(this).attr("data-pid"));
 			var formid 	= (pid != '0') ? "#e-comment-form-reply" : "#e-comment-form";
 			var data 	= $('form'+formid).serialize() ;
@@ -231,7 +231,7 @@ $(document).ready(function()
 			  url: url + '?ajax_used=1&mode=delete',
 			  data: { itemid: sp[3] },
 			  success: function(data) {
-			  	var a = $.parseJSON(data);
+			var a = $.parseJSON(data);
 			  
 				if(!a.error)
 				{
@@ -248,23 +248,23 @@ $(document).ready(function()
 		
 		$(".e-comment-approve").live("click", function(){
 			
-			var url 	= $(this).attr("data-target");
-			var sp 		= $(this).attr('id').split("-");	
-			var id 		= "#comment-status-" + sp[3];
+			var url = $(this).attr("data-target");
+			var sp = $(this).attr('id').split("-");	
+			var id = "#comment-status-" + sp[3];
 	
 			$.ajax({
 			  type: 'POST',
 			  url: url + '?ajax_used=1&mode=approve',
 			  data: { itemid: sp[3] },
 			  success: function(data) {
-			  	
+	
 			  
-			  	var a = $.parseJSON(data);
-				
-			  	
+			var a = $.parseJSON(data);
+			
+	
 				if(!a.error)
 				{		
-					//TODO modify status of html on page. 	
+					//TODO modify status of html on page 	
 					 $(id).text(a.html)
 					 .fadeIn('slow')
 					 .addClass('e-comment-edit-success'); //TODO another class?
@@ -289,28 +289,28 @@ $(document).ready(function()
 		
 		$(".e-rate-thumb").live("click", function(){
 					
-  			var src 		= $(this).attr("href");	
-  			var thumb 		= $(this);	
-  			var tmp 		= src.split('#');
-  			var	id 			= tmp[1];
-  			var	src 		= tmp[0];
-  			
+			var src 		= $(this).attr("href");	
+			var thumb 		= $(this);	
+			var tmp 		= src.split('#');
+			var	id 			= tmp[1];
+			var	src 		= tmp[0];
+			
  
-  			$.ajax({
+			$.ajax({
 				type: "POST",
 				url: src,
 				data: { ajax_used: 1, mode: 'thumb' },
 				dataType: "html",
 				success: function(html) {
 					
-					if(html == '')
+					if(html === '')
 					{
 						return false;	
 					}
 					
 					var tmp = html.split('|');
-  					up= tmp[0];
-  					down = tmp[1];	
+					up= tmp[0];
+					down = tmp[1];	
 					
 				    $('#'+id +'-up').text(up);
 				    $('#'+id +'-down').text(down);
@@ -323,4 +323,30 @@ $(document).ready(function()
 		});
 
 	
+	
+	
+	
+		/* Switch to Tab containing invalid form field. */
+		$('input[type=submit],button[type=submit]').on('click', function() {
+			
+			var id = $(this).closest('form').attr('id'), found = false;
+				
+			$('#'+ id).find(':invalid').each(function (index, node) {
+
+			var tab = $('#'+node.id).closest('.tab-pane').attr('id');
+			// console.log(node.id);
+			
+			if(tab && (found === false))
+			{
+				$('a[href="#'+tab+'"]').tab('show');
+					found = true;
+				}
+	
+			});
+            
+            return true;
+		});
+	
+	
+	
 });
\ No newline at end of file