Web services – which are a way of allowing disparate systems to share information, make enquiries and get responses over the internet – are old news to web developers, having been around in one form or another since the turn of the millennium. But for many survey programmers, they’re low-hanging fruit left on the vine, just waiting to be picked.

By tapping into these services, survey programmers can provide functionality that would have taken many hours or days to set up. Whether displaying extra information about the subject matter being gathered in the survey (e.g. accessing schedule data for TV and Radio listings), or finding items of interest in the locale of the respondent (e.g. local weather, last local election result, affluence of the borough, distance from a train station, etc ) – the possibilities are growing everyday.

At Askia we have known about the potential for web services in online surveys for a few years now, but it has taken a while for us to find a good compelling use case. We certainly think we have found one here. The web service we are showcasing today will provide a list of states/regions/counties for any country in the World. This clearly could save a lot of set-up for any survey with an international audience.

For this demonstration, we used a web service from Back4App. There are many other web services are available here as well: World Continents, Countries, and Cities | Database Hub. Back4App also allows you to publish your own relational databases as web services, providing easy access for anyone that needs it (and the ability to monetise the access, if needed).

Of course you will need to make sure that whatever web service you use will be reliable and ideally with an SLA (which will likely mean paying for a service rather than using a free one).

The demonstration shows the power of Askia to do client-side hierarchical web service calls, build dynamic dropdowns and populate Askia response objects with data.  We decided to use client-side routing instead of web service routing because it’s a hierarchical scenario and the State dropdown is built dynamically once a Country is selected.  

Demonstration survey link

Note:  The Country dropdown may take a few seconds to become available as the webservice can take a little while to spin up if not used in a while. 

A client-side web service call is made to grab the entire list of countries.

Once a country is selected, another client-side web service call is made (with country as a parameter) to grab the entire list of states/provinces.

On the screen I have placed two labels that have code to create an empty dropdown list.  I’ve also added a label to contain all the JavaScript code.

There are two Country variables that are very important to the JavaScript code.  The first is the dropdown and the second is the Askia open question.  Notice that I use the “Placeholder text” property of the Open ADC to designate which open question I am trying to reference.

Country Dropdown

  Country Open Question

. . . referenced by:  $(“input[placeholder=’Country’]”) 

There are then also two State variables that are very important to the JavaScript code.  The first is the dropdown and the second is the Askia open question.  Notice that I use the “Placeholder text” property of the Open ADC to designate which open question I am trying to reference.

State Dropdown 

State Open Question

JavaScript Functions 

getCountry() 

This function calls a webservice to grab a list of countries.  It then builds a list of <option> tags to populate the dropdown.  But first, it adds a “– Select Country –” item that comes from the Location_Titles variable (so it can be translated). 

punchCountryID() 

The dropdown items have values formatted as “Value:Text”.  For example, “US:United States” although the text on the dropdown only shows “United States”.  This function (once an item is selected) pushes the value “Value:Text” to the Askia open question. 

getState() 

This function calls a web service to grab a list of states (based on the country selected).  It then builds a list of <option> tags to populate the dropdown.  But first it adds a “– Select State/Province –” item that comes from the Location_Titles variable (so that it can be translated). 

punchStateID() 

The dropdown items have values formatted as “Value:Text”.  For example, “OH:Ohio” although the text on the dropdown only shows “Ohio”.  This function (once an item is selected) pushes the value “Value:Text” to the Askia open question. 

Hide the Open Questions 

Not really a function.  This allows you to change the value to “true” if you want to hide the open text boxes during live interviewing. 

Full JavaScript Source Code

<script type="text/javascript" />

// Make Call for Countries
// ===============================

function getCountry() {
	var settings = {
	  "url": "https://parseapi.back4app.com/classes/Continentscountriescities_Country?limit=10000&order=name&keys=name,code",
	  headers: {
	  	  'X-Parse-Application-Id': '<YOUR_APP_ID>', // app's application id
	  	  'X-Parse-REST-API-Key': '<YOUR_API_KEY>', // app's REST API key
	  },
	  "method": "GET",
	  "timeout": 0,
	};
	
	// Populate Dropdown
	$.ajax(settings).done(function (response) {
                               
		var listItems= "<option value=''>!! Location_Titles.Responses[1].Caption !!</option>";
		for (var i = 0; i < response.results.length; i++){
	  	  	  listItems+= "<option value='" + response.results[i].code + ":"  + escape(response.results[i].name) + "'>" + response.results[i].name + "</option>";
		}
		$("#Country").html(listItems);
		if ( $("input[placeholder='Country']").val() != "" ) {
			$("#Country").val( $("input[placeholder='Country']").val().split(":")[0] + ":" +  escape($("input[placeholder='Country']").val().split(":")[1]) );
			getState();		
		};
		$("#Country").removeAttr("disabled");
	});
};

// Punch dropdown value into the Askia open question
function punchCountryID() {
    $("input[placeholder='Country']").val( $("#Country").val().split(":")[0] + ":" + unescape($("#Country").val().split(":")[1])  );
};

getCountry();

 
// Make Call for States/Provinces
// ===============================

function getState() {

var sCountry = $("input[placeholder='Country']").val();
var sCountryID = "";

if (sCountry != null) {
 sCountryID = sCountry.split(":")[0];
}

// Creating JSON filter to pass to API to get States/Provinces
var sJSON_Country = '{"Country_Code": "' + sCountryID + '"}';

var sURL = "https://parseapi.back4app.com/classes/Continentscountriescities_Subdivisions_States_Provinces?limit=10000&order=Subdivision_Name&where=" + encodeURIComponent(JSON.stringify(sJSON_Country));

	var settings = {
	  "url": sURL,
	  headers: {
	  	  'X-Parse-Application-Id': '<YOUR_APP_ID>', // app's application id
	  	  'X-Parse-REST-API-Key': '<YOUR_API_KEY>', // app's REST API key
	  },
	  "method": "GET",
	  "timeout": 0,
	};

	$("#State").attr("disabled", true); 

	if ( typeof($("input[placeholder='Country']").val())  !== "undefined" && $("input[placeholder='Country']").val() != "" )  {

		// Populate Dropdown  (only if Country has a value)
		$.ajax(settings).done(function (response) {

			var listItems= "<option value=''>!! Location_Titles.Responses[2].Caption !!</option>";
			for (var i = 0; i < response.results.length; i++){
				listItems+= "<option value='" + response.results[i].Subdivision_Code + ":" + escape(response.results[i].Subdivision_Name) + "'>" + response.results[i].Subdivision_Name + "</option>";
			}
			$("#State").html(listItems);
			if ( $("input[placeholder='State']").val() != "" ) {
				$("#State").val( $("input[placeholder='State']").val().split(":")[0] + ":" +  escape($("input[placeholder='State']").val().split(":")[1]) );
			};

			$("#State").removeAttr("disabled");   
		});
	} else {
		$("#State").val("");
		$("input[placeholder='State']").val("");
	};
}

// Punch dropdown value into the Askia open question
function punchStateID() {
    $("input[placeholder='State']").val( $("#State").val().split(":")[0] + ":" + unescape($("#State").val().split(":")[1]) );
};

getState();

// Hide "Hidden" ADC Controls
// ===============================

if (false) {  // Change to True to hide the Askia open questions
	$("input[placeholder='Country']").parent().parent().css( "display", "none" );
	$("input[placeholder='State']").parent().parent().css( "display", "none" );
}

</script>

  Photo by Joshua S on Unsplash