I have a summary single-line text column in SharePoint 2007 that is a truncation of a multi-line text column. Going through the complicated process to get there, it turns into text which then needs to be converted back to HTML, so that the tags like <div> don't show. The following code works if the multi-line column is rich text, but not if it's enhanced rich text. Does anyone have the code handy to make this work? (Note: I am working on it but haven't really done any javascript up until now, so it's slow going).
<script type="text/javascript">
var theTDs = document.getElementsByTagName("TD");
var i=0;
var TDContent = " ";
while (i < theTDs.length)
{
try
{
TDContent = theTDs[i].innerText || theTDs[i].textContent;
if (TDContent.indexOf("<div") == 0)
{
theTDs[i].innerHTML = TDContent;
}
}
catch(err){}
i=i+1;
}
</script>
The result I'm getting now is nothing visible, because with enhanced rich text the div tag is longer than my 45 character truncation limit.
How about using Christophe's techniques to output HTML using a calculated column.
Specifically he has written javascript that will turn the encoded HTML (which you've now got) into HTML.
Add the following into a Content Editor Web Part (CEWP) on the same page.
<script type="text/javascript">
/*
Text to HTML Lite - version 2.1.1
Questions and comments: Christophe#PathToSharePoint.com
*/
function TextToHTML(NodeSet, HTMLregexp) {
var CellContent = "";
var i=0;
while (i < NodeSet.length)
{
try
{
CellContent = NodeSet[i].innerText || NodeSet[i].textContent;
if (HTMLregexp.test(CellContent))
{ NodeSet[i].innerHTML = CellContent; }
}
catch(err)
{}
i=i+1;
}
}
// Calendar views
var regexpA = new RegExp("\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*");
TextToHTML(document.getElementsByTagName("a"),regexpA);
// List views
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"),regexpTD);
</script>
I have modified the TextToHTML code from below link, source is PathToSharePoint.com and I have added an event listener which works on SharePoint 2016 successfully in IE compatiblity mode which runs as IE10 and Chrome latest version: Text to Html conversion in Sharepoint 2010
<script type="text/javascript">
/*
Text to HTML Lite - version 2.1.1
Questions and comments: Christophe#PathToSharePoint.com
*/
document.addEventListener("DOMContentLoaded", function() {
function TextToHTML(NodeSet, HTMLregexp) {
var CellContent = "";
var i = 0;
while (i < NodeSet.length) {
try {
CellContent = NodeSet[i].innerText || NodeSet[i].textContent;
if (HTMLregexp.test(CellContent)) {NodeSet[i].innerHTML = CellContent;}
}
catch (err) {}
i = i + 1;
}
}
// Calendar views
var regexpA = new RegExp("\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*");
TextToHTML(document.getElementsByTagName("a"), regexpA);
// List views
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"), regexpTD);
// This function is call continuesly every 100ms until the length of the main field changes
// after which the convert text to HTML is executed.
var postElemLength = 0;
function PostConvertToHtml() {
if (postElemLength == document.getElementsByTagName("TD").length) {
setTimeout(PostConvertToHtml, 100);
}
else {
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"), regexpTD);
}
}
// Grouped list views
ExpGroupRenderData = (function(old) {
return function(htmlToRender, groupName, isLoaded) {
var result = old(htmlToRender, groupName, isLoaded);
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"), regexpTD);
};
})(ExpGroupRenderData);
// Preview pane views
if (typeof (showpreview1) == "function") {
showpreview1 = (function(old) {
return function(o) {
var result = old(o);
var regexpTD = new RegExp("^\\s*<([a-zA-Z]*)(.|\\s)*/\\1?>\\s*$");
TextToHTML(document.getElementsByTagName("TD"), regexpTD);
};
})(showpreview1);
}
});
</script>
Related
In the content scripts of my chrome extension I am trying to inject code that highlights a specific word in the page.
In this instance, I am viewing espn.com and would like to have all instances of 'bryant' highlighted in the text immediately as the page is loaded.
This is the current code I have customized after viewing several questions similar to mine:
var all = document.getElementsByTagName("*");
highlight_words('Bryant', all);
function highlight_words(keywords, element) {
if(keywords) {
var textNodes;
keywords = keywords.replace(/\W/g, '');
var str = keywords.split(" ");
$(str).each(function() {
var term = this;
var textNodes = $(element).contents().filter(function() { return this.nodeType === 3 });
textNodes.each(function() {
var content = $(this).text();
var regex = new RegExp(term, "gi");
content = content.replace(regex, '<span class="highlight">' + term + '</span>');
$(this).replaceWith(content);
});
});
}
}
In my jquery-ui.css I have the following code. I understand it does not highlight at this moment but I am just trying to get a proof of concept:
.highlight {
font-weight: bold;
}
At this time everything loads properly but no iteration of 'bryant' is read in bold.
Thanks!
The fastest way to do this is to define the what are you want to search for highlight, for example:
You have 3 parts on site, the navbar on left, the title on the top and the content.
Lets attach .foo class to article.
var list = document.getElementsByClassName("foo")
var search_word = ""
var contents = []
for(var i = 0; i < list.length; i++){
var contents = list[i].textContext.split(search_word)
list[i].textContext = contents.join('<span class="heighlight\">'+search_word+'</span>')
}
Hope it will help.
(The highlight is bound to elements that have .foo class)
some example: https://jsfiddle.net/Danielduel/0842qntu/2/
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.
(NOTE: Priority is in the table but have removed it from the screenshot as it had a users name on there)
This is when we are in quick edit mode...
and this is what happens when we stop editing.
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?
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?
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
Pic 2. List View (default mode)
Using Tooltipster, I want to populate tooltips with words selected from a English/Thai glossary set up as a js 2D array. The intention is that as an English word is tooltipped it will be used to access and display the paired Thai word(s). All of this is in a modal dialog. Here is the html:
<div id="modal_text">
<p id="modal_text01">The <span class="tooltip">boy</span> is <span class="tooltip">walking</span><span> </span><span class="tooltip" >home</span></p>
here is the js code (the array is set as a global variable)
var eng_thai_glossary=[["the","คำนำหน้านามเจาะจง"], ["and","และ"], ... ["dependent","ซึ่งพึ่งพา ผู้อาศัย"]];
jQuery(document).ready(function () {
"use strict";
var modalIndex = "";
var ws_dlog = jQuery("div#ws_dialog").dialog({
... /* dialog setup */
jQuery("span.ws_dialog_icon").on("click",function(evnt) {
evnt.stopPropagation();
ws_dlog.dialog("open");
jQuery("#ui-dialog-title-dialog").hide();
jQuery(".ui-dialog-titlebar").removeClass('ui-widget-header');
var elementId = evnt.target.id;
modalIndex = elementId.substr(7);
var modalId = "modal_text" + modalIndex,
modalText = document.getElementById(modalId).innerHTML;
var ws_modal_html = '<div class = "ws_dialog_box"><p class = "ws_dialog_text">Here is the word in a sentence</p><p class="ws_dialog_thai">คำในประโยค</p><p class = "ws_dialog_sentence"></p><p><span class="fa fa-volume-up fa_volume_ws"></span></p></div>';
ws_dlog.html(ws_modal_html);
jQuery("div.ws_dialog_box p.ws_dialog_sentence").append(modalText);
jQuery('span.tooltip').tooltipster({
functionAfter: function(evnt) {
var eng_word = jQuery(this).evnt.innerHTML,
thai_word = "";
for( var i=0; i<eng_thai_glossary.length; i++) {
if(eng_thai_glossary[i][0] === eng_word) {
thai_word = eng_thai_glossary[i][1];
return thai_word;
}
}
}
});
});
... /* audio code */
});
Firebug shows the class "tooltipstered" is being added to the html indicating Tooltipster is being initialized. I'm a bit lost beyond this point. I'm not sure whether functionAfter is the right way to go here, or any of the other code for that matter. Any advice would be most welcome
OK, this is the solution I arrived at for the above issue. Pretty standard stuff, I guess. The toLowerCase method covers the English convention of capitalizing the first character of a sentence.
jQuery('span.tooltip').tooltipster({
functionBefore: function(origin, continueTooltip) {
var eng_word = jQuery(origin).text().toLowerCase(),
thai_word = "",
gloss_length = eng_thai_glossary.length;
for(var i=0; i<gloss_length; i++){
if(eng_thai_glossary[i][0] === eng_word) {
thai_word = eng_thai_glossary[i][1];
break;
}
}
origin.tooltipster( "content", thai_word);
continueTooltip();
}
});
In Google docs, this function changes the selected text to black
function selectedFontColorBlack() {
// DocumentApp.getUi().alert('selectedFontColorBlack');
var sel = DocumentApp.getActiveDocument().getSelection();
var elements = sel.getRangeElements();
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
// Only modify elements that can be edited as text; skip images and other non-text elements.
if(element.getElement().editAsText) {
var text = element.getElement().editAsText();
// Bold the selected part of the element, or the full element if it's completely selected.
if (element.isPartial()) {
text.setForegroundColor(element.getStartOffset(), element.getEndOffsetInclusive(), "#000000");
} else {
text.setForegroundColor("#000000");
}
}
}
}
This function changes the entire paragraph in which the cursor (or selection) exists to uppercase:
function uppercaseSelected() {
// DocumentApp.getUi().alert('uppercaseSelected');
var sel = DocumentApp.getActiveDocument().getSelection();
var elements = sel.getRangeElements();
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
// Only modify elements that can be edited as text; skip images and other non-text elements.
if(element.getElement().editAsText) {
var text = element.getElement().editAsText();
text.setText(text.getText().toUpperCase());
}
}
}
I don't see any corresponding setText function that works on the selection's "offset", as does the setForegroundColor(Integer,Integer,String). (Both of these functions are in class Text.)
How can I change the actually selected text to uppercase, and not the entire paragraph in which the selection exists?
Thank you.
Try using the setAttributes(startOffset, endOffsetInclusive, attributes) method. Check out the documentation
[EDIT: my bad, i don't think that'll do it. I'll look a bit longer tho]
The gem hidden in the post that #Mogsdad is referring to is this: var selectedText = elementText.substring(startOffset,endOffset+1);. to be little more verbose on how this is used: you can use the string method substring on objects such as DocumentApp.getActiveDocument().getSelection().getSelectedElements()[i].getElement().editAsText().getText()
so, essentially, grab that substring, convert it to uppercase, delete the text in the range (selectedElement.getstartOffset,selectedElement.endOffsetInclusive) and insert the bolded text at selectedElement.getstartOffset
Tada! check it out:
function uppercaseSelected() {
// Try to get the current selection in the document. If this fails (e.g.,
// because nothing is selected), show an alert and exit the function.
var selection = DocumentApp.getActiveDocument().getSelection();
if (!selection) {
DocumentApp.getUi().alert('Cannot find a selection in the document.');
return;
}
var selectedElements = selection.getSelectedElements();
for (var i = 0; i < selectedElements.length; ++i) {
var selectedElement = selectedElements[i];
// Only modify elements that can be edited as text; skip images and other
// non-text elements.
var text = selectedElement.getElement().editAsText();
// Change the background color of the selected part of the element, or the
// full element if it's completely selected.
if (selectedElement.isPartial()) {
var bitoftext = text.getText().substring(selectedElement.getStartOffset(), selectedElement.getEndOffsetInclusive() + 1);
text.deleteText(selectedElement.getStartOffset(), selectedElement.getEndOffsetInclusive());
text.insertText(selectedElement.getStartOffset(), bitoftext.toUpperCase());
} else {
text.setText(text.getText().toUpperCase());
}
}
}
Started with the code from Google App script Document App get selected lines or words?, and made this almost a year ago. I'm happy if it helps you.
The "trick" is that you need to delete the original text and insert the converted text.
This script produces a menu with options for UPPER, lower and Title Case. Because of the delete / insert, handling more than one paragraph needs special attention. I've left that to you!
function onOpen() {
DocumentApp.getUi().createMenu('Change Case')
.addItem("UPPER CASE", 'toUpperCase' )
.addItem("lower case", 'toLowerCase' )
.addItem("Title Case", 'toTitleCase' )
.addToUi();
}
function toUpperCase() {
_changeCase(_toUpperCase);
}
function toLowerCase() {
_changeCase(_toLowerCase);
}
function toTitleCase() {
_changeCase(_toTitleCase);
}
function _changeCase(newCase) {
var doc = DocumentApp.getActiveDocument();
var selection = doc.getSelection();
var ui = DocumentApp.getUi();
var report = ""; // Assume success
if (!selection) {
report = "Select text to be modified.";
}
else {
var elements = selection.getSelectedElements();
if (elements.length > 1) {
report = "Select text in one paragraph only.";
}
else {
var element = elements[0].getElement();
var startOffset = elements[0].getStartOffset(); // -1 if whole element
var endOffset = elements[0].getEndOffsetInclusive(); // -1 if whole element
var elementText = element.asText().getText(); // All text from element
// Is only part of the element selected?
if (elements[0].isPartial())
var selectedText = elementText.substring(startOffset,endOffset+1);
else
selectedText = elementText;
// Google Doc UI "word selection" (double click)
// selects trailing spaces - trim them
selectedText = selectedText.trim();
endOffset = startOffset + selectedText.length - 1;
// Convert case of selected text.
var convertedText = newCase(selectedText);
element.deleteText(startOffset, endOffset);
element.insertText(startOffset, convertedText);
}
}
if (report !== '') ui.alert( report );
}
function _toUpperCase(str) {
return str.toUpperCase();
}
function _toLowerCase(str) {
return str.toLowerCase();
}
// https://stackoverflow.com/a/196991/1677912
function _toTitleCase(str)
{
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
I see that theres is no build in way for doing tabs/indents in MarkItUp? So I did something like
onTab: {
keepDefault: false,
replaceWith: function(markItUp) {
return miu.openEachLineWith(markItUp, ' ');
}
},
openEachLineWith: function(markItUp, openingStr) {
var textarea = markItUp.textarea,
selStart = textarea.selectionStart,
selEnd = textarea.selectionEnd,
selText = textarea.value.substring(selStart, selEnd),
lines = [],
charsAdded = 0;
lines = selText.split(/\r?\n/);
for (var i = 0, len = lines.length; i < len; i++) {
lines[i] = openingStr + lines[i];
charsAdded += openingStr.length;
}
textarea.selectionEnd = selEnd + charsAdded;
return lines.join('\n');
}
which works but, how can I set the selection after replacing the the text, I want it to select the tabbed text, also I prefer the way the editor here on SO works where when I bold some text, it selects the bolded text instead of moving the cursor to the end, can I do that with markItUp too?
I've been working on a script to do this. Here's an example: http://jsfiddle.net/timdown/dp2WL/2/
It indents when Tab is pressed and outdents when Shift + Tab is pressed and doesn't require any library. It hasn't had as much testing as I'd like, but seems to work well in all major browsers, including IE 6. The main code comes from an open source project I'm working on. The bit that enables tab indentation is at the bottom:
window.onload = function() {
rangyInputs.init();
rangyInputs.enableTabIndentation(document.getElementById("test"), " ");
};
You must set the selection in the afterInsert callback (not in replaceWith)