Hi all!

I am trying to include two functions in an onchange when the user selects a new value from a select list:

It is a quite big form form - There are one select list, when changed - TWO other fields in the form needs to change accordingly:

I put the information back using ajax and place it within a <span id="blah"></span>;
I have checked the span ids, and they are correct!

Unfortunately, the second function disables the first one :-/

This is the select list with the onchange functions:

<?php
// SELECT LIST WHICH DECIDES THE "PREFIX-CONTENT" OF TWO OTHER FIELDS: 

echo '<select name="hovedside_id" onchange="hentPosition(this.value); urlKey(this.value)" style="padding:3px;">';
echo '<option value="'.$aktuelt_id.'"> - '.$aktuelt_hovedemne.' - </option>';
$sql = "SELECT id, link_titel FROM hovedsider ORDER BY placering ASC";
$result = mysqli_query($connection, $sql)or die(mysqli_error($connection));
while($row = mysqli_fetch_array($result))
{
	echo '<option value="'.$row['id'].'">&nbsp;&nbsp;'.$row['link_titel'].'</option>';	
}
echo '</select>';
?>

In the top of the page I have included two JS files, which run each function, and opens a ajax request for each their php file which returns the wanted data (not quite yet..)

<head>
<script language="Javascript" type="text/javascript" src="ajaxJS/underside_position.js"></script>

<script language="Javascript" type="text/javascript" src="ajaxJS/url_key.js"></script>
</head>

The top one: ajaxJS/underside_position.js

function hentPosition(str)
 {
 if (str=="")
   {
   document.getElementById("placering").innerHTML="";
   return;
   } 
if (window.XMLHttpRequest)
   {// code for IE7+, Firefox, Chrome, Opera, Safari
   xmlhttp=new XMLHttpRequest();
   }
 else
   {// code for IE6, IE5
   xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
   }
 xmlhttp.onreadystatechange=function()
   {
   if (xmlhttp.readyState==4 && xmlhttp.status==200)
     {
     document.getElementById("placering").innerHTML=xmlhttp.responseText;
     }
   }
 xmlhttp.open("GET","ajaxPHP/underside_position.php?q="+str,true);
 xmlhttp.send();
 }

The first one opens this php file, and returns the data fine when running alone:

session_start();
// Find positions for second dropdown list

$hoved_side_id = $_GET['q']; // Fra ajax i filen underside_position.js i ajaxJS folder

$sql = "SELECT placering FROM undersider WHERE hovedside_id ='$hoved_side_id'";
$resultat = mysqli_query($connection, $sql);

// If a new subject, return $count+1:
if ($_SESSION['gammelt_hovedside_id'] != $hoved_side_id)
{
echo '<select name="placering" style="padding:3px; width:45px;">';
$position_count = mysqli_num_rows($resultat);
for($count=1; $count<=$position_count+1; $count++)
{
echo '<option value= ' . $count . '>' . $count . '</option>';
}
echo '</select>
<small>Se Url Key hvis du skifter hovedemne!</small>';
}

// If its the same subject only return $count:
if ($_SESSION['gammelt_hovedside_id'] == $hoved_side_id)
{
echo '<select name="placering" style="padding:3px; width:45px;">';
$position_count = mysqli_num_rows($resultat);
for($count=1; $count<=$position_count; $count++)
{			
echo '<option value= ' . $count . ' style="width:40px;">' . $count . '</option>';
}
echo '</select>';
}	
?>

The second function: ajaxJS/url_key.js

function urlKey(str)
 {
 if (str=="")
   {
   document.getElementById("url_key").innerHTML="";
   return;
   } 
if (window.XMLHttpRequest)
   {// code for IE7+, Firefox, Chrome, Opera, Safari
   xmlhttp=new XMLHttpRequest();
   }
 else
   {// code for IE6, IE5
   xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
   }
 xmlhttp.onreadystatechange=function()
   {
   if (xmlhttp.readyState==4 && xmlhttp.status==200)
     {
     document.getElementById("url_key").innerHTML=xmlhttp.responseText;
     }
   }
 xmlhttp.open("GET","ajaxPHP/url_key.php?q="+str,true);
 xmlhttp.send();
 }

Opens this php file:

$url_id = $_GET['q'];
// Just testing if it gets printed the right place, which it does
echo $url_id;

When I am using both functions, the first one becomes inactive and doesnt work, how can i change that, fix that?

