Sorting

Manual sorting of items

From version 3.5 Open Content allows you to add inline sorting using drag and drop for Content Editors (in multi items templates(. If you want your visitors to change the order or filter, use a JavaScript library like JpList.

1. Create SortIndex field

{
    "type": "object",
    "properties": {
			
      "SortIndex": {
        "title": "Sort Order",
        "type": "number"
      }

    }
}

Newly created items will not get a SortIndex value and will end up on top.
If you want them to be added at the bottom use, a high default value for SortIndex .
You can also hide the order field for editors in the options.

"SortIndex": {
	"title": "Sorting Order",
	"type": "number",
	"default": 999999
}
{
    "fields": {
        "SortIndex": {
            "hidden": true
        }
    }
}

2. Modify your template

This need to be done in a template where all items are on the screen and ordered by SortIndex field (Filter settings).

Remark : Filter settings are only available when Index = true in manifest.json
https://opencontent.readme.io/v3.5/docs/manifest

Add Sortable javascript library to your template

More info at https://github.com/RubaXa/Sortable

Add a arrows icon for drag and drop

{{registerstylesheet "/DesktopModules/OpenContent/css/font-awesome/css/font-awesome.css"}}

{{registerscript "http://SortableJS.github.io/Sortable/Sortable.js"}}

  <div class="list-group sortableList" data-moduleid="{{Context.ModuleId}}" >
      {{#each Items}}
      <div class="list-group-item" data-id="{{Context.Id}}">

          {{#if Context.IsEditable}}
          <span class="fa fa-arrows sorthandle" aria-hidden="true" style="cursor: move;cursor: -webkit-grabbing;"></span>
          {{/if}}

          {{Title}}
      </div>
      {{/each}}    
  </div>
RegisterScript("/DesktopModules/OpenContent/css/font-awesome/css/font-awesome.css");
RegisterScript("http://rubaxa.github.io/Sortable/Sortable.js")

<div class="list-group sortableList" data-moduleid="@Model.Context.ModuleId">
@foreach (var dataItem in Model.Items)
{
   <div class="list-group-item" data-id="@dataItem.Context.Id">
   @if(dataItem.Context.IsEditable)
   {
      <span class="fa fa-arrows sorthandle" aria-hidden="true" style="cursor:move; cursor:-webkit-grabbing;"></span>
   }
   @dataItem.Title
   </div>
}
</div>

notes:

  • instead of "fa fa-arrows" (from font awesome) you can also use "glyphicons glyphicons-move" (from glyphicons).

3. Modify your javascript

(function ($) {
    $(document).ready(function () {
        initPage(document);
    });
    $(document).on("opencontent.change", function (event, element) {
        initPage(element);
    });
    function initPage(element) {
        $(".sortableList", element).each(function () {

            var moduleid = $(this).attr('data-moduleid');
            var sf = $.ServicesFramework(moduleid);

            var el = $(this)[0];
            Sortable.create(el, {
                handle: '.sorthandle',
                animation: 150,
                store: {
                    get: function (sortable) {
                        return [];
                    },
                    set: function (sortable) {
                        var order = sortable.toArray();
                        $.ajax({
                            type: "POST",
                            url: sf.getServiceRoot('OpenContent') + "OpenContentAPI/ReOrder",
                            contentType: "application/json; charset=utf-8",
                            dataType: "json",
                            data: JSON.stringify(order),
                            beforeSend: sf.setModuleHeaders
                        }).done(function (data) {
                            
                        }).fail(function (xhr, result, status) {
                            console.error("Uh-oh, something broke: " + status);
                        });
                    }
                }
            });
        });
    }
}(jQuery));

Lucene Issues

When you accidentally create the SortIndex field as type "string" instead of "number", this can lead to serious issues with Lucene indexing (which expects a number)

In that case will get an error like this:

❗️

Lucene Error

Invalid shift value in prefixCoded string (is encoded value really an INT?)

Alias: mysite.local/40f-skin-colormenubar/nl-nl
Tab: 100- http://mysite.local/test/OC/Links-Block
.....
DotNetNuke.Services.Exceptions.ModuleLoadException: Invalid shift value in prefixCoded string (is encoded value really an INT?) ---> System.FormatException: Invalid shift value in prefixCoded string (is encoded value really an INT?) at Lucene.Net.Util.NumericUtils.PrefixCodedToInt(String prefixCoded) at .....

To fix this, you should:

  • Change the type of all "SortIndex" fields to "number"
  • Clean up all you data, for all modules (also check the Recycle Bin).
  • Re-index the module / portal (From OC Filter Settings)

Please make sure you check the data of all Open Content Modules.
One "SortIndex": "1", in one of your modules, will lead to the error being shown for other modules as soon as you try to sort on SortIndex.

The following SQL query should not return any results:

SELECT TOP 1000 
	[ContentId]   
  ,[Json]
  ,[ModuleId]
     
  FROM [OpenContent_Items]
  WHERE json like '%SortIndex": "%'

In some cases you might even have to delete the files in the "App_Data\OpenContent\lucene_index" folder (stop the site first)