Showing posts with label Custom Actions. Show all posts
Showing posts with label Custom Actions. Show all posts

Tuesday, July 22, 2014

SharePoint 2010 - JavaScript Client - Updating items with visual feedback to user

I had created a custom action for a document library in SharePoint 2010.
When the user presses the custom action button in the ribbon bar, the selected documents should be updated in a special field ("Document Status").
I noticed, that the procedure to update the selected documents takes long time. During the update process the user cannot see what is happening, because of the asynchronous update request via JavaScript.
I thought, this is not very user-friendly, so I created a screen, where the user can see what the system is doing in this moment.
Here is my code with some screenshots.

function ApproveDocuments() {
    var ApprovalProcess = this;
    ApprovalProcess.SiteCollectionUrl = '';
    var counter = 0;
    var fileItems = [], item, docsSentToApproval = [];

    var ClientContext = SP.ClientContext.get_current();
    var LibraryID = SP.ListOperation.Selection.getSelectedList();
    var Library = ClientContext.get_web().get_lists().getById(LibraryID); //Gets the current Library
    var SelectedDocuments = SP.ListOperation.Selection.getSelectedItems(ClientContext);
    var SiteCollection = ClientContext.get_site();
    ClientContext.load(SiteCollection);
    ClientContext.executeQueryAsync(function (s, a) {
        jQuery('#myCloseInfoDivButton').click(function () {
            window.location.href = SiteCollection.get_url() + '/Lists/Document Center';
            ApprovalProcess.SiteCollectionUrl = SiteCollection.get_url();
        });
    });

    var newDiv = '<div id="myCoverAll" style="background-color:#182738;width:100%;height:100%;position:fixed;top:0px;left:0px;display:block;z-index:1000;filter:alpha(opacity=70);-ms-filter:alpha(opacity=70);opacity:0.7;"></div>';
    newDiv += '<DIV id="myInfoDivContainer" class="ms-dlgBorder" style="background-color:#ffffff;HEIGHT: 345px; WIDTH: 609px; position:absolute; left:50%; margin-left:-304px; top:50%; margin-top:-172px;z-index:1001;">';
    newDiv += ' <DIV class="ms-dlgTitle" style="CURSOR: default; WIDTH: 609px">';
    newDiv += ' <SPAN class="ms-dlgTitleText" id="dialogTitleSpan" style="WIDTH: 545px">Approve Documents</SPAN>';
    newDiv += '</DIV>';
    newDiv += '<DIV id="myInfoDivData" class="ms-dlgFrameContainer" style="background-color:#ffffff;padding-top:20px;"></DIV>';
    newDiv += '<div id="myButtonCloseDiv" style="position:relative;width:100px;left:50%;margin-left:-50px;background-color:#ffffff;padding-top:20px;"><input class="ms-toolbar" type="button" name="myCloseInfoDivButton" id="myCloseInfoDivButton" value=" Close " /></DIV>';
    newDiv += '</DIV>';
    jQuery("#aspnetForm").after(newDiv);
    if (SelectedDocuments.length > 0) {
        jQuery('#myCloseInfoDivButton').attr('disabled', 'disabled');
    }

    for (var currentItem in SelectedDocuments) {
        item = Library.getItemById(SelectedDocuments[currentItem].id);
        fileItems.push(item);
        ClientContext.load(item, 'FileLeafRef','Id','DocumentStatus');
    }

    var newElementHtmlHeader;
    newElementHtmlHeader = '<div style="position:relative;width:100px;left:50%;margin-left:-50px;display:block;vertical-align:middle; text-align:center;" id="myLoadingBar"><img src="' + ApprovalProcess.SiteCollectionUrl + '_layouts/images/mySPProject/busy.gif" /><br />Loading...</div>';
    newElementHtmlHeader += '<div style="font-weight:bold;float:left;padding:3px;width:50px;display:table-cell; vertical-align:middle; text-align:center;">Approval Status</div>';
    newElementHtmlHeader += '<div style="font-weight:bold;float:left;padding:3px;">Document</div>';
    newElementHtmlHeader += '<div style="font-weight:bold;float:left;padding:3px;"></div>';
    newElementHtmlHeader += '<div style="clear:both;"></div>';
    jQuery("#myInfoDivData").append(newElementHtmlHeader);

    ClientContext.executeQueryAsync(Function.createDelegate(this, function () {
        var newElementHtml;
        for (var i = 0; i < fileItems.length; i++) {
            newElementHtml = '<div style="float:left;padding:3px;width:50px;display:table-cell; vertical-align:middle; text-align:right;" id="item' + fileItems[i].get_id() + '">';
            if (fileItems[i].get_item('DocumentStatus') != 'Waiting for Approval') {
                newElementHtml += '<img src="' + ApprovalProcess.SiteCollectionUrl + '_layouts/images/mySPProject/docError.png" style="border:0px;width:15px;height:12px;" alt="Document approval error"></img>';
            }
            newElementHtml += '</div>';
            newElementHtml += '<div style="float:left;padding:3px;">' + fileItems[i].get_item('FileLeafRef') + '</div>';

            if (fileItems[i].get_item('DocumentStatus') == 'Waiting for Approval') {
                newElementHtml += '<div style="float:left;padding:3px;" id="approvalStatus' + fileItems[i].get_id() + '">';
                newElementHtml += '</div>';
            }
            else {
                newElementHtml += '<div style="float:left;padding:3px;color:#F60000;" id="approvalStatus' + fileItems[i].get_id() + '">';
                newElementHtml += 'Error: Document not in "Waiting for Approval"-State';
                newElementHtml += '</div>';
            }
            newElementHtml += '<div style="clear:both;"></div>';
            jQuery("#myInfoDivData").append(newElementHtml);
            if (fileItems[i].get_item('DocumentStatus') == 'Waiting for Approval') {
                fileItems[i].set_item('DocumentStatus', 'Approved');
                fileItems[i].update();
                docsSentToApproval[counter] = fileItems[i];
                counter++;
            }
        }
        ClientContext.executeQueryAsync(Function.createDelegate(this, function () {
            for (var i = 0; i < docsSentToApproval.length; i++) {
                jQuery('#item' + docsSentToApproval[i].get_id()).html('<img src="' + ApprovalProcess.SiteCollectionUrl + '_layouts/images/mySPProject/docApproved2.png" style="border:0px;width:15px;height:12px;" alt="Document approved"></img>');
                jQuery('#approvalStatus' + docsSentToApproval[i].get_id()).css('color', '#368131');
                jQuery('#approvalStatus' + docsSentToApproval[i].get_id()).html('Success');
                if(i == (docsSentToApproval.length - 1))
                {
                 jQuery('#myCloseInfoDivButton').removeAttr("disabled");
                 jQuery('#myLoadingBar').css('display','none');
                }
            }
        }), Function.createDelegate(this, function (sender, args) {
            // handle error somehow
        }));
    }), Function.createDelegate(this, this.onLoadItemFailure));
}