If i enter something else than ?q="+str,true - lets say ?url_key="+str,true
I get an undefined index error, also if i change this: $url_id = $_GET;
But i dont when i write q in the get, hmm?

Basically:

How can i make this work, so I can use ajax to update two fields when an onchange has happened to the select list?

It works fine when i use the functions alone, but i need them both though :-)

Hope someone has some experince in this, as i am not the most experienced using JS, ajax.

Regards, Klemme

Recommended Answers

All 15 Replies

in your fist php file you have echo'd a select box open, all its values, then a select box close, why not echo where you want the second response to go followed by the results of a second sql query, Yours span can cover multiple select boxes and text boxes etc

Could i write get.elementbyid and then define more than one id?

And then return additional information into the second span tag with a different id?

The are far apart in the form, which are dispayed in an accordion.

1, Do they need to be far apart in the form?
2, You can only receive one response.
3, that response can have "database response 1(select box)" + "all the form inbetween" + "database response 2"

I would recommend trying change the layout of your form to make it easier for yourself... always look for the easiest 'lightest' method

Have you got a 'working version' I can take a look at?
'

I understand that hentPosition() works when urlKey() is omitted but it's not clear - does urlKey() work when hentPosition() is omitted?

By the way this.value will not work for select elements in all browsers. this[this.selectedIndex].value is the cross-browser solution.

Airshow

3, that response can have "database response 1(select box)" + "all the form inbetween" + "database response 2"

HOLY SAINTS ALIVE!!!

Please don't even consider this.

Use JSON encoding to return a multi-variate response.

Airshow

I see Metophase point, by allmost sending the entire form back as a response, and replacing it with the values gathered.

But that would include half accordions split up etc.

HOLY SAINTS ALIVE :-) What would happen then? If you can explain :-)

Isnt it possible to set a timeout on the other request, as i am reading an getting more and more info saying that you can only make ONE ajax request at a time, right?

Is it called a callback maybe?

I am on deep water here, dont really know how to establish a callback or set a time out on lets say the second function.

They run fine both of them, when i remove one or the other - So the conflict must be that it is simultaneously, which is the way it is now. So I was thinking if i could insert a timeout on lets say 5 seconds, before function number to runs - you reckon that would work?

Thanks for the tip on : this[this.selectedIndex].value!!

Nope unfortunately not, there is no working or live version at the moment, but there will be, one fine day.. :-)

After thinking about it... you could in the JavaScript set a split of your response, so once your readystatus

split(xmlhttp.responseText,"anything you wanted to use to split your responses");

not tested might work, may be a little more complexed than this but have a look into it

Im reading all over the net, trying to find the best way..

I found this bit of code which uses split as you mentioned Metophase:

function updatePage() {
   if (request.readyState == 4) {
     if (request.status == 200) {
       var response = request.responseText.split("|");
       document.getElementById("order").value = response[0];
       document.getElementById("address").innerHTML =
         response[1].replace(/\n/g, "<br />");
     } else
       alert("status is " + request.status);
   }
 }

unfortunately I am terrible at javascript, so I am loooooooost :-)

Any idea on how to implement this into my two functions, and any idea on how it could work?

I was thinking about joining the two onchange functions in the same JS file instead, and the somehow set a timout or a delay on the second function, waiting until the first function has returned its answer. And that way make sure they do not run on the same time, and mix up the anwers etc etc.

I appreciate all help! Its a very nice bit of functionality to the form, if I can get i to work :-)

Somehow tjecking the state on the first request, and when it has reached, what? 400? Then use the request for function number two.

Does this make sense to someone who knows how to make multiple ajax requests in the same call?

Klemme

Klemme,

You have two realistic choices:

1. Make two ajax requests "in cascade" - call the second from the response handler of the first.

//First a function that returns an XMLHttpRequest object
//This makes the rest of the code simpler
function getXhrObject() {
  if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
    return new XMLHttpRequest();
  }
  else{// code for IE6, IE5
    return new ActiveXObject("Microsoft.XMLHTTP");
  }
}

