All posts by Alexander Bautz

DFFS v4.365 released

Finally, after a long BETA period, latest version of Dynamic forms for SharePoint is released.

DFFS v4.365 – February 29, 2016

  • Added support for using DFFS with DocumentSets.
  • Added new trigger “Workflow status” that lets you check the status on a workflow in the current item.
  • Added option to share the Field CSS configuration between different forms in the same list.
  • Added new option to preserve the selected tab when navigating from DispForm to EditForm in a list item. You find this setting in the Misc tab.
  • Split the “showTooltip” out in a separate function to let advanced users override it.
  • Added new functionality to show a list of empty required fields above the form when the save is halted. The list is clickable and will take you to the correct tab / accordion and highlight the field. You can turn this feature on in the Misc tab. Please note that you must update the CSS files also.
  • Added option to set the default “To” and “Cc” in the “E-Mail active tab” feature to a people picker in the current form, or to a fixed email address.
  • Added option to send E-Mails from DFFS rules. You can configure the E-Mail-templates in the new “E-Mail and Print” tab in DFFS backend. Added support for delaying an email until a set “Send date” has been reached. Please note that this is only possible if you use the “Use custom list with workflow to send E-Mails”, and is not when using the built in functionality for sending E-Mails in SP 2013 (REST). You find more information on the help icon in the “E-Mail and Print” functionality in DFFS backend, and in the user manual. You find a video describing the workflow setup in the user manual.
  • Changed the “target” on the link to a document of type “pdf” or “txt” in a DFFS dialog so it will open in a new window.
  • For SP2007: Made the “Return to DispForm when editing an item and NOT opening the form in a dialog” checkbox visible in the Misc tab.
  • Fixed a possible backwards compatibility issue when using the latest version of DFFS with a configuration saved with an older version.
  • Fixed some issues with using “content type” as trigger in a DFFS form.
  • In triggers on date and time columns: added support for comparing with today like this:
    [today]+14 or [today]-5

    The number is the number of days you want to offset the value with. This same functionality can be used when comparing with a value pulled from another date and time column in the form – like this:

     {NameOfField}+14 or {NameOfField}-5
  • Changed the “debug output” to make it easier to read by collapsing some sections initially.
  • Fixed a bug with hiding a field by a rule while using the accordion functionality.
  • Fixed the “change trigger” on date columns so it will trigger the change event on invalid dates.
  • Changed the backend code for detecting the change of a PeoplePicker field.
  • Added support for using People pickers as trigger in SP 2007 and 2010. This requires that you update SPJS-Utility.js. This may not work 100% in all cases – post any findings in the forum.

You find the full change log here: https://spjsblog.com/dffs/dffs-change-log/

User manual

The user manual has been updated with the latest changes: https://spjsblog.com/dffs/dffs-user-manual/

Post any question in the forum

https://spjsblog.com/forums/forum/dynamic-forms-for-sharepoint/

Alexander

Time tracker in a DFFS enabled list

Here is an example of a simple time tracker in a DFFS enabled list.

Before you start you must set up DFFS. You find more info here.

Create the list

