Solved

Custom Ribbon Action - Disabled with Document Set Selection

Posted on 2014-04-06
13
741 Views
Last Modified: 2014-07-20
The custom action enables/disables when a list item or folder is selected/deselected. The issue I'm running into is when a document set is selected, the custom action remains disabled.


Custom Ribbon Action:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <CustomAction
      Id="LinkDocsCustom"
      Location="CommandUI.Ribbon"
      RegistrationType="ContentType"
      RegistrationId="0x01">
    <CommandUIExtension>
      <CommandUIDefinitions>
        <CommandUIDefinition Location="Ribbon.Documents.Groups._children">
          <Group
              Id="LinkDocsCustomGroup"
              Sequence="15"
              Description="Copy permanent link to clipboard"
              Title="Permanent Link"
              Template="LinkDocsCustomGroupTemplate">
            <Controls Id="LinkDocsCustomGroupControl">
              <Button
                  Id="LinkDocsCustomGroupControlButton"
                  Sequence="5"
                  Command="SimpleAlert"
                  Image32by32="/_layouts/1033/images/formatmap32x32.png" Image32by32Left="-448" Image32by32Top="-128"
                  Description="Copies a permanent link to the clipboard"
                  LabelText="Copy Link to Clipboard"
                  ToolTipTitle="Copy Link to Clipboard"
                  TemplateAlias="o1" />
            </Controls>
          </Group>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.Templates._children">
          <GroupTemplate Id="LinkDocsCustomGroupTemplate">
            <Layout Title="LargeLarge">
              <OverflowSection Type="OneRow" TemplateAlias="o1" DisplayMode="Large"/>
              <OverflowSection Type="OneRow" TemplateAlias="o2" DisplayMode="Large"/>
            </Layout>
          </GroupTemplate>
        </CommandUIDefinition>
        <CommandUIDefinition Location="Ribbon.Documents.Scaling._children">
          <MaxSize Id="Ribbon.Documents.Scaling.Custom.MaxSize" Sequence="15" GroupId="LinkDocsCustomGroup" Size="LargeLarge" />
        </CommandUIDefinition>
      </CommandUIDefinitions>
      <CommandUIHandlers>
        <CommandUIHandler
          Command="SimpleAlert"
          CommandAction="javascript:CopyLinkToClipboard();"
          EnabledScript="javascript:EnableCopyLinkToClipboard();"/>
      </CommandUIHandlers>
    </CommandUIExtension>
  </CustomAction>

  <CustomAction
     Id="CopyLinkToClipboardScript"
     Location="ScriptLink"
     ScriptSrc ="/_layouts/15/CustomMenuAction/CopyLinkToClipboard.js"/>
</Elements>

Open in new window


JavaScript:

