Display a new icon for each row

This post we’ll go through how to add a new custom icon, next to the lock, compound, … icons.

This is not something that can be done with configuration in ICN. It needs some customization which is near hacking but that will give us what we want.

First step, if you are intending to display an icon based on a custom property, you will have to, either add the property as an icon so it gets fetched, or customize ICN to fetch it, this is explain here.

When this is done, you can proceed to the customization of the client to use the property and display the icon. This is a 2 step process.

  • Aspect the factory of IconValue which is the multiStateIcon method of the class ecm.widget.listview.decorators.common to add your icon when toString is called on the returned object
  • Aspect the createResultSet method of the class ecm.model.ContentItem to increase the size of the first column of the Content list view

First will result in this customization, here I’m using an existing class (ecmRecordIcon) since we are not using it, but you can add some css code in the css of your plugin and use your own icon of course:

// No need to use .prototype on common since it's already a Singleton, no instance are create with new
aspect.after(common, "multiStateIcon", function (result) {
    aspect.after(result, "toString", function (resToString) {
        if (this.item && this.item.attributes.MultiFiledIn) {
            resToString += '<img class="ecmStatusIcon ecmRecordIcon" alt="Multi Filed In Document" title="Multi Filed In Document" src="' + this._blankGif + '" />';
            resToString += '<div class="dijitHidden">Multi Filed In Document</div>';
        }
        return resToString;
    });
    return result;
});

The second will look like this:

// ContentItem.createResultSet is a static method from ContentItem, no need to aspect the prototype
aspect.after(ContentItem, "createResultSet", function (result) {
    if (result && result.structure && result.structure.cells && result.structure.cells.length > 0) {
        var s = result.structure.cells[0][0];
        s.width = "71px"; // 71 is good for one new icon, add 16 per icon
        s.widthWebKit = "71px"; // You can also reuse te value and just add 16px to make it more flexible and cleaner
    }
    return result;
});

And this is it. This way the IconValue will add your icon when its toString is called, and the resultSet will add some extra space to make sure it is still displayed on one line.

7 thoughts on “Display a new icon for each row

  1. George Bredis

    Hi, Guillaume! Just wanted to express my gratitude to You for sharing Your knowledge!
    Months ago I had a requirement to add some icon, dependent on “fake” property (not stored in ECM, but calculated and returned by response filter), and added additional column for it with separate decorator. In addition I had to reorder columns, since the icon have to be shown at the beginning… Now I modified solution the way You show!
    Thanks a lot!

    Reply
    1. bregt pompen

      Hello,

      Thanks for this solution. i managed to let it work , i needed to add in icon after i opened it.
      But for that I needed to refresh the contentlist’s resultset.

      Now when there’s alot of documents in the contentlist the refreshes back to the first row.

      Is there a way to only refresh the item’s row?
      Or a way to jump directly to the item’s row after the contentlist’s resultset.refresh?

      Thanks in advance.

      Bregt

      Reply
  2. George Bredis

    Hi, Guillaume!
    As I mentioned a time ago, I successfully added custom icons to ContentLists – with the help of Your post!
    But for now I’m in stuck. The customer’s requirement is to make icon “clickable”. Which means, that by clicking the icon besides thi item I have to execute Action (the normal ICN one, but not via the context menu or tuulbar). And since I have added an – I can define “onclick” for it, but how van I refer the dojo function of my plugin to be called? I’m sure, my question is quite simple and may be looking stupid, but I realy don’t know how yo achieve this goal…

    And one more question – regrding ICN ContentList… Is there any way to show items within it in a hierarchy? ContentList itself is derived from GridX and GridX allows to do this, by defining a datastore with special functions (hasChildren, getChildren), Can I implement this somehow in ContentList, by modifying the response in ICN ResponseFilter (and adding Tree module)?

    Would be grateful for any ihelp!
    Sincerely Yors,
    George Bredis

    Reply
    1. Guillaume Post author

      Hi George,

      Actually I’m not sure that’s so simple and they are good questions to which I’ll need to play with ICN to fully answer and sadly I won’t have time today. I’ll try to take a look later this weekend if I can but no promises.

      Meanwhile here are some clues, maybe that can help you get started.

      I’d say you can just instantiate directly your action class and call the perform method with all the needed parameters. To get the item and repository from it, you’ll probably need to use the rowId of the row.

      It might be easier instead of using onClick, to use the comtentlist api and add an click listener somehow, because you should have access to information about the item in an easier way, it’s even possible the ICN item might be directly accessible.

      For your second question, I’ve never done it so I’ll have to try. I don’t know what is returning the getFolder service but if there is all the JavaScript to create the contentlist there, your suggestion could be good. Let me know it’s cool stuff and could make a nice article for others 🙂

      Talk to you later,
      Guillaume

      Reply
      1. George Bredis

        Hello, Guillaume!
        Regarding the first question – I solved that easily after a day of research, by getting all the icons’ nodelist with dojo.query(“.myCustomIconClass”) and then assigning the onclick function. Before this, the function itself was added (created) to ContentList in aspect.after(ContentList.prototype, “onContentListModulesLoaded”…
        So, the first requirement was solved.

        But regrding the second one – for now we decided to create a custom property editor to show relationships tree inside the entry template – using original GridX. However, that would be great if there’s a possibility to get this in ICN ContentList…

        Anyway, thanks a lot for Your reply!
        George Bredis

        Reply
      2. George Bredis

        Hello, Guillaume!
        It’s me again, and I have a new question… Sorry for bothering You 🙂
        As I mentioned before, here CM 8.5 is in use with ICN. And there’re compound documents in CM (unfortunately, I’m not sure, is there the same in P8).
        Now, If I manually add the compound attribute to the search results – it’s displayed like “Values…” for items, in which there’re actually some values. And my custom clickable icon should appear for such items. This works fine! But the problem is that I don’t understand, how to add such an attribute in ResponseFilter (openFolder, search, continueQuery) to the JSONResultSetResponse. The point is that I need this functionality in all searches. Maybe there’s another way to recognize in ContentList, whether the item has values in compound attribute or not (without Response Filter)?

        Would be great if You provide me with any idea on how to achieve this!

        Sincerelly Yours,
        George

        Reply
  3. Steven Schmidt

    Hi Guillaume,
    I used your technique to add some custom state icons, but they only appear in a bookmark.jsp page for Navigator administrators. In the regular browse pane, everyone can see them but the bookmark pages don’t seem to ever call the aspect code unless the user is an administrator. Any idea why that would be?
    Thanks!

    Reply

Leave a Reply to Steven Schmidt Cancel reply