Pop-up Survey with ASP.NET and jQuery Dialog

Same pop-up survey as in the Pop-up Survey with jQuery UI Dialog post except with ASP.NET (VB) this time.
pop-up survey

Pop-up Behavior

  1. Pop-up survey opens when page loads. Pop-ups on window.unload or window close are being blocked by most browsers due to abuse and overuse.
  2. Cookie is set when survey submitted or user opts out (“No, thanks” click).
  3. Closing dialog will not set cookie

All survey data is stored in a database and jQuery .post is used to shuttle the information back and forth.

Code for the survey dialog:

<div id="survey" title="Pop-Up Survey">
	<p id="surveyDenied"><a href="#">No, thanks</a></p>
		<p>Pop-up survey that cookies browser on completion or on opt-out. Short 411 demo survey.</p>
		<form id="popup_survey" name="popup_survey" method="post">
        <p><strong>Pink or blue?</strong><br />
		<input id="pink" type="radio" name="radio_color" value="pink"  />Pink<br />
        <input id="blue" type="radio" name="radio_color" value="blue"  />Blue</p>
        <p><strong>Soccer or futbol?</strong><br />
		<input id="soccer" type="radio" name="radio_sport" value="soccer"  />Soccer<br />
        <input id="futbol" type="radio" name="radio_sport" value="futbol"  />Futbol</p>
        </form>
	<div id="error_message"></div>
</div>

It’s just a couple of radio buttons and a place for an error message. The submit is handled by the dialog button.

Here is the survey dialog code:

$(function(){  
			$('#survey').dialog({
				bgiframe: true,
				autoOpen: false,
				modal: true,
				width: 500,
				resizable: false,
				buttons: {
					Submit: function(){
						if($("input[name='radio_color']:checked").val() !== undefined && $("input[name='radio_sport']:checked").val() !== undefined){
							setCookie('POPsurvey','POPsurvey',30);
							$.post("process_survey.aspx", $("#popup_survey").serialize(),
							function(data){
								if(data.db_check == 'fail'){
									$("#error_message").html("<p>Database not available. Please try again.</p>");
								} else {
									$("div.pink").css("width",data.perPink);
									$(".perPink").html(data.perPink + "% (" + data.totalPink + ")");
									
									$("div.blue").css("width",data.perBlue);
									$(".perBlue").html(data.perBlue + "% (" + data.totalBlue + ")");
									
									$("div.soccer").css("width",data.perSoccer);
									$(".perSoccer").html(data.perSoccer + "% (" + data.totalSoccer + ")");
									
									$("div.futbol").css("width",data.perFutbol);
									$(".perFutbol").html(data.perFutbol + "% (" + data.totalFutbol + ")");
									
									$(".totalRes").html(data.totalRes);
									
									$('#survey').dialog('close');
									$('#survey_thanks').dialog('open');
								}
								}, "json");
						}else{
							$("#error_message").html("<p>Please answer all questions.</p>");
						}
					}
				}
			});
		});

Lots of stuff but it does several things. First, on submit, it checks that the user answered both questions. Then it sets the cookie. And, finally, it sends the form data off via post and puts the response in elements on the page that are part of the “Thank you” dialog. Speaking of which…

The “Thank you” dialog code is thus:

<div id="survey_thanks" title="Pop-Up Survey - Thank You!">
    <p>Thank you for taking the time to answer our survey. Your input will help us improve the site.</p>
    <p>Responses: <span class="totalRes"></span></p>
    
    <div class="progress-container">  
        pink <span class="perPink"></span>        
        <div class="pink"></div>
        blue <span class="perBlue"></span>
        <div class="blue"></div>
    </div>
    
    <div class="progress-container">  
        soccer <span class="perSoccer"></span>        
        <div class="soccer"></div>
        futbol <span class="perFutbol"></span>
        <div class="futbol"></div>
    </div>
</div>
$(function(){  
			$('#survey_thanks').dialog({
				bgiframe: true,
				autoOpen: false,
				modal: true,
				width: 500,
				resizable: false,
				buttons: {
					Close: function(){
						$(this).dialog('close');
						}
					}
			});
		});

Processing the Survey

The process_survey page adds the answers to the database and brings back the totals that are calculated by a view.

<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<%@ Import Namespace="System.Math" %>

