I followed example here http://blog.alexboev.com/2012/08/custom-callouts-in-sharepoint-2013.html to create callout control.
Now I'm trying to add Preview pane for documents(images, pptx, pdf etc..) in callout control. (similar to the OOTB functionality when user clicks on ellipse in document library item or search result).
How can I achieve this in my own callout control.
See SharePoint 2013 - Custom CallOut with File Preview.
It provide a working code sample:
function getCallOutFilePreviewBodyContent(urlWOPIFrameSrc, pxWidth, pxHeight) {
var callOutContenBodySection = '<div class="js-callout-bodySection">';
callOutContenBodySection += '<div class="js-filePreview-containingElement">';
callOutContenBodySection += '<div class="js-frame-wrapper" style="line-height: 0">';
callOutContenBodySection += '<iframe style="width: ' + pxWidth + 'px; height: ' + pxHeight + 'px;" src="' + urlWOPIFrameSrc + '&action=interactivepreview&wdSmallView=1" frameborder="0"></iframe>';
callOutContenBodySection += '</div></div></div>';
return callOutContenBodySection;
}
function OpenItemFilePreviewCallOut(sender, strTitle, urlWopiFileUrl) {
RemoveAllItemCallouts();
var openNewWindow = true; //set this to false to open in current window
var callOutContenBodySection = getCallOutFilePreviewBodyContent(urlWopiFileUrl, 379, 252);
var c = CalloutManager.getFromLaunchPointIfExists(sender);
if (c == null) {
c = CalloutManager.createNewIfNecessary({
ID: 'CalloutId_' + sender.id,
launchPoint: sender,
beakOrientation: 'leftRight',
title: strTitle,
content: callOutContenBodySection,
contentWidth: 420
});
var customAction = new CalloutActionOptions();
customAction.text = 'Open';
customAction.onClickCallback = function (event, action) {
if (openNewWindow) {
window.open(urlItemUrl);
RemoveItemCallout(sender);
} else {
window.location.href = urlItemUrl;
}
};
var _newCustomAction = new CalloutAction(customAction);
c.addAction(_newCustomAction);
}
c.open();
}
Usage:
<a id="CallOutExample" onclick="OpenItemFilePreviewCallOut(this, 'My Title','<WopiFileUrl>')" title="CallOut With File Preview" h ref="#">Call Out with File Preview</a>
Related
I want to use client side rendering(js link) for document library, the challenge for me is Sharepoint document library will be created dynamically when the remote event receiver triggers.
I know we need to pass js link reference in elements.xml file, but in my case list will be created later, so how can I achieve it?
Thanks in advance.
You can add script (JSLink) programmatically, after your condition event receiver:
C#:
using (SPSite site = new SPSite("http://sp/sites/test"))
{
SPWeb web = site.RootWeb;
SPFile page = web.GetFile("SitePages/Test.aspx");
page.CheckOut();
using (SPLimitedWebPartManager wpmgr = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
XmlElement p = new XmlDocument().CreateElement("p");
p.InnerText = "<script type='text/javascript'>alert('Hello World');</script>";
ContentEditorWebPart cewp = new ContentEditorWebPart
{
Content = p
};
wpmgr.AddWebPart(cewp, "Header", 0);
}
page.CheckIn(String.Empty);
}
JS:
var siteUrl = '/sites/MySiteCollection';
var serverRelativeUrl = '/sites/MySiteCollection/Default.aspx';
function addWebPart() {
var clientContext = new SP.ClientContext(siteUrl);
var oFile = clientContext.get_web().getFileByServerRelativeUrl(serverRelativeUrl);
var limitedWebPartManager = oFile.getLimitedWebPartManager(SP.WebParts.PersonalizationScope.shared);
var webPartXml = '<?xml version=\"1.0\" encoding=\"utf-8\"?>' +
'<WebPart xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"' +
' xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"' +
' xmlns=\"http://schemas.microsoft.com/WebPart/v2\">' +
'<Title>My Web Part</Title><FrameType>Default</FrameType>' +
'<Description>Use for formatted text, tables, and images.</Description>' +
'<IsIncluded>true</IsIncluded><ZoneID></ZoneID><PartOrder>0</PartOrder>' +
'<FrameState>Normal</FrameState><Height /><Width /><AllowRemove>true</AllowRemove>' +
'<AllowZoneChange>true</AllowZoneChange><AllowMinimize>true</AllowMinimize>' +
'<AllowConnect>true</AllowConnect><AllowEdit>true</AllowEdit>' +
'<AllowHide>true</AllowHide><IsVisible>true</IsVisible><DetailLink /><HelpLink />' +
'<HelpMode>Modeless</HelpMode><Dir>Default</Dir><PartImageSmall />' +
'<MissingAssembly>Cannot import this Web Part.</MissingAssembly>' +
'<PartImageLarge>/_layouts/images/mscontl.gif</PartImageLarge><IsIncludedFilter />' +
'<Assembly>Microsoft.SharePoint, Version=13.0.0.0, Culture=neutral, ' +
'PublicKeyToken=94de0004b6e3fcc5</Assembly>' +
'<TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName>' +
'<ContentLink xmlns=\"http://schemas.microsoft.com/WebPart/v2/ContentEditor\">' + '/sites/SiteAssets/Test.js</ContentLink>' +
'<Content xmlns=\"http://schemas.microsoft.com/WebPart/v2/ContentEditor\">' +
'<![CDATA[This is a first paragraph!<DIV> </DIV>And this is a second paragraph.]]></Content>' +
'<PartStorage xmlns=\"http://schemas.microsoft.com/WebPart/v2/ContentEditor\" /></WebPart>';
var oWebPartDefinition = limitedWebPartManager.importWebPart(webPartXml);
this.oWebPart = oWebPartDefinition.get_webPart();
limitedWebPartManager.addWebPart(oWebPart, 'Left', 1);
clientContext.load(oWebPart);
clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function onQuerySucceeded() {
alert('Web Part added: ' + oWebPart.get_title());
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
In Add Link page, is it possible to change the default values like title, address, show these links to, by using URL parameters?
According to this, it seems possible in sharepoint2010. Does anyone know whether it works in 2013??
If not, is it possible to add a link by post REST API??
This problem can be solved by the steps below.
Add a custom action. Just follow the steps here.
In my case code is as below
SP.SOD.executeFunc("callout.js", "Callout", function() {
var itemCtx = {};
itemCtx.Templates = {};
itemCtx.BaseViewID = 'Callout';
// Define the list template type
itemCtx.ListTemplateType = 101;
itemCtx.Templates.Footer = function(itemCtx) {
// context, custom action function, show the ECB menu (boolean)
return CalloutRenderFooterTemplate(itemCtx, AddCustomAction, true);
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);
});
function AddCustomAction(renderCtx, calloutActionMenu) {
// Add your custom action
calloutActionMenu.addAction(new CalloutAction({
text: "FAVORITE",
// tooltip: 'This is your custom action',
onClickCallback: function() {
CreateCustomNewQuickLink(renderCtx.CurrentItem.FileLeafRef, renderCtx.CurrentItem.FileRef);
}
}));
// Show the default document library actions
CalloutOnPostRenderTemplate(renderCtx, calloutActionMenu);
}
function CreateCustomNewQuickLink(title, url) {
var urlAddress = $(location).attr('protocol') + "//" + $(location).attr('host') + '/_Layouts/quicklinksdialogformTEST.aspx?Mode=Link' +
'&title=' + encodeURIComponent(title) +
'&url=' + encodeURIComponent(url);
ShowNewQuicklinkPopup(urlAddress, PageRefreshOnDialogClose);
}
Create a new add link page which is copied from "quicklinksdialogform.aspx". I add some javascript as below.
$(init)
function init() {
var args = new Object();
args = GetUrlParms();
if (args["title"] != undefined) {
$(".ms-long")[0].value = decodeURIComponent(args["title"]);
}
if (args["url"] != undefined) {
$(".ms-long")[1].value = decodeURIComponent(args["url"]);
}
}
function GetUrlParms() {
var args = new Object();
var query = location.search.substring(1);
var pairs = query.split("&");
for (var i = 0; i < pairs.length; i++) {
var pos = pairs[i].indexOf('=');
if (pos == -1) continue;
var argname = pairs[i].substring(0, pos);
var value = pairs[i].substring(pos + 1);
args[argname] = unescape(value);
}
return args;
}
It works like below
I am printing the AnyGantt chart using the print API, but all I can print is the part I am viewing, kind of a snapshot of the current screen.
Is there an option to somehow print all the items present in the gantt (at least vertically, something like scrolling down the chart and capturing all the items, event if they are not visible at the moment) in the visible time range?
Thank you.
This can be implemented with a few code tricks. The idea is to expand the chart's div container to show all existing rows in gantt chart, then print it, and finally collapse the container's div back. Unfortunately, there's no other solution for this now. The snippet below may not work in stackoverflow playground. I will leave a link to the same sample in AnyChart Playground which provides printing features.
anychart.onDocumentReady(function () {
// The data used in this sample can be obtained from the CDN
// https://cdn.anychart.com/samples/gantt-charts/activity-oriented-chart/data.js
anychart.data.loadJsonFile('https://cdn.anychart.com/samples/gantt-charts/activity-oriented-chart/data.json', function (data) {
var stage = anychart.graphics.create("container");
// create data tree
var treeData = anychart.data.tree(data, 'as-table');
// create project gantt chart
var chart = anychart.ganttProject();
// set data for the chart
chart.data(treeData);
// set start splitter position settings
chart.splitterPosition(370);
// get chart data grid link to set column settings
var dataGrid = chart.dataGrid();
// set first column settings
dataGrid.column(0)
.title('#')
.width(30)
.labels({hAlign: 'center'});
// set second column settings
dataGrid.column(1)
.labels()
.hAlign('left')
.width(180);
// set third column settings
dataGrid.column(2)
.title('Start Time')
.width(70)
.labels()
.hAlign('right')
.format(function () {
var date = new Date(this.actualStart);
var month = date.getUTCMonth() + 1;
var strMonth = (month > 9) ? month : '0' + month;
var utcDate = date.getUTCDate();
var strDate = (utcDate > 9) ? utcDate : '0' + utcDate;
return date.getUTCFullYear() + '.' + strMonth + '.' + strDate;
});
// set fourth column settings
dataGrid.column(3)
.title('End Time')
.width(80)
.labels()
.hAlign('right')
.format(function () {
var date = new Date(this.actualEnd);
var month = date.getUTCMonth() + 1;
var strMonth = (month > 9) ? month : '0' + month;
var utcDate = date.getUTCDate();
var strDate = (utcDate > 9) ? utcDate : '0' + utcDate;
return date.getUTCFullYear() + '.' + strMonth + '.' + strDate;
});
// calculate height
var traverser = treeData.getTraverser();
var itemSum = 0;
var rowHeight = chart.defaultRowHeight();
while (traverser.advance()){
if (traverser.get('rowHeight')) {
itemSum += traverser.get('rowHeight');
} else {
itemSum += rowHeight;
}
if (chart.rowStroke().thickness != null) {
itemSum += chart.rowStroke().thickness;
} else {
itemSum += 1;
}
}
itemSum += chart.headerHeight();
//customize printing
var menu = chart.contextMenu();
menu.itemsFormatter(function(items) {
items['print-chart'].action = function() {
document.getElementById('container').style.height = String(itemSum) + 'px';
setTimeout(function() {
chart.print();
setTimeout(function() {
document.getElementById('container').style.height = '100%';
},5000);
},1000);
}
return items;
});
chart.container(stage).draw();
chart.zoomTo(951350400000, 954201600000);
});
});
html, body, #container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
<link href="https://cdn.anychart.com/releases/8.2.1/fonts/css/anychart-font.min.css" rel="stylesheet"/>
<link href="https://cdn.anychart.com/releases/8.2.1/css/anychart-ui.min.css" rel="stylesheet"/>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-bundle.min.js"></script>
<div id="container"></div>
We are glad to notify that we have created a JS module for printing large Gantt charts. You can get the link to the module and sample of using it in the comment below.
This module exports enableLargeGanttPrint({Object: chart}) function, which gets the chart instance and implements printing functionality. To print the chart executes right mouse click on the chart and choose 'print' option. This will call standard browser print for prepared Gantt chart.
Cisar verifies the jslink is getting called correctly but rendering only happens when I open the file with the cisar inspector. Weird.
(function () {
var overrideCtx = {};
overrideCtx.Templates = {};
overrideCtx.Templates.Header = "<div class='row'><div class='col-md- 8'>Title</div><div class='col-md-1'>Screen 16x9</div><div class='col-md-1'>Print</div><div class='col-md-2'>Updated</div>";
overrideCtx.Templates.Footer = "</div>";
overrideCtx.Templates.Item = CustomItem;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();
function CustomItem(ctx) {
// Build a listitem entry for every announcement in the list.
var ret = "<div class='col-md-8'>" + ctx.CurrentItem.Title + "</div><div class='col-md-1'><a href='https://domain/subsite/library/" + ctx.CurrentItem.FileLeafRef + "'><i class='fa fa-tv fa-2x'></i></a></div><div class='col-md-1'><a href='" + ctx.CurrentItem.Print_x0020_4x3 + "'><i class='fa fa-print fa-2x'></i></a> </div>" "<div class='col-md-2'>" + ctx.CurrentItem.Updated + " </div>"
;
return ret;
}
I am using SPD 2010 and SharePoint Sever 2010.
Using conditional formatting I'm trying to format a list so that if today's date is greater than 30 days before the start date column a cell will turn red.
I've tried several XPath expressions from other Stackoverflow entries but nothing has worked. I'm wondering if I am even adding the XPath expression in the right place: In SPD I am selecting a date from the desired column, choosing "Conditional Formatting", selecting "Format Column", selecting "Advanced" and putting my expressions in the XPath expression textbox.
Appreciate your help!
I'm going to suggest a non-Xpath approach, but if you're looking to stick with Xpath you should take a look at the answers on this similar question.
After struggling with this problem myself, I've taken to using JavaScript for conditional formatting, since it can work with dates (including the current date), numbers, and strings, and it can manipulate HTML pretty easily.
A bit of client side code can automatically:
Detect whether a list of conditional formatting rules exists
Create the list if necessary
Provide an interface for creating new rules (which are stored as list items) that should apply to the current page
Loop through all the current page's rules and apply them to any list view web parts detected on the same page
The nicest part of this approach is that I can add the web part to a page and just let the business users configure the formatting to their liking; no need for me to be further involved whenever they want to change something.
I put the combined HTML/CSS/JavaScript in a text file that can be saved to a document library somewhere in my site collection. To then add the conditional formatting to page, I just add a content editor web part to the page and set its "content link" property to be the path to the text file.
The content editor web part then displays a gray "Conditional Formatting" button that the user can click to view and modify the formatting rules, as seen in the screen shot below.
Here's the conditional formatting code for SharePoint 2010 that I use in my text file:
<div id="_conditional_formatting_link" style="display:none; ">
<div unselectable="on" style="display:inline-block; user-select:none; cursor:pointer; padding: 3px; background-color:#9b9b9b; color:white; border:1px solid #888;" onclick="javascript:var rules = document.getElementById('_conditional_formatting'); if(rules.style.display == 'none'){rules.style.display = 'inline-block'}else{rules.style.display = 'none'}">
Conditional Formatting
</div>
</div>
<div id="_conditional_formatting" style="display:none;background-color:#dfdfdf; border: 1px solid black; width:95%; max-width:1100px;">
<a style="border:0px;padding:5px;float:right;" title="Reapply Formatting" href="javascript:getConditions(false);">
<img style="border:0px;" src="/_layouts/images/staticrefresh.gif"/>
</a>
<ol id="_conditional_formatting_rules"></ol>
<div style="text-align:right; ">
<div id="_add_conditional_formatting_rule" unselectable="on" onclick="javascript: Add_Conditional_Formatting();" style="user-select:none; cursor:pointer; padding: 3px; margin: 3px; display:inline-block; background-color:#9b9b9b; border:1px solid #888; color:white;">Add Rule</div>
</div>
</div>
<script>
this.cfl = this.cfl ? this.cfl : new Object(null);
var conditionalFormattingList = "Conditional Formatting";
function getConditions(reloadRules) {
/* if reloadRules, query the conditions list and get all the rules. Otherwise just reapply the ones in memory to the current document. */
if (typeof reloadRules == "undefined") { reloadRules = true; }
if (reloadRules) {
var conditionalFormattingRules = document.getElementById("_conditional_formatting_rules");
while (conditionalFormattingRules.children.length > 0) { /* Clear out the currently displayed list of rules. */
conditionalFormattingRules.removeChild(conditionalFormattingRules.children[0]);
}
this.cfl.clientContext = new SP.ClientContext();
this.cfl.user = cfl.clientContext.get_web().get_currentUser();
var list = cfl.clientContext.get_web().get_lists().getByTitle(conditionalFormattingList);
var camlQuery = new SP.CamlQuery();
var folder = list.get_rootFolder();
camlQuery.set_viewXml('<View><Query><Where><Eq><FieldRef Name=\'URL\' /><Value Type=\'Text\'>' + document.location.pathname + '</Value></Eq></Where><OrderBy><FieldRef Name=\'Priority\' /><FieldRef Name=\'Name\' /></OrderBy></Query></View>');
this.cfl.items = list.getItems(camlQuery);
cfl.clientContext.load(cfl.user);
cfl.clientContext.load(list, 'EffectiveBasePermissions');
cfl.clientContext.load(cfl.items);
cfl.clientContext.load(folder);
}
this.cfl.clientContext.executeQueryAsync(
Function.createDelegate(this,
function () {
var Me = this.cfl.user.get_title();
if (reloadRules) {
var baseFormUrl = folder.get_serverRelativeUrl() + "/EditForm.aspx?ID=";
/* Figure out if the current user has access to create or edit items on the Conditional Formatting list */
var perms = list.get_effectiveBasePermissions();
this.cfl.hasEdit = perms.has(SP.PermissionKind.editListItems);
this.cfl.hasCreate = perms.has(SP.PermissionKind.addListItems);
/* Fill an array with our formatting rules */
this.cfl.targets = [];
var itemEnumerator = this.cfl.items.getEnumerator();
while (itemEnumerator.moveNext()) {
var item = itemEnumerator.get_current();
var targ = new Object(null);
targ.column = item.get_item("Column");
targ.comparison = item.get_item("Comparison");
targ.style = item.get_item("Style");
targ.scope = item.get_item("Scope");
targ.type = item.get_item("Type");
targ.value = item.get_item("Value"); if (targ.value == null) { targ.value = ""; }
targ.id = item.get_item("ID");
targ.offset = item.get_item("Offset");
cfl.targets.push(targ);
}
}
if (!this.cfl.hasCreate) { document.getElementById("_add_conditional_formatting_rule").style.display = "none"; }
for (var targetIterator = 0, len = cfl.targets.length; targetIterator < len; targetIterator++) {
var currentTarget = cfl.targets[targetIterator];
if (reloadRules) {
var rulelist = document.getElementById("_conditional_formatting_rules");
var ruletoadd = document.createElement("li");
var comparisondisplay = currentTarget.type.indexOf("Field") != -1 ? "value of the <b>" + currentTarget.value + "</b> column" : "<b>'" + currentTarget.value + "'</b>";
if (currentTarget.type == "Special" || currentTarget.type == "Number") {
if (currentTarget.value.toString().toLowerCase() == "[me]") { comparisondisplay = "<b>[Me](" + Me + ")</b>"; }
else { comparisondisplay = "<b>" + currentTarget.value + "</b>"; }
}
if (currentTarget.value == "") { comparisondisplay = "<b>(blank)</b>"; }
if (currentTarget.offset != null) {
comparisondisplay += "<b>" + (currentTarget.offset < 0 ? " " : " +") + currentTarget.offset + "</b>"
}
var editLink = this.cfl.hasEdit ? "<div style='display:inline-block;cursor:pointer;' onclick='SP.UI.ModalDialog.commonModalDialogOpen(" + '"' + baseFormUrl + currentTarget.id + '&Source=' + document.location.pathname + '"' + ",{},refreshPageConditions); '>" + "<img src='/_layouts/images/EDITITEM.GIF' style='vertical-align:middle;' title='Customize' alt='Customize'/>" + " </div>" : "";
ruletoadd.innerHTML = editLink + "When <b>" + currentTarget.column + "</b> "
+ currentTarget.comparison + " " + comparisondisplay
+ ", apply {" + (currentTarget.style == null ? "remove all formatting" : "<span style='" + currentTarget.style + "'>" + currentTarget.style + "</span>") + "} to the <b>" + currentTarget.scope + "</b>" + ((currentTarget.scope != "Cell" && currentTarget.scope != "Row") ? " column" : "");
rulelist.appendChild(ruletoadd);
}
var tables = document.querySelectorAll("table.ms-listviewtable"); /* Should get all the list view web parts on the page. */
var t_i = 0;
while (t_i < tables.length) {
var columnIndex = null; /* Index of the column to compare against */
var valueIndex = null; /* Index of a second column from which to pull the value to compare */
var styleTargetIndex = null; /* Index of a column to apply formatting to */
var thisTable = tables[t_i];
var headings = thisTable.rows[0].cells;
var h_i = 0;
while (h_i < headings.length) { /* Check all the column headings... */
var thisHeading = headings[h_i].querySelector("div:first-child");
if (thisHeading != null) {
/* In Internet Explorer, the headings have a DisplayName attribute you can grab. If that's not there, just grab the innerText or textContent */
var dispname = thisHeading.DisplayName ? thisHeading.DisplayName : (thisHeading.innerText ? thisHeading.innerText : thisHeading.textContent);
dispname = dispname.replace(/^\s+|\s+$/g, '');/* removes leading and trailing whitespace */
if (currentTarget.scope != "Cell" && currentTarget.scope != "Row") {
/*If the scope isn't Cell or Row, see if this is the cell to which the formatting should applied */
if (dispname == currentTarget.scope) { styleTargetIndex = h_i; }
}
if (currentTarget.type.indexOf("Field") != -1) {
/*If the value type is a Field, check to see if this is the field whose value we care about */
if (dispname == currentTarget.value.toString()) { valueIndex = h_i; }
}
if (dispname == currentTarget.column) { columnIndex = h_i; }
}
h_i += 1;
}
if (columnIndex != null) { /* If we found a matching heading, let's try to apply the rules... */
var rows = thisTable.rows;
for (var i = (rows.length > 0 ? 1 : 0) ; i < rows.length; i++) {
var cells = rows[i].children;
if (cells.length <= columnIndex) { continue }
var innerLink = cells[columnIndex].querySelector("a"); /* I want to specifically target links so that we can change their text color if necessary */
/* Populate valueToEval with the text value of the current cell, or its inner link if it has one */
var valueToEval = cells[columnIndex].innerText ? (innerLink != null ? innerLink.innerText : cells[columnIndex].innerText) : (innerLink != null ? innerLink.textContent : cells[columnIndex].textContent);
if (typeof (valueToEval) == "undefined") { valueToEval = "" } /* Treat empties as blanks */
var listValueToCompareAgainst = null;
if (valueIndex != null) { /* valueIndex only has a value if we need to grab the comparison value from another column on the list */
valueLink = cells[valueIndex].querySelector("a");
listValueToCompareAgainst = cells[valueIndex].innerText ? (valueLink != null ? valueLink.innerText : cells[valueIndex].innerText) : (valueLink != null ? valueLink.textContent : cells[valueIndex].textContent);
}
var needsStyling = false;
switch (currentTarget.type) {
case "Number":
if (!isNaN(Number(valueToEval))) {
valueToEval = +(valueToEval);
}
if (!isNaN(Number(currentTarget.value))) {
currentTarget.value = +(currentTarget.value);
}
break;
case "Date":
valueToEval = new Date(valueToEval);
currentTarget.value = new Date(currentTarget.value);
if (currentTarget.offset != null) {
currentTarget.value.setDate(currentTarget.value.getDate() + +(currentTarget.offset));
}
break;
case "Text": /* Already covered, bro */ break;
case "Date Field":
valueToEval = new Date(valueToEval);
currentTarget.value = new Date(listValueToCompareAgainst);
if (currentTarget.offset != null) {
currentTarget.value.setDate(currentTarget.value.getDate() + +(currentTarget.offset));
}
break;
case "Text Field": currentTarget.value = listValueToCompareAgainst; break;
case "Number Field":
if (!isNaN(Number(listValueToCompareAgainst))) {
currentTarget.value = listValueToCompareAgainst;
if (currentTarget.offset != null) {
currentTarget.value += Number(currentTarget.offset);
}
}
if (!isNaN(Number(valueToEval))) {
valueToEval = Number(valueToEval);
}
break;
case "Special":
if (currentTarget.value.toLowerCase) {
if (currentTarget.value.toLowerCase() == "[me]") { currentTarget.value = Me }
else if (currentTarget.value.toLowerCase().indexOf("[today]") != -1) {
var dateDifference = Number(currentTarget.value.toLowerCase().replace("[today]", "").replace(" ", "").replace("+", ""));
currentTarget.value = new Date();
if (!isNaN(dateDifference)) { currentTarget.value.setDate(currentTarget.value.getDate() + dateDifference); }
if (currentTarget.offset != null) {
currentTarget.value.setDate(currentTarget.value.getDate() + Number(currentTarget.offset));
}
valueToEval = new Date(valueToEval);
}
} else { valueToEval = new Date(valueToEval); }
break;
}
switch (currentTarget.comparison) {
case "Greater Than or Equal To": needsStyling = (valueToEval >= currentTarget.value); break;
case "Greater Than": needsStyling = (valueToEval > currentTarget.value); break;
case "Less Than or Equal To": needsStyling = (valueToEval <= currentTarget.value); break;
case "Less Than": needsStyling = (valueToEval < currentTarget.value); break;
case "Equal To": needsStyling = (valueToEval == currentTarget.value); break;
case "Not Equal To": needsStyling = (valueToEval != currentTarget.value); break;
case "Contains": needsStyling = (valueToEval.indexOf(currentTarget.value) != -1); break;
case "Does Not Contain": needsStyling = (valueToEval.indexOf(currentTarget.value) == -1); break;
}
if (needsStyling) {
var links;
if (currentTarget.scope != "Row") {
var targetIndex = (styleTargetIndex != null) ? styleTargetIndex : columnIndex;
cells[targetIndex].setAttribute("style", currentTarget.style);
links = cells[targetIndex].querySelectorAll("a");
} else {
rows[i].setAttribute("style", currentTarget.style);
for (var j = 0; j < cells.length; j++) {
cells[j].setAttribute("style", currentTarget.style);
}
links = rows[i].querySelectorAll("a");
}
for (var j = 0; j < links.length; j++) {
if (links[j].title != "Open Menu") {
links[j].setAttribute("style", currentTarget.style);
links[j].style.backgroundColor = "";
}
links[j].style.border = "0px";
}
}
}
}
t_i += 1;
}
}
document.getElementById("_conditional_formatting_link").style.display = "inline-block";
}
),
Function.createDelegate(this,
function (sender, args) { /* There was an error accessing the list. Time to create it! */
var lci = new SP.ListCreationInformation();
lci.set_title(conditionalFormattingList);
lci.set_templateType(SP.ListTemplateType.genericList);
var condition_list = clientContext.get_web().get_lists().add(lci);
clientContext.load(condition_list);
var colTitle = condition_list.get_fields().getByTitle("Title");
colTitle.set_required(false); colTitle.set_hidden(true); colTitle.update();
condition_list.update();
var colColumn = condition_list.get_fields().addFieldAsXml('<Field Description=\'The column to compare (must be visible on the page)\' DisplayName=\'Column\' Type=\'Text\'/>', true, SP.AddFieldOptions.defaultValue);
var colComparison = condition_list.get_fields().addFieldAsXml('<Field Description=\'\' Type=\'Choice\' DisplayName=\'Comparison\' Format=\'Dropdown\' FillInChoice=\'FALSE\'><Default>Equal To</Default><CHOICES><CHOICE>Greater Than</CHOICE><CHOICE>Greater Than or Equal To</CHOICE><CHOICE>Equal To</CHOICE><CHOICE>Less Than or Equal To</CHOICE><CHOICE>Less Than</CHOICE><CHOICE>Not Equal To</CHOICE><CHOICE>Contains</CHOICE><CHOICE>Does Not Contain</CHOICE></CHOICES></Field>', true, SP.AddFieldOptions.defaultValue);
var colValue = condition_list.get_fields().addFieldAsXml('<Field Description=\'The value or the name of a column to compare against\' DisplayName=\'Value\' Type=\'Text\'/>', true, SP.AddFieldOptions.defaultValue);
var colType = condition_list.get_fields().addFieldAsXml('<Field Description=\'Indicate the type of value you are comparing against. Choose Special if using the [Me] or [Today] placeholders.\' Type=\'Choice\' DisplayName=\'Type\' Format=\'Dropdown\' FillInChoice=\'FALSE\'><Default>Text</Default><CHOICES><CHOICE>Date</CHOICE><CHOICE>Number</CHOICE><CHOICE>Text</CHOICE><CHOICE>Date Field</CHOICE><CHOICE>Number Field</CHOICE><CHOICE>Text Field</CHOICE><CHOICE>Special</CHOICE></CHOICES></Field>');
var colOffset = condition_list.get_fields().addFieldAsXml('<Field Description=\'Optionally specify a number to offset the value by when comparing against a number or date.\' DisplayName=\'Offset\' Type=\'Number\' />', true, SP.AddFieldOptions.defaultValue);
var colStyle = condition_list.get_fields().addFieldAsXml('<Field NumLines=\'4\' Description=\'The CSS to apply to when the condition is met. Leave blank to remove formatting. Example syntax: background-color:darkred; color:white; font-weight:bold;\' DisplayName=\'Style\' Type=\'Note\' />', true, SP.AddFieldOptions.defaultValue);
var colScope = condition_list.get_fields().addFieldAsXml('<Field Description=\'The scope to which the style should be applied. Choose Row, Cell, or specify a column name.\' Type=\'Choice\' DisplayName=\'Scope\' Format=\'Dropdown\' FillInChoice=\'TRUE\'><Default>Cell</Default><CHOICES><CHOICE>Cell</CHOICE><CHOICE>Row</CHOICE></CHOICES></Field>', true, SP.AddFieldOptions.defaultValue);
var colPriority = condition_list.get_fields().addFieldAsXml('<Field Description=\'Priority determines which styles are applied in case of overlapping conditions. Higher numbers are applied later.\' DisplayName=\'Priority\' Type=\'Number\' />', true, SP.AddFieldOptions.defaultValue);
var colUrl = condition_list.get_fields().addFieldAsXml('<Field Description=\'Page where this rule should be applied\' DisplayName=\'URL\' Type=\'Text\'/>', true, SP.AddFieldOptions.defaultValue);
clientContext.executeQueryAsync(
Function.createDelegate(this, function () { getConditions(); }),
Function.createDelegate(this, function (sender, args) { document.getElementById("_conditional_formatting").innerHTML = ("An error occcurred while trying to apply conditional formatting to the list for you. Error details: " + args.get_message() + " " + args.get_stackTrace()); document.getElementById("_conditional_formatting_link").style.display = "inline-block"; }));
}
));
}
/* This method is called when the Add Rule button is clicked. */
function Add_Conditional_Formatting() {
/* Create a new item with only the URL and Priority fields filled out */
var currUrl = document.location.pathname;
var clientContext = new SP.ClientContext();
var itemCreateInfo = new SP.ListItemCreationInformation();
var newItem = clientContext.get_web().get_lists().getByTitle(conditionalFormattingList).addItem(itemCreateInfo);
newItem.set_item('URL', currUrl);
/* Give the new item a priority that will put it at the end of the list. This is kind of a hack since the highest priority is not necessarily the rulecount. */
newItem.set_item('Priority', document.getElementById("_conditional_formatting_rules").children.length + 1);
newItem.update();
clientContext.load(newItem);
clientContext.executeQueryAsync(Function.createDelegate(this, function () {
getConditions(); /* Reload to refresh the rules list after adding the item */
}), Function.createDelegate(this, function (sender, args) { alert(args.get_message()); }));
}
/* This method is called when the Edit Item dialog box is closed. It refreshes the page it the item was saved. */
function refreshPageConditions(result) { if (result != SP.UI.DialogResult.cancel) { window.location.replace(document.location.href) } }
ExecuteOrDelayUntilScriptLoaded(function () {
getConditions();
/* If there are any collapsible sections on the page, keep checking to see whether formatting needs to be reapplied */
this.cfl.TableRowCount = 0;
if (document.querySelector("img[alt='expand']") != null) {
setInterval(function () {
var tempTableRowCount = document.querySelectorAll("tr").length;
if (tempTableRowCount != this.cfl.TableRowCount) {
/* Only reapply formatting if the count of table rows is different than it was previously */
this.cfl.TableRowCount = tempTableRowCount;
getConditions(false) /* Passing false reapplies loaded rules without re-querying the SharePoint list */
}
}, 1000)
}
}, "SP.JS");
</script>