Skip to main content

I have implemented an auto-save feature for an end user (as per this post https://community.skuid.com/t/auto-save-w24gp), but the thing that is a bit of a showstopper at the moment is that after a save, the focus is removed from the field the user was in. This could be quite annoying 🙂 So I was wondering if there is a solution to set focus to a specific field, based on a variable, after the save - this is my non-working solution so far: //Get the current field var foc = $(document.activeElement); //Do the save …e.g. skuid.model.save //Set the focus $(foc).focus()

Here is the code for an Inline JavaScript Resource that will perform autosave on a given Model after the user has stopped making changes, with a fixed delay to wait before performing the save. After the save completes, an attempt is made to refocus on the last field the user was typing immediately before the save, and also to set the cursor position to the last point the user was at before the save, using 2 jQuery UI extensions Skuid includes: “getCursorPosition” and “setCursorPosition”.


(function(skuid){ var $ = skuid.$; $(function(){ // The delay after which to perform a save var DELAY = 5000; // The name of the Model you wish to autosave. var NAME_OF_MODEL_TO_AUTOSAVE = 'Account'; var editor = new skuid.ui.Editor(); var inputModel = skuid.model.getModel(NAME_OF_MODEL_TO_AUTOSAVE); editor.registerModel(inputModel); // Find all changes in the input model, // and apply them to the record in our 'save' model. var saveChanges = function(){ var activeEl = $(document.activeElement), activeField = activeEl.closest('.nx-field'), fieldId, rowId, cursorPosition, editorEl; if (activeField && activeField.length) { var fieldObj = activeField.data('object'); if (fieldObj) { fieldId = fieldObj.id; rowId = fieldObj.row.Id; cursorPosition = activeEl.getCursorPosition(); editorEl = fieldObj.editor.element; } } inputModel.save({ callback:function(result){ if (result.totalsuccess) { // All saves completed successfully. // Go re-focus the selected field if (editorEl) { $.each(editorEl.data('object').list.renderedItemsrrowId].fields,function(){ if (this.id === fieldId) { var input = this.element.find(':input'); input.focus().setCursorPosition(cursorPosition); } }); } } else { // Something went wrong. } } }); }; var timer; editor.handleChange = function(){ // Reset our timer, if we're already scheduled to save changes if (timer) { clearTimeout(timer); } // Schedule a timeout to save changes timer = setTimeout(saveChanges,DELAY); }; // This will be called if our input model was manually saved/cancelled/refreshed by the user editor.handleSave = editor.handleCancel = editor.handleDataRefresh = function() { clearTimeout(timer); }; }); })(skuid); 

That is awesome, thanks Zach.  I have adapted the code to save multiple models i.e. :
 


skuid.model.save(e inputModel1,inputModel2,inputModel3], {callback:function(result)...

Also I found that there was a problem with email and checkbox fields with the setCursorPosition function so I made a change to test for those types before calling setCursorPosition.

Finally because my page is quite complex and has 2 related lists in edit mode which need to be autosaved, I had a problem with new rows failing autosave, because they don’t have a ‘proper’ id yet.  My solution/hack is as follows, I expect there is a much better way to do this but it works:

firstly when identifying the ‘active’ row:


&nbsp; &nbsp; //If rowId is not a Salesforce record Id, it is a //new record&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; if(rowId.length &lt; 18){<br>&nbsp; &nbsp; &nbsp; rowId = 0;<br>&nbsp; &nbsp; }


and then when finding the control to focus back on:


&nbsp; &nbsp; if(rowId !=0) {<br>&nbsp; &nbsp; &nbsp; &nbsp; //Existing row<br>&nbsp; &nbsp; &nbsp; &nbsp; fields = editorEl.data('object').list.renderedItems rrowId].fields;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; else {<br>&nbsp; &nbsp; &nbsp; &nbsp; //New row<br>&nbsp; &nbsp; &nbsp; &nbsp; fields = editorEl.data('object').list.<b>visibleItems</b>t 0].fields;<br>&nbsp; &nbsp; }


Thanks again for the solution Zach, much appreciated.