Index: main/plugin-survey/resources/js/survey.i18n.js
===================================================================
--- main/plugin-survey/resources/js/survey.i18n.js	(revision 45873)
+++ main/plugin-survey/resources/js/survey.i18n.js	(working copy)
@@ -51,16 +51,17 @@
     return false;
 }
 
-function survey_begin (id)
+function survey_begin (id, surveyId, context)
 {
 	$j("#survey-" + id + "-mandatory-hint").show();
 	$j("#survey-" + id + "-page-1").show();
 	$j("#survey-" + id + "-start-page").hide();
 	
 	survey_arrange_matrix(id, "survey-" + id + "-page-1");
+	survey_save_page(surveyId, "page-1", context);
 }
 
-function survey_end (id, pos)
+function survey_end (id, pos, surveyId, context)
 {
 	var errors = eval('checkForm_' + id + '_' + pos + '()');
 	if (errors.length &gt; 0)
@@ -69,11 +70,13 @@
 		return;
 	}
 	
+	survey_delete_cookie(surveyId, context);
+	
 	// Submit form
 	$j("#survey-" + id + "-form").submit();
 }
 
-function survey_nextpage(id, pos, last)
+function survey_nextpage(id, pos, last, surveyId, context)
 {
 	var errors = eval('checkForm_' + id + '_' + pos + '()');
 	if (errors.length &gt; 0)
@@ -110,9 +113,10 @@
 	survey_arrange_matrix(id, "survey-" + id + "-page-" + next);
 	
 	survey_precedePages[id].push(pos);
+	survey_save_page(surveyId, "page-" + next, context);
 }
 
-function survey_previouspage(id, pos)
+function survey_previouspage(id, pos, surveyId, context)
 {
 	$j("#survey-" + id + "-mandatory-hint").show();
 
@@ -132,6 +136,7 @@
 	$j("#survey-" + id + "-page-" + precedePage).show();
 	
 	$j(window).scrollTop($j("#survey-" + id + "-page-" + precedePage).position().top);
+	survey_save_page(surveyId, "page-" + precedePage, context);
 }
 
 function survey_input_radio_empty (formId, name)