//Now javascript function with combined action - two ajax calls in cascade
function hentPos_urlKey(str, str2) {
	var placering = document.getElementById("placering");
	if (str=="") {
		if(placering){ placering.innerHTML = ""; }
		return;
	}
	var xmlhttp = getXhrObject();//outer ajax request
	xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
			if(placering) { placering.innerHTML = xmlhttp.responseText; }
			var url_key = document.getElementById("url_key");
			if (str2 == "") {
				if(url_key) { url_key.innerHTML = ""; }
				return;
			}
			var xmlhttp = getXhrObject();//inner ajax request
			xmlhttp.onreadystatechange=function() {
				if (xmlhttp.readyState==4 && xmlhttp.status==200) {
					if (url_key) { url_key.innerHTML = xmlhttp.responseText; }
				}
			}
			xmlhttp.open("GET", "ajaxPHP/url_key.php?q="+str2, true);
			xmlhttp.send();
		}
	}
	xmlhttp.open("GET", "ajaxPHP/underside_position.php?q="+str, true);
	xmlhttp.send();
}

2. Make one ajax request and arrange for php to return both types of result in one response.

Server-side:

session_start();
// **************
// *** PART 1 ***
// **************
// Find positions for second dropdown list
$hoved_side_id = (isset($_GET['q1'])) ? $_GET['q1'] : ''; // Fra ajax i filen underside_position.js i ajaxJS folder
if($hoved_side_id != '') {
	$sql = "SELECT placering FROM undersider WHERE hovedside_id ='$hoved_side_id'";
	$resultat = mysqli_query($connection, $sql);
	// If a new subject, return $count+1:
	if ($_SESSION['gammelt_hovedside_id'] != $hoved_side_id)
	{
		$hentMenu = .......;//build <select>....</select> for hentPosition here
	}
}
else {
		$hentMenu = '';
}

// **************
// *** PART 2 ***
// **************
$url_id = (isset($_GET['q2'])) ? $_GET['q2'] : '';
if(url_id != '') {
	$url_key = ........;// build whetever is necessary for url_id/url_key here
}
else {
	$url_key = '';
}

// **************
// *** PART 3 ***
// **************
//Now build an associative array containing both elements that need to be returned to the ajax response handler
$rtnArray = array(
	'hentMenu' => $hentMenu,
	'url_key' => $url_key
);
echo json_encode($rtnArray);

Client-side:

function hentPos_urlKey(str, str2) {
	var placering = document.getElementById("placering");
	var url_key = document.getElementById("url_key");
	if (!str) {
		if(placering){ placering.innerHTML = ""; }
		str = '';
	}
	if (!str2) {
		if(url_key) { url_key.innerHTML = ""; }
		str2 = '';
	}
	var xmlhttp = getXhrObject();
	xmlhttp.onreadystatechange = function() {
		if (xmlhttp.readyState==4 && xmlhttp.status==200) {
			//Now we json_decode with eval(). It's not very sophisticated but it will do.
			var responseArray = eval(responseText);//Here responseArray is a javascript mimic of $rtnArray built by php.
			if(placering){ placering.innerHTML = responseArray.hentMenu || 'error'; }
			if (url_key) { url_key.innerHTML = responseArray.url_key || 'error'; }
		}
	}
	xmlhttp.open("GET", "ajaxPHP/hentPos_urlKey.php?q1="+str+"&q2="+str2, true);//note change of filename here
	xmlhttp.send();
}

All untested so there may be some bugs

Airshow

You need one function.... but combine your two php pages.....

then have the response consist of,

(database response for echoing selectbox1)
(echo your Spliter)in the example above the guy uses '|'
(database response for echoing selectbox2)

Out of the options airshow has given I would definitely choose option 2, as it condense your code right down, with the array being the response is also excellent however, a simple split would also work to split the response into two part back on client side, that all about personaelk preference... i would use the array, and json-decoding, but if you dont understand this the example you found will do what you need it too. if you combine it with a nice php serverside script that echos the two response you need, seperated by a splitter.

The implode-split approach should be fine in this case as long as you can define a splitter character that is absolutely guaranteed never to appear in the component strings.

If in doubt about any single character, you can use a short character string as the splitter, eg. '^||^'.

Airshow

I am sorry about my late reply to the thread!

The weekend was suddenly there :-)

I appreciate your answers guys! - Tomorrow at some point, I will try to implement the scripts, and see what logic i follow the best!

I might return again, and hopefully it works fine - But then I am curios on why :-)

Ill drop a line in here tomorrow, and mark it solved if i get this far!

Good weekend guys, and thank you so much Airshow and Metophase!

Klemme

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.