<script runat="server">
    Dim serializer As JavaScriptSerializer

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
        serializer = New JavaScriptSerializer()
        Response.Write(JSONData(Request("radio_color").ToString,Request("radio_sport").ToString))
    End Sub
    
    Public Class Survey
		Public dbcheck As String
        Public totalPink As Integer
		Public perPink As Integer
        Public totalBlue As Integer
		Public perBlue As Integer
        Public totalSoccer As Integer
		Public perSoccer As Integer
		Public totalFutbol As Integer
		Public perFutbol As Integer
		Public totalRes As Integer
    End Class

    Private Function JSONData(ByVal color As String, ByVal sport As String) As String
		Dim srvy As New Survey()
		 
		If color.Length and sport.Length then
        
			Dim mySql As String
			Dim insertSql As String
			Dim insertCommand As SqlCommand
			Dim objConn As New SqlConnection("Server=YOUR_SERVER_HERE;Database=YOUR_DB_HERE;User ID=YOUR_ID_HERE;Password=YOUR_PW_HERE")
			insertSql = "INSERT INTO survey (color,sport) VALUES ('" 
			insertSql += color & "', '"
			insertSql += sport & "')"
			objConn.Open()
			insertCommand = New SqlCommand(insertSql,objConn)
			
			insertCommand.ExecuteNonQuery()
			
			Dim myds As New DataSet("Survey")
			mySql = "SELECT * FROM v_totals"
		   
			Dim adapter As New SqlClient.SqlDataAdapter(mySql, objConn)
			Dim dr As DataRow

			adapter.Fill(myds, "Survey")
			
			dr = myds.Tables(0).Rows(0)
			
				srvy.dbcheck = "OK"
				srvy.totalPink = dr("Pink")
				srvy.perPink = Round(dr("Pink")/(dr("Pink")+dr("Blue")),2)*100
				srvy.totalBlue = dr("Blue")
				srvy.perBlue = Round(dr("Blue")/(dr("Pink")+dr("Blue")),2)*100
				srvy.totalSoccer = dr("Soccer")
				srvy.perSoccer = Round(dr("Soccer")/(dr("Soccer")+dr("Futbol")),2)*100
				srvy.totalFutbol = dr("Futbol")
				srvy.perFutbol = Round(dr("Futbol")/(dr("Soccer")+dr("Futbol")),2)*100
				srvy.totalRes = dr("Total")
	
			objConn.Close()
		
		Else
			 srvy.dbcheck = "fail"
        End If
        
		Return serializer.Serialize(srvy)
    End Function
</script>    

The totals for the return data are stored in a view to prevent separate and multiple calls to the database. The table and the view can be created in SQL Server as such:

CREATE TABLE [dbo].[survey](
	[id] [smallint] IDENTITY(1,1) NOT NULL,
	[color] [varchar](4) NOT NULL,
	[sport] [varchar](6) NOT NULL,
 CONSTRAINT [PK_survey] PRIMARY KEY CLUSTERED 
(
	[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

CREATE VIEW [dbo].[v_totals]
AS
SELECT     TOP (1)
                          (SELECT     COUNT(color) AS Expr1
                            FROM          dbo.survey
                            WHERE      (color = 'pink')) AS Pink,
                          (SELECT     COUNT(color) AS Expr2
                            FROM          dbo.survey AS survey_5
                            WHERE      (color = 'blue')) AS Blue,
                          (SELECT     COUNT(sport) AS Expr3
                            FROM          dbo.survey AS survey_4
                            WHERE      (sport = 'futbol')) AS Futbol,
                          (SELECT     COUNT(sport) AS Expr3
                            FROM          dbo.survey AS survey_3
                            WHERE      (sport = 'soccer')) AS Soccer,
                          (SELECT     COUNT(id) AS Expr4
                            FROM          dbo.survey AS survey_2) AS Total
FROM         dbo.survey AS survey_1

Cookies

The code to handle setting, checking, and deleting cookies is standard javascript:

function setCookie(c_name,value,expiredays)
{
	var exdate=new Date();
	exdate.setDate(exdate.getDate()+expiredays);
	document.cookie=c_name+ "=" +escape(value)+((expiredays==null) ? "" : ";expires="+exdate.toGMTString());
} 

function getCookie(c_name)
{
	if (document.cookie.length>0)
	  {
	  c_start=document.cookie.indexOf(c_name + "=");
	  if (c_start!=-1)
		{
		c_start=c_start + c_name.length+1;
		c_end=document.cookie.indexOf(";",c_start);
		if (c_end==-1) c_end=document.cookie.length;
		return unescape(document.cookie.substring(c_start,c_end));
		}
	  }
	return "";
}

function checkCookie(c_name)
{
	cookie_value=getCookie(c_name);
	if (cookie_value=="") {
		$('#survey').dialog('open');
	}	  
}

function deleteCookie(c_name) {
	document.cookie = c_name +'=; expires=Thu, 01-Jan-70 00:00:01 GMT;';
} 

The style for the “Thank you” graph:

div.progress-container {
  border: 1px solid #ccc; 
  width: 150px; 
  padding: 1px; 
  margin-bottom: 5px;
  background: white;
}

div.progress-container > div {
  height: 12px;
  margin-bottom: 2px;
}
div.progress-container > div.pink { 
  background-color:#CC6699; 
}
div.progress-container > div.blue { 
  background-color: #3366CC; 
}
div.progress-container > div.soccer { 
  background-color: #006633; 
}
div.progress-container > div.futbol { 
  background-color: #663333; 
}

You’ll notice in the .post function that the width of the bar graph is set with the percent of responses for each answer that comes back from the database.

Note: The download zip does not include a web.config. You will need to create your own.

Download zip of all files

Posted in .net, jquery. Tags: , . Permalink. Both comments and trackbacks are closed.

One Trackback

  1. […] This post was mentioned on Twitter by jQuery Bot. jQuery Bot said: via @ASPExperts New post: Pop-up Survey with ASP.NET and jQuery Dialog on jensbits.com: http://wp.me/pBHhc-ep […]