Background color for a livetable cell

Last modified by Valdis Vitolins on 2021/03/18 11:28

cogChange the background color for a livetable element
TypeSnippet
Category
Developed by

Mircea Staicu

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1

Description

Changing the background color of a cell based on its value

Even though this example is pretty basic and straightforward, it is a good idea to get acquainted with the XWiki Javascript API and prototype.js, in order to extend the functionality of this snippet and adapt it to your needs.

  1. We should create a document, in the desired space. I personally would put it in the 'Code' space of the wiki.
  2. Next, we should edit the document in Object Mode, and attach to it a JavaScriptExtension object.
  3. In the 'Name' field of the newly created JavaScriptExtension object, specify the name of the object.
  4. The interesting part starts in the 'Code' section of the JavaScriptExtension object. This is where we define the functionality of the object. Because we want to observe for the livetable rows creation, we start with the following structure:
  document.observe("xwiki:livetable:newrow", function(ev){

  });

According to the documentation: xwiki:livetable:newrow (event.memo.row holds the new row).

First, we have to find out which elements we want to work with. We can use Mozilla Firefox's Firebug tool to select the column's cell and expose the class of the element that we want to track. In our case, the cell has the 'Priority' class. Code snippet: <td class="Priority linknone typelist">

Now, using prototype's CSS selector, we will assign an 'each' function to the desired elements. In our case, the ones which have a Priority class. 

  document.observe("xwiki:livetable:newrow", function(ev){
    $$('.Priority').each(function(element){

    });
  });

Now we captured each element of the livetable with the "typedate" class (notice that we used the dot selector which means 'class' in CSS). 

Now, we should decide what we want to do with our element. This example is restricted to changing the background of the element, so that is what we are going to do. Attach a StyleSheetExtension object to that document, give it a name, and inside the 'code' section define the CSS rule for the background. 

  .red-background{
   background-color: #ff0000;
  }

Be sure to choose a class name that its available, because if it already exists, it will override the existing rules of that particular CSS class.

After setting the CSS rules, be sure to mark it on the 'Use this extension' as Always on this wiki, if you plan to use this CSS class more than in one place.

Now back to the javascript code. We will get the content of that element in a cross browser fashion.

  var content = element.innerText;
 if(content === undefined){
    content = element.textContent;
  }

Now that we have the content, we want to do something with it, like associate it a CSS class depending on its content. So that's what we'll going to do.

  if(content === 'High'){
      element.addClassName('red-background');
  }

If the content's value is equal to 'High', add it the class of the StyleSheetExtension code that we defined in the same document.

The final code:

  document.observe("xwiki:livetable:newrow", function(ev){
    $$('.Priority').each(function(element){
     var content = element.innerText;
     if(content === undefined){
        content = element.textContent;
      }
     if(content === 'High'){
        element.addClassName('red-background');
    }
    });
  });

Now, in order to use this functionality, we must go to the desired document which holds the particular livetable and edit that document in wiki mode. Inside the velocity macro tags, add the following line:

#set($discard = $xwiki.jsx.use("Space.Document")) //Space.Document where the JavaScriptExtension object was defined.

If the 'Always on this wiki' is not marked, or if you want to use it in a different wiki you should also include the

#set($discard = $xwiki.ssx.use("Space.Document")) //Space.Document where the StyleSheetExtension object was defined.

The result will look like this:

{{velocity}}
#set($discard = $xwiki.jsx.use("Space.Document"))
#set($discard = $xwiki.ssx.use("Space.Document"))
#livetable(...) ## Livetable code goes here
{{/velocity}}

If you want to use this script on a different wiki:

#set($discard = $xwiki.jsx.use("wikiWhereTheDocumentWasDefined:Space.Document"))

and also include the StyleSheetExtension, if we're on a different wiki

#set($discard = $xwiki.ssx.use("wikiWhereTheDocumentWasDefined:Space.Document"))

The result will look like this:

{{velocity}}
#set($discard = $xwiki.jsx.use("wikiWhereTheDocumentWasDefined:Space.Document"))
#set($discard = $xwiki.ssx.use("wikiWhereTheDocumentWasDefined:Space.Document"))
#livetable(...) ## Livetable code goes here
{{/velocity}}

Changing the background color of a cell based on whether a date is in the past

Another example will make the background of the elements with a lower date than the present date, red.

When defining the column properties of the livetable, the column which holds the date, must be of type date.

  #set($columnsProperties = {
  ...
 "Date" : {"type" : "date", ...}

This will expose the date elements in the livetable with a "typedate" class, which we'll use to capture these elements.

Now, using prototype's CSS selector, we will assign an 'each' function to the desired elements. In our case, the ones which have a 'typedate' class. 

We start with the same structure

  document.observe("xwiki:livetable:newrow", function(ev){
    $$('.typedate').each(function(element){

    });
  });

Notice that we changed the value inside the CSS selector, that is because we are now looking at a different element which has a different class. The element holds a date, well, a string representing the date.

We get the value in the same way. We are assuming now that the date format is dd/mm/yyyy. 

  var date = element.innerText;
 if(date === undefined){
    date = element.textContent;
  }

We split the string and store the values.

  var dateSplit = date.split("/");

We create a valid javascript Date object using the values from the String date, after the split. 

  var dateString = dateSplit[2]+ "/" + dateSplit[1] + "/" + dateSplit[0];
 var specifiedDate = new Date(dateString);

We get the current date:

  var today = new Date();

Now we can compare the dates.

  if(specifiedDate < today){
    element.addClassName('red-background');
  }

This is where you can make the comparison depending on what you are looking for. If the date is past or forthcoming, make the background of that element red.

The final code:

  document.observe("xwiki:livetable:newrow", function(evt){
    $$('.typedate').each(function(element){
     var date = element.innerText;
     if(date === undefined){
        date = element.textContent;
      }

     var dateSplit = date.split("/");

     var dateString = dateSplit[2]+ "/" + dateSplit[1] + "/" + dateSplit[0];
     var specifiedDate = new Date(dateString);

     var today = new Date();
 
     if(specifiedDate < today){
        element.addClassName('red-background');
      }
    });
  });

Don't forget to

{{velocity}}
#set($discard = $xwiki.jsx.use("Space.Document"))
#set($discard = $xwiki.ssx.use("Space.Document"))
#livetable(...) ## Livetable code goes here
{{/velocity}}

And attach a SSX object to the same document (or any other document) and define the style which you want the selected element/elements to have.

Tags:
     

Get Connected