PivotTable.js conditionally change color on text - javascript

So I'm working with PivotTable.js which has been a great help at work.
Right now though, I'm trying to get a filter going to change the color of cells or font within the cell depending on the value.
For example, if I have an array of dates in my dataset
dates = ["N/A", "4/12/2016", "7/9/2024", "7/9/2024", "4/1/2013"]
I want to make it so any dates before 6/1/2016 to change colors.
I have my data being passed in locally as a variable 'data' if that makes any difference
$(function(){
var derivers = $.pivotUtilities.derivers;
var renderes = $.extend($.pivoUtilities.renderers, $.pivotUtilities.export_renderers);
$("#pivot_table").pivotUI(data, {
derivedAttributes: function(data){
// not sure how to access the css of the element from here
}
rows: [],
cols: ["Name", "Date", "Organization", "Cost"],
renderers: renderers,
rendererName: "Table"
});
});
I've tried going into derivedAttributes, but everything I tried wasn't working.
Any help or brainstorming would be much appreciated on this

So...I actually solved it on my own haha...
One of the great things about PivotTable.js is the flexibility in options and sorting. So I used the onRefresh attribute and fed it this function
onRefresh: function() {
var $labels = $('.pvtRowLabel')
var today = new Date();
var d = today.getDate();
var m = today.getMonth()+1;
var y = today.getFullYear();
var date;
var dateReg = /^\d{1,2}[\/]\d{1,2}[\/]\d{4}$/;
// Goes through each cell with the class '.pvtRowLabel'
for (var i=0; i<$labels.length; i++) {
if ($labels[i].innerHTML.match(dateReg)) {
date = $labels[i].innerHTML.split('/');
if (Number(date[2]) == y) {
if (Number(date[0]) == m) {
if (Number(date[1]) <= d) {
$('.pvtRowLabel').eq(i).addClass('expired');
}
} else if (Number(date[0]) < m) {
$('.pvtRowLabel').eq(i).addClass('expired');
}
} else if (Number(date[2]) < y) {
$('.pvtRowLabel').eq(i).addClass('expired');
}
}
};
},
After that, just use a css selecter to specify the color you want to use
.expired { background-color: #F08080 !important; }
The problem with my solution is that it adds more strain on the browser since it's checking the DOM and adding classes every time the table is refreshed. I'm not sure if there's a way to accomplish this when it's first rendered, so those cells are always going to be labeled as expired when generated.

Here's one solution I found to change the font color of a single row in the table, say row no. 5:
$("#pivot-table").pivotUI(data, {
...
onRefresh: function (config) {
// Show row no.5 as red
$("#pivot-table").find('.pvtVal.row5').css('color', 'red');
},
...
});

I did custom coloring by editing the pivot.min.js file.
You may have to tweak the loop to segregate the data and add required css style in the js file.

Related

Multiple nowIndicators on fullCalendar

Since there is very little documentation of the nowIndicator ... is there a way of showing a similar element like the nowIndicator on the same page ?
For example... I want to show a green one starting at 01:00 and i want to show a blue one starting at 12:00
I'm not sure if this is the best solution, it's more like a hack. The idea is to change the background-color to today's row.
So you select all the rows because the interval of time is 30 minutes, you'll get 96 elements. (48 per day) the first 24 you don't need it because its the day before. You'll need the 25-73 elements because is today rows.
I wrote this function, that will be called on every dayRender.
function colorToday() {
var color = '#EEEEEE';
var fullArray = $('.fc-slats tr .fc-widget-content:nth-child(2)');
var todayArray = fullArray.slice(24, 72);
for(var i = 0; i < todayArray.length; i++) {
var data = $(todayArray[i]);
$(data).css('background', color);
}
}
And add this to the options:
dayRender: function (element) {
colorToday();
}
This is a JSFIDDLE
Like I said, I'm not sure if this is the best solution, but it does the work. Hope will help you.

AngularJS -- RZSlider update stepsArray

I'm trying to edit the rz-slider's labels that appear below the ticks. I am able to obtain the values and everything but if I try to update the stepsArray to the rzslider, it is not being updated. I couldn't find anything on how to update the legend values like this. I feel like I need to reinitialize or refresh the slider in some way but the refresh slider code as shown in https://github.com/angular-slider/angularjs-slider did not work:
vm.refreshSlider = function () {
$timeout(function () {
$scope.$broadcast('rzSliderForceRender');
});
};
The code that I am using is as follows. Currently the existing legend contains the word "Text" and I am just trying to check if I can update it to the numeric values just to check if it works but it isn't:
if(vm.legend != ""){
var stepCount = $("#stepCount").val();
vm.priceSlider.options.stepsArray = [];
for(var i = 1; i <= stepCount; i++){
vm.priceSlider.options.stepsArray.push({
value: i,
legend: i.toString()
});
}
vm.refreshSlider();
}
I am kinda new to angular and this is my first time working with the rzslider as well, so any help would be appreciated. Thank you.

Trying to call Javascript Function when SharePoint List View Web Part is filtered

I have some JavaScript that will colour row in a SharePoint list View web part depending on values in certain column.
This part works fine and the rows are coloured correctly upon page load.
The issue I have is that when the List is filtered (if you click on any of the column headers and arrange by Ascending or Descending order) the formatting is lost and the colours disappear.
I'm looking for a way for the formatting to stay or be reapplied after the filter action has completed.
If the page is refreshed, the Filter that was selected will remain in place and the colours will return.
I need a way for the colours to be reapplied once a filter has been applied instead of just on Page Load.
Thanks in advance.
Here is my current JS:
SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
OnPostRender: function(ctx) {
var rows = ctx.ListData.Row;
for (var i=0;i<rows.length;i++)
{
var trimmed = rows[i]["Age"]
var final = trimmed.replace(",", "");
var oneWeek = final < 7;
var oneToTwo = final >= 7 && final <= 14;
var twoOrMore = final > 14;
if (oneWeek)
{
var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
var tr = document.getElementById(rowElementId);
tr.style.backgroundColor = "#CCFFCC";
}
else if (oneToTwo)
{
var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
var tr = document.getElementById(rowElementId);
tr.style.backgroundColor = "#FFEECC";
}
else if (twoOrMore)
{
var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
var tr = document.getElementById(rowElementId);
tr.style.backgroundColor = "#FFCCCC";
}
}
}
}
);
So after a ton of investigation, it turns out my formatting was being overwritten at the last second after a sort or filter had taken place.
The solution was to add this to the end of the code:
ctx.skipNextAnimation = true;
This skipped the animation that shows all of the rows falling into place and allows my formatting to take effect as it should.
I would recommend to check the jquery.tablesorter.js out, this will hold your styles.
The ordering is on client side in your case, so you have to solve it there.
You can apply it for simple tables, and add a short js:
$(document).ready(function()
{
$("#myTable").tablesorter();
}
);

