2

I was using JSLink to change the display of a documents webpart. I was retrieving the document icon url set by Sharepoint for a document library item like this:

(it can be shortcut icon (DOCLINK.GIF), or document type icon (ictxt.gif, ichtm.gif, icdoc.gif, etc.) -> i.e. not the File type document, since shortcuts are aspx files, but are not the same icon as a standard aspx file: it recognizes it's a shortcut (="Link to document" type) )

itemHtml:function (ctx) {
    //...
    var iconURL = ctx.imagesPath+ctx.CurrentItem["HTML_x0020_File_x0020_Type.File_x0020_Type.mapico"];
    //...
}

It is working fine.

Now i'm trying to get that same icon with CSOM and caml query, for easier implementation (JSLink is quite a pain to do)

var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml("<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FSObjType' /><Value Type='int'>0</Value></Eq></Where></Query></View>");
collListItem = oList.getItems(camlQuery);

clientContext.load(collListItem);

clientContext.executeQueryAsync(function () {
    var listItemEnumerator = collListItem.getEnumerator();
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
        //...
        var icon = oListItem.get_item('???'); 
        //...
    }

}, function(){
    alert('error');
});

Do you know a way to get the icon set by SP for each item?

Many thanks!

5
  • Maybe this answer of mine can help you: Refer office icons programatically
    – jcp
    Mar 18, 2016 at 9:57
  • @jcp tried this, couldn't make ik work since it requires a new async call on ctx,and from the while loop, it doesn't wait for the returned value to continue the loop...
    – okp
    Mar 21, 2016 at 9:05
  • Fetch the icons after you've fetched the items with a second ctx.executeQueryAsync(): First fetch all items and store the relevant values in an array (e.g. title, filename, ...). Within your first OnSuccess function you iterate over the array and store the icon like this: results[i]["docicon"] = web.mapToIcon(results[i]["filename"], '', SP.Utilities.IconSize.Size16); When you've iterated over the complete array call ctx.executeQueryAsync() a second time. Wihtin the second OnSuccess function you should be able to access the icon image name at results[i]["docicon"].
    – jcp
    Mar 21, 2016 at 10:24
  • I managed to to something similar but since I have 500+ documents to get, that makes A LOT of async calls... I get Out of memory issues on sp.runtime.js 9 times out of 10... I don't get why an item property would be directly available with JSLink but not with CSOM...
    – okp
    Mar 21, 2016 at 15:09
  • Please see my answer for updated details on how to fetch the icon names.
    – jcp
    Mar 21, 2016 at 16:05

3 Answers 3

1

You can fetch the icons after after you've fetched the items using the function SP.Web.mapToIcon() (see corresponding MSDN-Article).

This function returns the name of an icon image for a given filename. E.g. passing in MyDocument.docx returns icdocx.png.

To fetch the document icons for multiple items proceed as follows:

First fetch all itmes and store them in an array (here: myItems).

var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml("<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FSObjType' /><Value Type='int'>0</Value></Eq></Where></Query></View>");
collListItem = oList.getItems(camlQuery);

clientContext.load(collListItem);

clientContext.executeQueryAsync(function () {
    // array to store items
    var myItems = [];

    var i = 0;
    var listItemEnumerator = collListItem.getEnumerator();

    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();

        // store item in array
        myItems[i]["Item"] = oListItem;
        i++;
    }

    getDocIcons(myItems);

}, function(){
    alert('error');
});

Pass the results myItems to a second function getDocIcons() to retrieve the icon names. This is where SP.Web.mapToIcon() comes into play. Here you call ctx.executeQueryAsync() a second time to retrieve the icon names from the server.