@@ -226,4 +231,153 @@
 {
 	var checked = input.value != '';
 	$j('#' + id).get(0).checked = checked;
-}
\ No newline at end of file
+}
+
+/********************************* Cookie survey form ****************************************************/
+var surveyCookieExpireDay = 390;
+var surveyCookiePath = "/";
+
+// Save all the form values
+function survey_save_form_values (surveyId, uniqueId)
+{
+	var formJson = survey_get_formJson ();
+	if (formJson[surveyId] == null)
+	{
+		formJson[surveyId] = {};
+	}
+	
+	var surveyFormJson = formJson[surveyId];
+	var form = $j("#survey-" + uniqueId + "-form");
+	surveyFormJson["values"] = form.serializeArray();
+	
+	$j.cookie("org.ametys.survey.formSurveys", JSON.stringify(formJson), {expires: surveyCookieExpireDay, path: surveyCookiePath});
+}
+
+// Save the current page
+function survey_save_page (surveyId, pageId, context)
+{
+	if (context == '' || context == 'front')
+	{
+		var formJson = survey_get_formJson ();
+		if (formJson[surveyId] == null)
+		{
+			formJson[surveyId] = {};
+		}
+		
+		var surveyFormJson = formJson[surveyId];
+		surveyFormJson["page"] = pageId;
+		
+		$j.cookie("org.ametys.survey.formSurveys", JSON.stringify(formJson), {expires: surveyCookieExpireDay, path: surveyCookiePath});
+	}
+}
+
+// Get the form values from the cookie
+function survey_get_formJson ()
+{
+	var cookieJson = $j.cookie("org.ametys.survey.formSurveys");
+	if (cookieJson != null)
+	{
+		return JSON.parse(cookieJson);
+	}
+	
+	return {};
+}
+
+// Go to the page pre-selected from the cookie
+function survey_go_to_page (uniqueId, surveyFormJson, totalPage)
+{
+	var pageName = surveyFormJson["page"];
+	if (pageName != null)
+	{
+		$j("#survey-" + uniqueId + "-mandatory-hint").show();
+		$j("#survey-" + uniqueId + "-" + pageName).show();
+		$j("#survey-" + uniqueId + "-start-page").hide();
+		
+		if (pageName.substring(5) == totalPage)
+		{
+			$j("#survey-" + uniqueId + "-mandatory-hint").hide();
+		}
+		
+		survey_arrange_matrix(uniqueId, "survey-" + uniqueId + "-" + pageName);
+	}
+}
+
+// Fill the form with the values pre-selected from the cookie
+function survey_fill_form (surveyId, uniqueId, totalPage)
+{
+	var formJson = survey_get_formJson();
+	if (formJson[surveyId] != null)
+	{
+		var surveyFormJson = formJson[surveyId];
+		var values = surveyFormJson["values"];
+		var form = $j("#survey-" + uniqueId + "-form");
+		// browse all values from the cookie
+		for (var ind in values)
+		{
+			var object = values[ind];
+			// get the input in the form link to the name 'object.name'
+			var input = $j('[name='+object.name+']', form);
+			if (object.value != "")
+			{
+				// check the type of the input
+				switch(input.attr("type"))  
+			    {  
+			        case "text" :   
+			        case "hidden":  
+			        	input.val(object.value);
+			        break;   
+			        case "radio" : 
+		        	case "checkbox":   
+			        	input.each(function()
+	        			{
+			        		if ($j(this).attr('value') == object.value) 
+			        		{  
+			        			//We trigger a click event because with Jqtranform, .attr('checked', true) doesn't work
+			        			$j(this).trigger('click');
+			        		} 
+		        		});   
+			        break;  
+			        default:
+			        	// the default case for textarea or select (to handle)
+			        	input.val(object.value);
+			    }  
+			}
+		}
+		
+		survey_go_to_page (uniqueId, surveyFormJson, totalPage);
+	}
+}
+
+// Delete form survey from cookie
+function survey_delete_cookie (surveyId, context)
+{
+	if (context == '' || context == 'front')
+	{
+		var formJson = survey_get_formJson();
+		if (formJson[surveyId] != null)
+		{
+			formJson[surveyId] = {};
+			$j.cookie("org.ametys.survey.formSurveys", JSON.stringify(formJson), {expires: surveyCookieExpireDay, path: surveyCookiePath});
+		}
+	}
+}
+
+// Returns a function, that, as long as it continues to be invoked, will not
+// be triggered. The function will be called after it stops being called for
+// N milliseconds. If `immediate` is passed, trigger the function on the
+// leading edge, instead of the trailing.
+// cf https://davidwalsh.name/javascript-debounce-function
+function survey_debounce(func, wait, immediate) {
+	var timeout;
+	return function() {
+		var context = this, args = arguments;
+		var later = function() {
+			timeout = null;
+			if (!immediate) func.apply(context, args);
+		};
+		var callNow = immediate &amp;&amp; !timeout;
+		clearTimeout(timeout);
+		timeout = setTimeout(later, wait);
+		if (callNow) func.apply(context, args);
+	};
+};
Index: main/plugin-survey/stylesheets/survey2html.xsl
===================================================================
--- main/plugin-survey/stylesheets/survey2html.xsl	(revision 45873)
+++ main/plugin-survey/stylesheets/survey2html.xsl	(working copy)
@@ -40,7 +40,6 @@
 			}
 			
 			survey_precedePages['<xsl:value-of select="$uniqueId"/>'] = [];
-
 			<xsl:for-each select="survey//page">
 				function checkForm_<xsl:value-of select="$uniqueId"/>_<xsl:value-of select="position()"/>()
 				{
@@ -87,6 +86,25 @@
 					return -1;
 				}
 			</xsl:for-each>