Create a custom list, and add these fields. Ensure you use the exact same FieldInternalName as described here. When the field has been created, you can change the name to whatever you like.

  • Title (Default field already present in the list)
  • Description (Multiple lines of text ) – This field is optional, and not required in the solution.
  • StartTimeString (Single line of text
  • TotalTimeString (Single line of text)
  • Activity (Multiple lines of text – plain text)
  • Log (Multiple lines of text – plain text)
  • TotalTime (Calculated) – with this formula – output as “Single line of text”:
    =TEXT(INT(TotalTimeString/1000)/86400,"hh:mm:ss")
  • Ticking (Calculated) – with this formula – output as “Yes/No”:
    =StartTimeString<>""

Configure DFFS

Enter DFFS backend in NewForm and EditForm, and set up DFFS like this (you can create NewForm first, and then clone it to EditForm):

TimeTrackerInDFFS_1

TimeTrackerInDFFS_2

TimeTrackerInDFFS_3

TimeTrackerInDFFS_4

Then add this code to the Custom JS textarea:

(function(){
 var a = [], b = [], tt;
 a.push("<tr style='font-size:18px;color:green;'>");
 a.push("<td colspan='2' style='padding:2px;'>");
 a.push("<span id='elapsedTime'></span><span id='totalTime'></span>"); 
 a.push("</td>");
 a.push("</tr>");
 $("table.ms-formtable").prepend(a.join(""));
 b.push("<span title='You can save and close the list item while the timer is running. It will keep tracking time until you edit the item and click \"Stop the timer\".'>");
 b.push("<input style='background-color:#C2CF8A;color:#444;' type='button' id='dffsTimeTrackerStartBtn' value='Start the timer' onclick='startTicker()'>");
 b.push("<input style='background-color:#D57C7C;color:#ffffff;display:none;' type='button' id='dffsTimeTrackerStopBtn' value='Stop the timer' onclick='stopTicker()'>");
 b.push("<span>&nbsp;</span>");
 b.push("</span>");
 $("input[id$='_diidIOSaveItem']:last").before(b.join(""));
 tt = getFieldValue("TotalTimeString");
 if(tt !== ""){
 $("#elapsedTime").html("Total time: "+getFriendlyTime(Number(tt)));
 }
})();

function startTicker(){
 var a= getFieldValue("StartTimeString");
 if(a === ""){
 setFieldValue("StartTimeString",new Date().valueOf());
 $("#dffsTimeTrackerStartBtn").hide();
 $("#dffsTimeTrackerStopBtn").show();
 $("#totalTime").html("");
 }
}

function stopTicker(){
 var a = getFieldValue("StartTimeString")
 , b = new Date().valueOf()
 , u = spjs.utility.userInfo(_spPageContextInfo.userId)
 , et = b-Number(a)
 , tt = Number(getFieldValue("TotalTimeString")) + et
 , log = getFieldValue("Log")
 , al = getFieldValue("Activity");
 setFieldValue("TotalTimeString",Number(tt));
 // Reset start time and log
 setFieldValue("StartTimeString","");
 setFieldValue("Activity","");
 if(a !== ""){
 if(log !== ""){
 log += "\n*******************\n";
 }
 if(al !== ""){
 al = "\n\nActivity log:\n"+al;
 }
 setFieldValue("Log",log+u.Title+"\nStart: "+new Date(Number(a)).toLocaleString(_spPageContextInfo.currentUICultureName)+"\nEnd: "+new Date().toLocaleString(_spPageContextInfo.currentUICultureName)+"\nElapsed time="+getFriendlyTime(et)+al);
 }
 $("#elapsedTime").html("");
 $("#totalTime").html("Total time: "+getFriendlyTime(tt));
 $("#dffsTimeTrackerStartBtn").show();
 $("#dffsTimeTrackerStopBtn").hide();
}

function getFriendlyTime(ms){
 var h, m, s;
 h = Math.floor(ms / 3600000);
 m = Math.floor((ms % 3600000) / 60000);
 s = Math.floor((ms % 60000) / 1000);
 return (h<10?"0"+h:h)+":"+(m<10?"0"+m:m)+":"+(s<10?"0"+s:s);
}

if(getFieldValue("StartTimeString") !== ""){
 $("#dffsTimeTrackerStartBtn").hide();
 $("#dffsTimeTrackerStopBtn").show();
}

setInterval(function(){
 var a = getFieldValue("StartTimeString"), b = new Date().valueOf(), tt = Number(getFieldValue("TotalTimeString"));
 if(a !== ""){
 $("#elapsedTime").html("Elapsed time: "+getFriendlyTime(b - Number(a))); 
 if(tt !== ""){
 $("#elapsedTime").append(" / Total time: "+getFriendlyTime(tt + (b - Number(a))));
 }
 } 
},1000);

Final result

When you press “Start the timer”, this is how it looks in the form:

TimeTrackerInDFFS_5

When you stop the timer, the total time is displayed like this:

TimeTrackerInDFFS_6

If you restart the timer again, it will count the current elapsed time, and the total time like this:

TimeTrackerInDFFS_7

You can save the list item with the timer running. When you  edit it again afterwards, press “Stop the timer” and save the item.

This is how it looks in the list view:

TimeTrackerInDFFS_8

Please note that the “TotalTime” field will only show the time after the timer has been stopped, and will not show the “live ticker”.

Post any questions in the forum for DFFS here

Alexander

 

New version of CommentBox for SharePoint

I have updated CommentBox for SharePoint with the following changes:

  • Tidied up the code and added support for adding attachments to comments. You can add as many attachments as you like, and they will be listed below the comment.
  • You can also upload imaged directly from the “insert” menu to have them appear inline in the comment.
  • With some restrictions (browser related) you can also paste images from the clipboard directly in the comment textarea.
  • These images are stored as a base64 encoded string inline in the comment, so don’t add very large images this way.
  • Hover over image attachments to show a preview, click, to open in a dialog.

If you have an existing license code, you can request an updated code for this version at no extra cost.

Use the forum for comments and questions

Alexander

AD-Group in SP-Group: Workaround for verifying membership

Change log
January 12, 2016
Fixed a bug with using “getByTitle” and not the correct “getByName” in the SP 2010 code example.

This is a workaround for verifying membership in a SharePoint group when the user is added to the group as a member in an AD-group, and not as an individual user.

For this to work, the SharePoint group must be set up to only allow members to view membership in the group:

You find two code examples below. The first one will work in SP 2013 only, but the last will work in both SP 2010 and SP 2013 (not SP 2007).

Disclaimer: I have NOT been able to test this as I don’t have any AD groups to add in my SP 2013 Office 365 test site.

Based on this post by Eric Alexander

How to set up a trigger in DFFS

In DFFS backend – add this code to the Custom JS:

SharePoint 2013:

function spjs_isCurrentUserInGroup(groupIdOrName){
 var endpoint;
 if(typeof groupIdOrName === "string"){
 endpoint = _spPageContextInfo.webAbsoluteUrl+"/_api/web/sitegroups/getbyname('"+groupIdOrName+"')/CanCurrentUserViewMembership" 
 }else{
 endpoint = _spPageContextInfo.webAbsoluteUrl+"/_api/web/sitegroups("+groupIdOrName+")/CanCurrentUserViewMembership" 
 }
 return jQuery.ajax({ 
 "url":endpoint,
 "type":"GET", 
 "contentType":"application/json;odata=verbose",
 "headers":{ 
 "Accept": "application/json;odata=verbose"
 }
 });
}

function checkADGroupMembership(){
 // 18 is the ID of the SharePoint group
 spjs_isCurrentUserInGroup(18).success(
 function(data){
 if(data.d.CanCurrentUserViewMembership){
 setTimeout(function(){
 spjs.dffs.triggerRule(["isInADGroup"]);
 },10);
 }
 }
 );
}

SharePoint 2010:

function spjs_isCurrentUserInGroup(groupIdOrName){
 var cc, gc, g, u;
 cc = new SP.ClientContext.get_current();
 gc = cc.get_web().get_siteGroups();
 if(typeof groupIdOrName === "string"){
 g = gc.getByName(groupIdOrName);
 }else{
 g = gc.getById(groupIdOrName);
 } 
 u = g.get_users();
 cc.load(u);
 cc.executeQueryAsync(
 function(sender, args){
 setTimeout(function(){
 spjs.dffs.triggerRule(["isInADGroup"]);
 },10);
 },
 function(sender, args){
 // No access
 }
 );
}

function checkADGroupMembership(){
 // 18 is the ID of the SharePoint group
 spjs_isCurrentUserInGroup(18);
}

The number 18 in the function “checkADGroupMembership” is the SharePoint group id, but you can also use the display name of the group – change it to match your group.

Add a rule to DFFS with the “Rule friendly name”:

isInADGroup

This rule is set up with the trigger “No trigger (must be triggered manually), and with all the actions you want to apply if the rule is triggered.

As this is a “manual trigger rule”,  you must add another rule to trigger this one when the form has loaded. This is necessary because the REST call cannot be used with the trigger “Custom JavaScript functions” directly.

To trigger the REST call / JSOM query, and the following trigger of the DFFS rule if the user is member of the group is done by another DFFS rule triggering on “The form is ready”.

Set this one up with the function name “checkADGroupMembership” in the “Run these functions / trigger these rules” field.

If the logged in user is member of the SharePoint group as a member in an AD-group, the rule “isInADGroup” will be triggered.

I hope this makes sense, and if not – post a comment below or in the forum.

Alexander

Redirect from NewForm to EditForm in DFFS

Change log
September 23, 2016
I had forgot to add “return false” in the PreSaveAction function – this could result in duplicates being added to the list.
January 05, 2016
Changed the code example to include the “InDlg” attribute if you are in a dialog.

Here is an alternative solution for redirecting from NewForm to EditForm when using DFFS.

This solution is based on entering NewForm, filling in the Title field, and hitting “Save” to continue in EditForm.

Here is an example on a NewForm

SaveAndContinue

Add this code to the Custom JS

function saveAndRedir(){
	var ok = spjs.dffs.check_Mandatory(["Title"]), data = {}, newItem, url;
	if(ok){
		data.Title = getFieldValue("Title");
		newItem = spjs.utility.addItem({"listName":_spPageContextInfo.pageListId,"data":data});
		if(newItem.success){
			url = location.pathname.substring(0,location.pathname.lastIndexOf("/")) + "/EditForm.aspx?ID="+newItem.id;
			if(GetUrlKeyValue("IsDlg")==="1"){
				url += "&IsDlg=1";
			}
			location.href = url;
		}else{
			alert(newItem.errorText);
		}
	}
}

function PreSaveAction(){
	saveAndRedir();
	return false;
}

This is it – test it and let me know how it works out  in the Forum.

Best regards,
Alexander

Changed outgoing mailserver on SPJSBlog.com

Hi,
I have had some trouble with messages disappearing – especially when someone answers a post in the forum. I have therefore change the outgoing email settings to use Postman SMTP plugin.

This means outgoing email will now be sent from my email address [@gmail.com] and not from [@spjsblog.com].

I’l monitor the email setup to ensure it works as expected, but please post any comments below.

Alexander