// get icons for items
function getDocIcons(myItems) {
    var ctx = new SP.ClientContext.get_current();
    var web = ctx.get_web();

    for (var i = 0; i < myItems.length; i++) {
        var iconName = web.mapToIcon(myItems[i]["Path"], '', SP.Utilities.IconSize.Size16);
        myItems[i]["DocIcon"] = iconName;
    }

    ctx.executeQueryAsync(
        Function.createDelegate(this, function(){ doSomethingWithResults(myItems); } ),
        alert ('Error on retrieving docIcons');
}

On success call the function doSomethingWithResults(). Within this function you can access the icon names retrieved from the server.

// do something with your items and icons
function doSomethingWithResults(items) {
    for (var i = 0; i < myItems.length; i++) {
        var fileName = item[i]["Item"]["FileLeafRef"];
        var iconName = item[i]["DocIcon"];  // sth. like "icdocx.png"
        var imgSrc = _spPageContextInfo.siteAbsoluteUrl + "/" + _spPageContextInfo.layoutsUrl + "/images/" + iconName;
        ...
    }
}

Overall you have two ctx.executeQueryAsync() calls:

  1. retrieve items themselves
  2. retrieve icon names for the items

Disclaimer: I've copied the JavaScript code from another project, modified it for this answer but haven't tested the modified code in depth.

0

The field : DocIcon will just give to you the Name of the icon (log, xlsx...) it will not give you the FileName of the icone.

To do that there is a wonderfull methode in CSOM/JSOM : SP.Web.mapToIcon That return the icone file name of a SPFile

Exemple of use :

var fileAbsolutURL = http://server/sites/web/docLib/myFile.docx"
var context = SP.ClientContext.get_current();
var web = context.get_web();
context.load(web);
context.executeQueryAsync();
var iconResult = web.mapToIcon(fileAbsolutURL,'',SP.Utilities.IconSize.size16)
context.executeQueryAsync();
var iconFileName = iconResult.get_value();
var imgSrc = _spPageContextInfo.siteAbsoluteUrl + "/" + _spPageContextInfo.layoutsUrl + "/images/" + iconFileName;
0

Thanks a lot to @jcp for his useful help. I made a few modifications:

  • can't set directly a array sub value myItems[i]["Item"] = oListItem;. Had to add myItems[i]=[]; before.
  • get item properties with myItems[i]["Item"].get_item('Title') instead of myItems[i]["Item"]['Title']
  • get the m_value of iconName since it returns an object (SP.Result type)

Here is my final code:

var collListItem;
var clientContext = new SP.ClientContext.get_current();
var oList = clientContext.get_web().get_lists().getByTitle('My List Name');

var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml("<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FSObjType' /><Value Type='int'>0</Value></Eq></Where></Query></View>");
collListItem = oList.getItems(camlQuery);

clientContext.load(collListItem);

clientContext.executeQueryAsync(function () {
    var myItems=[];
    var i=0;
    var listItemEnumerator = collListItem.getEnumerator();

    while (listItemEnumerator.moveNext()) {             
        var oListItem = listItemEnumerator.get_current();
        myItems[i]=[];
        myItems[i]["Item"] = oListItem;
        i++;
    }
    getDocsIcons(myItems,targetId,rootFolder)
}, function(){
    console.log('Error loading elements');
});


function getDocsIcons(myItems) {
    var ctx = new SP.ClientContext.get_current();
    var web = ctx.get_web();

    for (var i = 0; i < myItems.length; i++) {
        var iconName = web.mapToIcon(myItems[i]["Item"].get_item("FileLeafRef"), '', SP.Utilities.IconSize.Size16);
        myItems[i]["DocIcon"] = iconName;
    }

    ctx.executeQueryAsync(
        Function.createDelegate(this, function(){ renderAllItems(myItems); } ),
        console.log('Error on retrieving docIcons')
    )           
}

function renderAllItems(myItems){   
    for (var i = 0; i < myItems.length; i++) {
        var iconFile = myItems[i]["DocIcon"].m_value; 
        var title =  myItems[i]["Item"].get_item('Title'); 
        var fileRef =  myItems[i]["Item"].get_item('FileRef');

        $('#myContainer').append('<li><img src="'+_spPageContextInfo.layoutsUrl+'/images/'+iconFile+'" /><a target="_blank" href="'+fileRef+'">'+title+'</a></li>');
    }       
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.