Adding additional data to Raphael.js text element

I am working on some sort of graph in Raphael.js, I made it first with D3 (which can be found here), but that didn't work as well in Internet Explorer. I've heard Raphael.js does it much better in IE.
So now I am trying to convert my D3 code to Raphael, I made some progress, but I have some problems trying to add additional data or an id to a text element, which I can use to modify the text of a specific element. In D3 I've used .attr("weight", weight) on a text element, and this works fine. But in Raphael, I can't get it to work.
I've tried giving the text an ID like this:
var text = paper.text((y * 50) + 20, (i * 50) + 15, weight).attr({
fill: '#000'
});
text.attr({
"font-size": 16,
"font-family": "Arial, Helvetica, sans-serif"
});
text.id = weight;
But still no luck in logging that ID. If it is not clear why I need this ID, check the before mentioned jsFiddle I made with D3, I need to get a specific element to change its text.
var grossRisks = [{
"weight": "1",
"number": "5"
}, {
"weight": "4",
"number": "6"
}];
function populateChart(riskArray) {
var element = document.getElementsByTagName("text"),
attr;
var loops = riskArray.length;
for (var i = 0; i < loops; i++) {
var obj = riskArray[i];
for (var x = 0; x < element.length; x++) {
attr = element[x];
if (/^text/.test(attr.nodeName)) {
console.log(
"Weight: " + attr.getAttribute("weight"));
if (attr.getAttribute("weight") == obj.weight) {
attr.textContent = obj.number;
}
}
}
}
I have tried multiple things like making a new set and adding data to that set, but I don't know where to go from that point, like how do I change the text of a set with a specific ID?
newSet[i] = paper.set();
newSet[i].push(rect, text);
newSet[i].attr({
cursor: 'pointer'
}).data('weight', weight);
newSet[i].click(function () {
console.log(this.id("weight"));
});
The not working code of Raphael can be found in this jsFiddle.
The issues are
You get the raw DOM nodes, and not the RaphaelJS wrapped objects (because you use document.getElementsByTagName)
You set data but try to access it through attr.
In the fiddle, the newSet is not correctly built becuase you use the i variable which goes from 1 to 5.. to calculate the index you need to account for both of the loop counter.
So the changes made are
When populating the newSet
var index = (i*5) + y;
newSet[index] = paper.set();
When clearing and populating the chart use newSet
newSet[x].forEach(function(item){
if (item.type=='text')
attr=item;
});
to get the text node.
Working demo at Have a look at http://jsfiddle.net/G94sQ/22/
You can ofcourse use id to simplify the code
To assign an id just use text.id = 'your-id'
When creating the newSet
text.id = 'weight-'+weight;
and when clearing/populating
attr = paper.getById('weight-'+obj.weight);
Working demo at http://jsfiddle.net/G94sQ/23/
(additionally: you are using jquery 1.11 in which the .toggle method just shows/hide the element and does not rotate the click functions as earlier versions. So I changed your code to 1.4.2 as a quick fix..)

Efficient way of changing background color of an element in CSS3 or HTML5

I need to change each item's color in a list after a reorder or removing one item, now I am using jquery's css method like below
$('li').css('background-color', color);
It works, but terribly slow, and sometimes the page will render the color incorrectly, even on Chrome, which is supposed to be fast. The list doesn't have many items, below 10, usually 5 - 7. So this performance is not acceptable. So I want to know if there is a better, faster way in CSS3, or HTML5. If not, if there is an walkaround or some kind of jquery solution?
The code for refreshing list items' color is as below. The index can be decided by a function and the color can decide color by it. The major issue I think is that changing background color trigger reflow or maybe rerendering.
function refreshListItemColor(liElements, colorGetter, indexGetter) {
colorGetter = colorGetter || (function (color) {
return color;
});
indexGetter = indexGetter || (function (liElement, index) {
return index;
});
liElements.each(function (index, liElement) {
index = indexGetter(liElement, index);
var data = ko.dataFor(liElement);
var indexColor = colorForIndex(index);
indexColor = colorGetter(indexColor, data);
if (indexColor !== $(liElement).css('background-color')) {
$(liElement).css('background-color', indexColor);
}
});
}
Update: using element.style['background-color'] won't do. The issue still remains. Another possible explanation for the lagging is that every list item itself has about 10 child elements, making change list item's color particularly expensive.
Update2: I'll try to ask a related question: is there a way to change the color of the background of the parent node without triggering a rerender of children elements?
Update3: I tried to add delay for each color change operation, like below
var delay = 100, step = 100;
liElements.each(function (index, liElement) {
index = indexGetter(liElement, index);
var data = ko.dataFor(liElement);
var indexColor = colorForIndex(index);
indexColor = colorGetter(indexColor, data);
if (indexColor !== $(liElement).css('background-color')) {
setTimeout(function () {
liElement.style['background-color'] = indexColor;
}, delay);
delay += step;
}
});
It seems can alleviate this issue a lot. I guess this will not solve the problem, but will reduce the impact to an acceptable level.
Could you use attribute selectors in your stylesheet?
[data-row="1"][data-col="3"]{
background-color: blue;
}
I noticed that If you want to select a whole row or column you have to use !important
[data-col="3"]{
background-color: blue !important;
}
(edit)Adding styles dynamically
Create a empty style tag with a div
<style type="text/css" id="dynamicstyle"></style>
and just append to it like any other tag
$("#dynamicstyle").append('[data-row="0"]{background-color:red !important;}');
for your case you can check whenever an element is added and add a row style since in theory the user could pile up all of the elements.
$(function () {
var maxRows = 0;
$("ul").bind("DOMSubtreeModified", updateStyleSheet);
function updateStyleSheet() {
var childCount = $("ul").children().length;
if (maxRows < childCount) {
maxRows = childCount;
var newRule = [
'[data-row="',
maxRows,
'"]{background-color:', ((maxRows % 2) ? "red" : "blue"),
' !important;}'].join('')
$("#dynamicstyle").append(newRule);
}
}
});
http://jsfiddle.net/PgAJT/126/
FizzBuzz rows http://jsfiddle.net/PgAJT/127/
Remove your "if", which may force browser to redraw/recompile/reflow latest CSS value.
if (indexColor !== $(liElement).css('background-color')) {
Yes, read are slow and as they will block write-combine.
Presumably, the colour is determined by the position of the element in the list.
Use nth-child or nth-of-type selectors in your stylesheet.
Hi i have just tried wat u need just check it..
http://jsbin.com/awUWAMeN/7/edit
function change()
{
var colors = ['green', 'red', 'purple'];
alert(colors)
$('.sd-list li').each(function(i) {
var index = $(this).index();
$(this).css('background-color', colors[index]);
});
}
I've created a simple test with 10 list items, each with 12 children and setting the background colour for every item each time Gridster's draggable.stop event fires. The change is pretty much instantaneous in IE11 and Chrome.
To me, this suggests it isn't the CSS rendering that's slow, but maybe the calculations determining which colours are for which elements.
This is the JavaScript I was using:
var colors = ['#000', '#001', '#002', '#003', '#004', '#005', '#006', '#007', '#008', '#009', '#00a', '#00b'];
$('.gridster ul').gridster({
widget_margins: [10, 10],
widget_base_dimensions: [120, 120],
draggable: {
stop: function (e, ui, $widget) {
refreshListItemColor();
}
}
});
function refreshListItemColor() {
var sortedElements = [];
$('ul > li:not(.preview-holder').each(function () {
sortedElements.push([this, this.getAttribute('data-col'), this.getAttribute('data-row')]);
});
sortedElements.sort(function (a, b) {
return a[1] - b[1] || a[2] - b[2];
});
for (var i = sortedElements.length - 1; i >= 0; i--) {
sortedElements[i][0].style.backgroundColor = colors[i];
}
}
How are you determining which colours to set on each list item?
I've find it fast to create a class with the css attributes you want and then add that class to the dom element you want the css attribute applied to. CSS rules appear without refresh.
css:
.bg-green{
background:green;
}
js:
$("#someDomId").toggleClass('bg-green','add');
A cool way of dealing with lists is to index the id of each list element as you create/alter it:
Create list:
for (i=0;i=m;i++){
var listElement = "<li id='"+i+">Some Content</div>";
$('ul').append(listElement);
}
Then instead of iterating through a dom element (which is expensive) you can run another for loop and alter each list element by selecting it's id.
for (i=0;i=m;i++){
$("#"+i).toggleClass('bg-green','add');
}

Categories