+			
+			<!-- Go to the page pre-selected in the cookies and fill the form -->
+			<xsl:if test="ametys:renderingContext() = 'front'">
+				$j(document).ready(function()
+				{
+				     surveyCookiePath = "<xsl:value-of select="ametys:siteUriPrefix()"/>";
+				     survey_fill_form('<xsl:value-of select="survey/@id"/>', '<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="count(survey/page) + 1"/>);
+	                 
+	                 $j("form#survey-<xsl:value-of select="$uniqueId"/>-form :input").each(function(){
+						 var input = $j(this);
+						 var onEvent_debounced = survey_debounce(function() {
+						   survey_save_form_values ('<xsl:value-of select="survey/@id" />', '<xsl:value-of select="$uniqueId" />')
+					     }, 200);
+						 input.on('input', onEvent_debounced);
+	                     input.on('change', onEvent_debounced);
+	                     input.on('blur', onEvent_debounced);
+					});
+	            });
+            </xsl:if>
 		</script>
             
 		<script type="text/javascript" src="{ametys:pluginResourceURL('survey', 'js/survey.i18n.js')}"/>
@@ -94,7 +112,6 @@
 	
 	<xsl:template name="view">
 		<xsl:param name="level">2</xsl:param>
-	
 		<div id="survey-{$uniqueId}">
 			<xsl:call-template name="start-page"/>
 				
@@ -131,7 +148,7 @@
                 <xsl:with-param name="picture" select="survey/picture" />
                 <xsl:with-param name="alt" select="survey/pictureAlternative" />
                 <xsl:with-param name="idObject" select="survey/@id" />
-            </xsl:call-template>  
+            </xsl:call-template>    
 
 			<xsl:if test="survey/description != ''">
 				<p class="survey-hint">
@@ -156,7 +173,7 @@
 	                	<xsl:call-template name="common-utils-jswrite-input-submit">
 	                		<xsl:with-param name="class-name">start</xsl:with-param>
 	                		<xsl:with-param name="i18nkey">PLUGINS_SURVEY_PAGE_FORM_BEGIN_BUTTON</xsl:with-param>
-	                		<xsl:with-param name="onclick">try { survey_begin('<xsl:value-of select="$uniqueId"/>'); } catch(e) {} return false;</xsl:with-param>
+	                		<xsl:with-param name="onclick">try { survey_begin('<xsl:value-of select="$uniqueId"/>', '<xsl:value-of select="survey/@id" />', '<xsl:value-of select="ametys:renderingContext()" />'); } catch(e) {} return false;</xsl:with-param>
 	                	</xsl:call-template>
                     document.write('&lt;/div&gt;');
                 }
@@ -183,7 +200,7 @@
 	               	<xsl:call-template name="common-utils-jswrite-input-submit">
 	               		<xsl:with-param name="class-name">previous</xsl:with-param>
 	               		<xsl:with-param name="i18nkey">PLUGINS_SURVEY_PAGE_FORM_PRECEDE_BUTTON</xsl:with-param>
