Sorry,
with http://www.ViewMaster365.com/#How I have been an avid promotor of the undocumented HTML trick (worked since SP2010, maybe even SP2007)
Like you I am amazed Microsoft actually disabled it, then again it already was disabled for Modern Experiences, so it was clear the HTML trick had no future
Must be kismet or faith or karma or just plain common sense,
I switched careers, and totally left the Microsoft Front-end world I worked in for 12 years,
the day before Microsoft really killed all Front-end Fun.
(They already killed UserCustomActions and CSR/JSLink Client Side Rendering in Modern Experiences, and SPFx sucks)
I don't even use Outlook anymore for email .... LOL
At the moment (june 13th, 2017) my tenant still does the HTML trick just fine.
And as you can read in the announcement, you can request Microsoft to delay implementation till September 10, 2017
The Solution
Is to switch back to the original 2007 workaround:
- Let the Column display the bare HTML
- Use a document ready script to process the DOM elements
- and rewrite to .innerHTML
Christophe
(also left the Microsoft business..LOL.. does something with games now)
blogged about this some 9 years ago
https://pathtosharepoint.wordpress.com/2008/09/01/using-calculated-columns-to-write-html/
Note; that script could do with an update to modern JavaScript...
I'll see if I can drag myself away from the modern WebComponents world I am in now for some minutes .. tomorrow.. or the day after.. or never
A day later:
No need for jQuery, replace HTML with Vanilla JavaScript
jQuery is f* slow with the contains filter
Since IE9 everyone can use the TreeWalker API (every other Browser supported it long ago..)
but ofcourse no jQuery addict wants to learn Modern and Faster techniques ;-)
If I had gotten a dime from every "Front-End developer" who actually knows about this API I still couldn't pay for a one months O365 subscription
Whack this code in a JS file, then reference it from a CEWP
remember! put it below all other ListView WebParts! because those DOM nodes need to exist
console.clear();
document.querySelectorAll('.ms-listviewtable').forEach(function (table) {
function getTextNodes(element) {
function acceptNode() {// stupid IE needs this function where other browsers don't.
return NodeFilter.FILTER_ACCEPT;
}
var safeFilter = acceptNode;
safeFilter.acceptNode = acceptNode;
return document.createTreeWalker(element, NodeFilter.SHOW_TEXT, safeFilter, false);
}
var TRrows = table.querySelectorAll("tr[role='row']");
var htmlNodes = [];
TRrows.forEach(function (TRrow) {// processing by row so you could do fancy Row actions
var tree = getTextNodes(TRrow);//standard since IE9, get TEXT nodes
while (textNode = tree.nextNode()) {//loop all found textnodes
console.log('textNode id:', TRrow.id, 'value:', textNode.nodeValue);
var isHTML = textNode.nodeValue.match(/<[a-zA-Z]>/);
if (isHTML) {
htmlNodes.push({
//store all data now so we don't have to do any DOM calls later
node: textNode,
parent: textNode.parentNode,
value: textNode.nodeValue
}
);
}
}
});
console.log('processing', htmlNodes.length, 'htmlNodes:', htmlNodes);
htmlNodes.forEach(function (htmlNode) {
console.log('processing HTML:', htmlNode);
var fragment = document.createElement('SPAN');
fragment.classList.add("processedHTML");
fragment.innerHTML = htmlNode.value;
htmlNode.parent.replaceChild(fragment, htmlNode.node);
//htmlNode.parent.style.background='lightgreen'; // for debugging purposes
});
});
Yes.. you can do this with 7 lines of jQuery...
But you need to load a 90 KB Library... slow!
And the jQuery code itself is about 30% slower!
jQuery slowness means: your users could see a screen flash from old content to new HTML content on larger pages
CSR / JSLink
OR use the above code in the OnPostRender
function of a JSLinked CSR file
All Pages
But executing on one page is no fun... execute it on every page wih a UserCustomAction ...
this very powerfull official technique has only been around since 2010 (but was killed by Microsoft in Modern Experiences)..
(If I would get a penny.....)
Remember, you then need to make sure it executes after the DOM is created (where jQuery lovers use $.ready())
So wrap it in something like:
document.addEventListener("DOMContentLoaded", function (event) {
[the above code goes here]
}
Before:
After:
Green marked are the only TextNodes converted to HTML
... Yes.. why not do the Column name as well.. think about the functionality you can add :-)