and here how it looks like:

Full Screen Layer with "PopUp"


After updating the properties of the selected documents

Maybe this is useful for someone.

Friday, June 13, 2014

SharePoint 2010 - Building Custom Actions in Visual Studio

Today I will show how you can add custom actions to the ribbon bar and the edit control block in SharePoint.

We have to start with creating an empty element in the project. Then replace the text in the xml file with this:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
  Description="Approve Documents"
  Title="Approve Documents"
  Id="RibbonDocumentsManageApproveDocuments"
  Location="CommandUI.Ribbon"
  RegistrationId="10000"
  RegistrationType="List"
  Sequence="0"
  xmlns="http://schemas.microsoft.com/sharepoint/">
    <CommandUIExtension xmlns="http://schemas.microsoft.com/sharepoint/">
      <!-- Define the (UI) button to be used for this custom action -->
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children">
          <Button Id="Ribbon.Documents.Manage.ApproveDocuments"
          Command="{4E2F5DC0-FE2C-4466-BB2D-3ED0D1917763}"
          Image32by32="~site/_layouts/Images/SharePoint-Z-Drive-Project/approve_document_32x32.png"
          Image16by16="~site/_layouts/Images/SharePoint-Z-Drive-Project/approve_document_16x16.png"
          Sequence="0"
          LabelText="Approve Documents"
          Description="Approve Documents"
          TemplateAlias="o1" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <!-- Define the action expected on the button click -->
        <CommandUIHandler Command="{4E2F5DC0-FE2C-4466-BB2D-3ED0D1917763}" CommandAction="javascript:window.open('http://www.bing.com/search?q='.concat(escape(document.title)))" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>

  <CustomAction
  Description="Approve Document"
  Title="Approve Document"
  Id="EditControlBlockApproveDocument"
  Location="EditControlBlock"
  RegistrationId="10000"
  RegistrationType="List"
  ImageUrl="~site/_layouts/Images/SharePoint-Z-Drive-Project/approve_document_16x16.png"
  Sequence="1101"
  xmlns="http://schemas.microsoft.com/sharepoint/">
    <CommandUIExtension xmlns="http://schemas.microsoft.com/sharepoint/">
      <!-- Define the (UI) button to be used for this custom action -->
      <CommandUIDefinitions>
        <CommandUIDefinition Location="EditControlBlock">
          <Button Id="EditControlBlock.ApproveDocument"
          Command="{F8C45D3A-A00D-4412-91BB-C49D75A36F3A}"
          Sequence="1101"
          LabelText="Approve Document"
          Description="Approve Document"
          TemplateAlias="o2" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <!-- Define the action expected on the button click -->
        <CommandUIHandler Command="{F8C45D3A-A00D-4412-91BB-C49D75A36F3A}" CommandAction="javascript:window.open('http://www.bing.com/')" />
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>
</Elements>

The first custom action is to add the button to ribbon bar in the document library. 
The second custom action will add the button to the edit control block of an item.