-	               		<xsl:with-param name="onclick">try { survey_previouspage('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="count(survey/page) + 1"/>); } catch(e) {} return false;</xsl:with-param>
+	               		<xsl:with-param name="onclick">try { survey_previouspage('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="count(survey/page) + 1"/>, '<xsl:value-of select="survey/@id" />', '<xsl:value-of select="ametys:renderingContext()" />'); } catch(e) {} return false;</xsl:with-param>
 	               	</xsl:call-template>
 	            </script>
 	
@@ -208,6 +225,7 @@
 				<xsl:call-template name="common-utils-input-submit">
 					<xsl:with-param name="class-name">submit</xsl:with-param>
 					<xsl:with-param name="i18nkey">PLUGINS_SURVEY_PAGE_FORM_FINISH_BUTTON</xsl:with-param>
+					<xsl:with-param name="onclick">try { survey_end('<xsl:value-of select="$uniqueId" />', <xsl:value-of select="count(survey/page)"/>, '<xsl:value-of select="survey/@id" />', '<xsl:value-of select="ametys:renderingContext()" />'); } catch(e) {} return false;</xsl:with-param>
 				</xsl:call-template>
 			</xsl:otherwise>
 		</xsl:choose>
@@ -233,8 +251,8 @@
                 <xsl:with-param name="picture" select="picture" />
                 <xsl:with-param name="alt" select="pictureAlternative" />
                 <xsl:with-param name="idObject" select="@id" />
-            </xsl:call-template>  
-            
+            </xsl:call-template>   
+			
 			<xsl:if test="description != ''">
 				<p class="survey-page-hint">
 					<xsl:call-template name="text.nl2br">
@@ -253,7 +271,7 @@
 			               	<xsl:call-template name="common-utils-jswrite-input-submit">
 			               		<xsl:with-param name="class-name">previous</xsl:with-param>
 			               		<xsl:with-param name="i18nkey">PLUGINS_SURVEY_PAGE_FORM_PRECEDE_BUTTON</xsl:with-param>
-			               		<xsl:with-param name="onclick">try { survey_previouspage('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="position()"/>); } catch(e) {} return false;</xsl:with-param>
+			               		<xsl:with-param name="onclick">try { survey_previouspage('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="position()"/>, '<xsl:value-of select="../@id" />', '<xsl:value-of select="ametys:renderingContext()" />'); } catch(e) {} return false;</xsl:with-param>
 			               	</xsl:call-template>
 				        </xsl:if>
 			
@@ -269,7 +287,7 @@
 								<xsl:call-template name="common-utils-jswrite-input-submit">
 									<xsl:with-param name="class-name">submit</xsl:with-param>
 									<xsl:with-param name="i18nkey">PLUGINS_SURVEY_PAGE_FORM_FINISH_BUTTON</xsl:with-param>
-									<xsl:with-param name="onclick">try { survey_end('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="position()"/>); } catch(e) {} return false;</xsl:with-param>
+									<xsl:with-param name="onclick">try { survey_end('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="position()"/>, '<xsl:value-of select="../@id" />', '<xsl:value-of select="ametys:renderingContext()" />'); } catch(e) {} return false;</xsl:with-param>
 								</xsl:call-template>
 							</xsl:otherwise>
 						</xsl:choose>
@@ -283,13 +301,13 @@
 		                	<xsl:call-template name="common-utils-jswrite-input-submit">
 		                		<xsl:with-param name="class-name">previous</xsl:with-param>
 		                		<xsl:with-param name="i18nkey">PLUGINS_SURVEY_PAGE_FORM_PRECEDE_BUTTON</xsl:with-param>
-		                		<xsl:with-param name="onclick">try { survey_previouspage('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="position()"/>); } catch(e) {} return false;</xsl:with-param>
+		                		<xsl:with-param name="onclick">try { survey_previouspage('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="position()"/>, '<xsl:value-of select="../@id" />', '<xsl:value-of select="ametys:renderingContext()" />'); } catch(e) {} return false;</xsl:with-param>
 		                	</xsl:call-template>
 						</xsl:if>
 		               	<xsl:call-template name="common-utils-jswrite-input-submit">
 		               		<xsl:with-param name="class-name">next</xsl:with-param>
 		               		<xsl:with-param name="i18nkey">PLUGINS_SURVEY_PAGE_FORM_NEXT_BUTTON</xsl:with-param>
-		               		<xsl:with-param name="onclick">try { survey_nextpage('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="position()"/>, <xsl:value-of select="count(../page) + 1"/>); } catch(e) {} return false;</xsl:with-param>
+		               		<xsl:with-param name="onclick">try { survey_nextpage('<xsl:value-of select="$uniqueId"/>', <xsl:value-of select="position()"/>, <xsl:value-of select="count(../page) + 1"/>, '<xsl:value-of select="../@id" />', '<xsl:value-of select="ametys:renderingContext()" />'); } catch(e) {} return false;</xsl:with-param>
 		               	</xsl:call-template>
 						document.write("&lt;/div&gt;");
 					</script>
@@ -336,12 +354,12 @@
 					</label>
 				</div>
 				
-				<xsl:call-template name="picture" >
+                <xsl:call-template name="picture" >
 	                <xsl:with-param name="picture" select="picture" />
 	                <xsl:with-param name="alt" select="pictureAlternative" />
 	                <xsl:with-param name="idObject" select="@id" />
-	            </xsl:call-template>  
-            
+	            </xsl:call-template>
+	            
 				<div class="input">	
 					<input type="text" name="{@name}" id="{@name}_{$uniqueId}" class="text"/>
 				</div>
@@ -363,7 +381,7 @@
 	                <xsl:with-param name="picture" select="picture" />
 	                <xsl:with-param name="alt" select="pictureAlternative" />
 	                <xsl:with-param name="idObject" select="@id" />
-	            </xsl:call-template>          
+	            </xsl:call-template>           
 				<div class="input">	
 					<textarea name="{@name}" id="{@name}_{$uniqueId}" rows="3" cols="10"></textarea>
 				</div>
@@ -384,8 +402,8 @@
 	                <xsl:with-param name="picture" select="picture" />
 	                <xsl:with-param name="alt" select="pictureAlternative" />
 	                <xsl:with-param name="idObject" select="@id" />
-	            </xsl:call-template> 
-	            
+	            </xsl:call-template>
+                   
 				<div class="fields">         
 					<xsl:variable name="name" select="@name"/>
 					<xsl:for-each select="options/option">
