6

Having an issue with javascript in sharepoint 2013. We have set up javascript and it is working by changing the colours of the rows in a task list. The issue is when the user goes into quick edit, and then stops that edit, the script stops running and the colours are removed. This is the script.

<script type = "text/javascript">
SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
          OnPostRender: function(ctx) {
            var rows = ctx.ListData.Row;
            for (var i=0;i<rows.length;i++)
            {
              var high = rows[i]["Priority"] == "High";
              if (high)
              {
                var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
                var tr = document.getElementById(rowElementId);
                tr.style.backgroundColor = "#F78181";
              }
            }
            for (var i=0;i<rows.length;i++)
            {
              var normal = rows[i]["Priority"] == "Normal";
              if (normal)
              {
                var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
                var tr = document.getElementById(rowElementId);
                tr.style.backgroundColor = "#BCF5A9";
              }
            }
            for (var i=0;i<rows.length;i++)
            {
              var milestone = rows[i]["Priority"] == "Milestone";
              if (milestone)
              {
                var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
                var tr = document.getElementById(rowElementId);
                tr.style.backgroundColor = "#F3F781";
              }
            }
            for (var i=0;i<rows.length;i++)
            {
              var goLive = rows[i]["Priority"] == "Go Live";
              if (goLive)
              {
                var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
                var tr = document.getElementById(rowElementId);
                tr.style.backgroundColor = "#81B1F8";
              }
            }
          }
        });
</script>

This is an image of what it looks like on page load.

enter image description here

(NOTE: Priority is in the table but have removed it from the screenshot as it had a users info on there)

This is when we are in quick edit mode...

enter image description here

and this is the error when we stop editing.

enter image description here

I am trying to help someone who is working with sharepoint. This not a language I have ever used so don't really know how to solve the problem. What I have done is create some JS code that does a simple alert on post render. This did not cause any issues. However, the minute we try to deal with the table content the problem arises. At a guess I think that SharePoint is changing the ID and so the JS script is no longer pointing at the right object? Having said that I tried to write some javascript that didn't use an ID and just changed the colour of a cell if a particular value was found but that resulted in nothing happening when stop editing. Here is the code.

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$Text = $("td.ms-cellstyle.ms-vb2:contains('High')");
$Text.css("background-color", "green");
$Text.css("font-weight", "bold");
$Text = $("td.ms-cellstyle.ms-vb2:contains('Normal')");
$Text.css("background-color", "red");
$Text.css("font-weight", "bold");
});
</script>

I'm not sure of this either, but looking under what is happening I can see that the program is waiting on a GIF file and it never receives it, would this mean the post render is never called?

enter image description here

However, why would the alert function then run?

But I could also be way off, so was hoping someone with far more knowledge in web processes, and javascript, could help me resolve this?

  • 1: I have the feeling like the script you have used earlier will fail because of the script couldn't find the object you specified. So make sure you check the object if it is available in DOM. 2: If you last script doesn't work, make sure you check the jQuery selector which you have added in script. – Pradip R. Oct 14 '15 at 5:04
  • Just to be clear, when you added the alert to the post-render function, it did fire an alert when you stop editing in quick edit mode? Also, have you tried stepping through the original script to see the state of things when post-render is fired after exiting quick edit mode? – Dylan Cristy Oct 14 '15 at 16:29
  • That is correct, the alert fired after leaving quick edit mode. I am not sure how I would go about checking hte state of things as I am new to javascript etc? – Danrex Oct 14 '15 at 20:08
  • 1
    Modern browsers have developer tools which you can access by hitting F12, or right-clicking on something in the browser and selecting "inspect element". Once the tools window is open, there is a section for scripts (sources). You should be able to find your CSR script in there, and then you can set a breakpoint in the script, inside the OnPostRender function. Then go through the process of going into quick-edit mode, and leaving. When your breakpoint gets hit after leaving quick-edit, you can use the object explorer in the dev tools to inspect the ctx object and see what it's missing. – Dylan Cristy Oct 15 '15 at 16:34
  • 1
    You can also step through the code line by line to see if things like GenerateIIDForListItem(ctx, rows[i]) are failing. (Failing to generate an ID would lead to document.getElementById failing, which would lead to a null tr.) – Dylan Cristy Oct 15 '15 at 16:39