// This method contains the code needed to request the unique url to the document
function CopyLinkToClipboard() {
    // First get the context and web
    var ctx = SP.ClientContext.get_current();
    this.web = ctx.get_web();
    // Get the current selected list, then load the list using the getById method of Web (SPWeb)
    var listId = SP.ListOperation.Selection.getSelectedList();
    var sdlist = this.web.get_lists().getById(listId);
    // Get the currently selected item of the list. This will return a dicustonary with an id field
    var items = SP.ListOperation.Selection.getSelectedItems(ctx);
    var mijnid = items[0];
    // Request the list item from the server using the getItemById method. This will load all properties.   
    // If needed, one could pre-request the fields to be loaded to preserve bandwidth.
    this.listItem = sdlist.getItemById(mijnid.id);
    // load the item in the context for batch operation.
    ctx.load(this.listItem);
    //Execute the actual script on the server side. Specify delegates to handle the response. 
    ctx.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

// Delegate that is called when server operation is complete upon success.
function onQuerySucceeded(sender, args) {
    // Request url by using the get_item method. It will return the Url field type, which has a Url property. 
    var url = this.listItem.get_item('_dlc_DocIdUrl').get_url();
    // Request the name of the document. 
    var title = this.listItem.get_item('FileLeafRef');
    // Copy Link To Clipboard (Only works in Internet Explorer)
    window.clipboardData.setData('Text', url);
    // Notify the user that the link was successfully copied
    var notificationId = SP.UI.Notify.addNotification('Link Successfully Copied to Clipboard');
}

// Delegate that is called when server operation is completed with errors.
function onQueryFailed(sender, args) {
    alert('failed ' + args.toString());
}

// Method to enable/disable the button on the ribbon or ECB. 
function EnableCopyLinkToClipboard() {
    var enable = true;
    var context = SP.ClientContext.get_current();
    var selection = SP.ListOperation.Selection.getSelectedItems(context);

    // Check if more than one item is selected, disable the button if items > 1
    if (CountDictionary(selection) == 1)
        this.enable = true;
    else
        return false;
    // Check if a folder is selected
    var item;
    for (item in selection) {
        if (selection[item].fsObjType != 0)
            enable = false;
    }
    return enable;
}

Open in new window

0
Comment
Question by:brendanlefavre
  • 7
  • 6
13 Comments
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39982399
0
 

Author Comment

by:brendanlefavre
ID: 39983390
I'm trying this, but get an error when it tries to load the content type

function EnableCopyLinkToClipboard() {
    var enable = true;
    var context = SP.ClientContext.get_current();
    var selection = SP.ListOperation.Selection.getSelectedItems(context);

    // Check if more than one item is selected, disable the button if items > 1
    if (CountDictionary(selection) == 1)
        this.enable = true;
    else
        return false;
    // Check if a folder is selected
    var item;
	var _contentType = item.get_contentType();
    for (item in selection) {
	    alert(_contentType);
        if (selection[item]._contentType != 'Document')
            enable = false;
    }
    return enable;
}

Open in new window

0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39983543
Did you get 'PropertyOrFieldNotInitializedException' or something else?

Line 13?
0
 

Author Comment

by:brendanlefavre
ID: 39983571
I'm getting "Object doesn't support property or method 'get_contentType'" on line 13
0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39983617
// Check if a folder is selected
    var item;
	var _contentType = item.get_contentType();

Open in new window


Looking at the above code, Item gets declared but never initialized to any type of object?
0
 

Author Comment

by:brendanlefavre
ID: 39984517
what do I need to do to get the object initialized?
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 31

Accepted Solution

by:
Jamie McAllister MVP earned 500 total points
ID: 39985306
Check out the sample from the link I sent (shown below).

After getting the selected item, the actual list item instance is obtained; this.listItem =  list.getItemById(items[k].id);

Then in the Product received function it looks like your code except the Var is initialized as so;
var item = this.listItem;
              var _contentType =  item.get_contentType();



var listItem;
function someFunction()
{
var ctx = SP.ClientContext.get_current();            
            items = SP.ListOperation.Selection.getSelectedItems(ctx);
for (k in items)
            {
              this.listItem =  list.getItemById(items[k].id);
              ctx.load(this.listItem,'Title', 'ContentType');
              ctx.executeQueryAsync(Function.createDelegate(this, this.productReceived), Function.createDelegate(this, this.failed));

            }
}


 function productReceived() {
              var item = this.listItem;
              var _contentType =  item.get_contentType();
              if(_contentType.get_name() == 'Document Set')
              {
                 alert('Document Set Item is selected')                 
              }
            }

function failed(sender, args) {
                alert('failed. Message:' + args.get_message());
            }

Open in new window

0
 

Author Comment

by:brendanlefavre
ID: 39987810
I have tried your suggestion, and get the following error

script error

this is how i'm calling the custom script
get content type action
0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39988140
Please post your latest script here.
0
 

Author Comment

by:brendanlefavre
ID: 39991650
var listItem;
function someFunction() {
    var ctx = SP.ClientContext.get_current();
    items = SP.ListOperation.Selection.getSelectedItems(ctx);
    for (k in items) {
        this.listItem = list.getItemById(items[k].id);
        ctx.load(this.listItem, 'Title', 'ContentType');
        ctx.executeQueryAsync(Function.createDelegate(this, this.productReceived), Function.createDelegate(this, this.failed));
    }
}

function productReceived() {
    var item = this.listItem;
    var _contentType = item.get_contentType();
    if (_contentType.get_name() == 'Document Set') {
        alert('Document Set Item is selected')
    }
}

function failed(sender, args) {
    alert('failed. Message:' + args.get_message());
}

Open in new window

0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 39991737
It looks OK to me.

I'd put some diagnostics after var item = this.listItem; to ensure you really have a List Item at that point. Put some Alerts in there to examine the item title or whether it's null. That will narrow down the investigation as to whether there's an item or .get_contentType() is the problem.
0
 

Author Comment

by:brendanlefavre
ID: 40085310
I got this work, and will post the final code
0
 
LVL 31

Expert Comment

by:Jamie McAllister MVP
ID: 40085585
Good work!
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

If you create your solutions on SharePoint sooner or later you will come upon a request to set  permissions of the item depending on some of the item's meta-data - the author, people assigned as approvers, divisions, categories etc. The most natu…
There is one common problem that all we SharePoint developers share: custom solution deployment. This topic can't be covered fully in this short article, so all I want to do in this one is to review it from a development-to-operations perspectiv…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now