4

The specified error occurs since in Quick Edit mode list view is rendered differently then in default mode, that causes the following selector to return null:

var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
var tr = document.getElementById(rowElementId);  //returns null in Quick Edit mode since tr element does not contain id attribute 

since tr element does not contain id attribute when list view is rendered in Quick Edit mode.

Below is shown function for retrieving row element for default & Quick Edit modes:

function getTableRow(ctx,row)
{
   var rowElementId = GenerateIIDForListItem(ctx, row);
   if(!ctx.inGridMode)
      return document.getElementById(rowElementId);
   return document.querySelectorAll('[iid="' + rowElementId +  '"]')[0];
}

Final example

Below is provided the example that demonstrates how to highlight row in List View both in default and Quick Edit modes

SP.SOD.executeFunc("clienttemplates.js", "SPClientTemplates", function() {
   SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
     OnPostRender: function(ctx) {

            var colorMapping = {"High": "#F78181","Normal": "#81B1F8","Milestone": "#F3F781","Go Live": "#81B1F8"};

            var rows = ctx.ListData.Row;
            for (var i=0;i<rows.length;i++)
            {
              var key = rows[i]["Priority"];
              var color = colorMapping[key];
              highlightRow(ctx, rows[i],color);
            }            

     }
   });
});  


function highlightRow(ctx,row,color){
   var tr = getTableRow(ctx,row);
   if(tr != null)
      tr.style.backgroundColor = color;
}



function getTableRow(ctx,row)
{
   var rowElementId = GenerateIIDForListItem(ctx, row);
   if(!ctx.inGridMode)
      return document.getElementById(rowElementId);
   return document.querySelectorAll('[iid="' + rowElementId +  '"]')[0];
}

Gist: ListView_HighlightRows.js

Results

Pic 1. List View in Quick Edit mode enter image description here

Pic 2. List View (default mode) enter image description here

3

The Issue most likely has to do with MDS (Minimal Download Strategy). You have to add extra code so your code re-executes.
Or disable the MDS feature in Site-Settings.

https://msdn.microsoft.com/en-us/library/office/dn456544.aspx?f=255&MSPPError=-2147217396

Apart from that your code could use some optimization...

You now loop all colors for every item

Replace all those for loops with one, a modern (since IE9*) forEach loop

function OnPostRender_ColorPriority(ctx) {
    var colors ={
      'High'     :'#F78181',
      'Normal'   :'#BCF5A9',
      'Milestone':'#F3F781',
      'Go Live'  :'#81B1F8',
    };
    ctx.ListData.Row.forEach(function(row){
      var fieldValue=row["Priority"];
      var el=document.getElementById( GenerateIIDForListItem(ctx, row) );
      el.style.backgroundColor = colors[ fieldValue ];
    });
};

All this CSR development is a breeze with the awesome Cisar Extension in Chrome developed by Andrei Markeev.

But.. there is a different method

There is a way to change a Row color using a Calculated Column,
works since 2010 and just works in every View without the hassle of separate script-files and JSlinks for every View.

All you have to do is set the datatype to Number

=[Priority] 
 &"<img src=/_layouts/images/blank.gif onload=""{"
    &"var TR=this;while(TR.tagName!='TR'){TR=TR.parentNode}"                
    &"TR.style.backgroundColor=" 
    &"({'High':'#F78181','Normal':'#BCF5A9','Milestone':'#F3F781','Go Live':'#81B1F8'})"
    &"['" &[Priority]& "'];"
 &"}"">"

Full explanation of pros and cons at: http://www.viewmaster365.com/#/How

Update #1

I never knew about

since tr element does not contain id attribute when list view is rendered in Quick Edit mode.

But it does have a unique iid so there is no need for an id, or querySelectorAll)[0]

function OnPostRender_ColorPriority(ctx) {
    var colors ={
      'High'     :'#F78181',
      'Normal'   :'#BCF5A9',
      'Milestone':'#F3F781',
      'Go Live'  :'#81B1F8',
    };
    ctx.ListData.Row.forEach(function(row){
      var fieldValue=row["Priority"];
      var el=document.querySelector('[iid="'+GenerateIIDForListItem(ctx, row)+'"]');
      el.style.backgroundColor = colors[ fieldValue ];
    });
};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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