I am rather new to JavaScript. In my experimentation with some sample code, I have created an html file which contains a table. In one of the table data fields I have a text type field. Is there a way to make a button that inserts a pre-defined template for entry that allows for manipulation? aka I press a button "money" that inputs an additional formatted text to "$0.00".
so for example
function input_button(){
var template = "$0.00"
var my_txt = document.getElementById("money");
my_txt.value += Template;
On a side note, what if I wanted to use subscript and superscript? I have tried utilizing the .sup() and .sub() methods, but it just inserts the tags and doesn't alter the aesthetics of the text. ( so in the table, it looks like
<sub> things to be subscript </sub>
opposed to
things to be subscript
I'm not familiar with any way to template text formats, so you might just have to hard code in the logic. As to your second question, when you use the .sup and .sub methods, are you inserting the result in the inner html? For example:
function helloWorldSuper(){
var str = "Hello World";
var result = str.sup();
document.getElementById("tableCell").innerHTML = result;
}
To apply a mask to the input field in order to auto-format values with a template you will need to listen to input key press events and handle according to your mask. There are some scripts that already do this, like Masked Input Plugin for jQuery.
If you want the input text to just have $0.00 as an initial value, it's quite easy to do.
You can create and insert a row into the table via JavaScript like this:
<html>
<body>
<button id="insertRowButton">Insert</button>
<table>
<thead>
<tr><th>Text</th><th>Input</th></tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
<script>
(function() {
// Elements used
var tableBody = document.getElementById('tableBody'),
insertRowButton = document.getElementById('insertRowButton');
// Create a new row template
function createRow() {
var tr = document.createElement('tr'),
tdText = document.createElement('td'),
tdInput = document.createElement('td'),
sub = document.createElement('sub'),
input = document.createElement('input'),
text = document.createTextNode('This is a text node '),
subscriptText = document.createTextNode('with subscript');
sub.appendChild(subscriptText);
tdText.appendChild(text);
tdText.appendChild(sub);
input.value = '$0.00';
tdInput.appendChild(input);
tr.appendChild(tdText);
tr.appendChild(tdInput);
return tr;
}
// Insert a new row into table
function insertRow() {
var tr = createRow();
tableBody.appendChild(tr);
}
// Bind events
insertRowButton.addEventListener('click', insertRow);
}());
</script>
</body>
</html>
Here is it at JSFiddle: http://jsfiddle.net/ck7qargw/
I'm a little confused but I'm making the assumption that you are trying to add sup/sub script via innerHTML?
var template = "<span class='supStyle'>$0.00</span>"
CSS:
.supStyle{vertical-align:top;font-size:smaller;}
Or, you can use a forloop:
mySup = document.getElementsByClassName("supStyle");
for (var i=0;i<mySup.length;i++)
{
mySup[i].style.verticalAlign = "sub";
mySup[i].style.fontSize = "smaller";
}
Related
I have a html/js code that takes data from a json and render it to html table. It has been working fine for a while. Recently the number of items being handled has greatly increased and can't afford to put data statically into html anymore. So I have changed the code in html and I'm now using data attributes, and a JS that loops through each item from the json file and writes it to the correct data attribute in html. It works.
I have another JS file that scans through all td cells and if a condition is met the text in the cell turns red, or purple. Else it remains standard black. This used to work, but not anymore.
This is the new html code implemented:
`
<table id="table" align="center" render-area="reboot">
<thead>
<tr>
<th class="text-center" data-tsorter="input-text">
Server Name
<img src='/icons/sort.png' width='20' height='20' style='display:inline;'>
</th>
<th class="text-center" data-tsorter="numeric">
Last Boot
<img src='/icons/sort.png' width='20' height='20' style='display:inline;'>
</th>
</tr>
</thead>
<tbody render-action="loop">
<tr render-data="json">
<td>{!Server Name!}</td>
<td>{!Last Boot!}</td>
</tr>
</tbody>
</table>
`
and here below the JS that does not work anymore:
`
const today = new Date();
const todayMonth = (today.getMonth())+1;
const todayDay = today.getDate();
// Query all table cells in document
document.querySelectorAll('table td').forEach(function(td) {
const srvDay = parseInt(td.innerHTML.split('/')[1]); // day
if(Number.isInteger(srvDay)){
const srvMonth = parseInt(td.innerHTML.split('/')[0]); //month
// If date contained in td text before current date then apply red background style
if(srvDay != todayDay || srvMonth != todayMonth){
td.style.color = "red";
}
}
if((td.innerHTML.split(' ')[0]).includes('unreachable')){
td.style.color = "purple";
}
});
`
if I examine that table td through the console, I get that the td html is !Last Boot! and that is why I believe the JS above does not work anymore. But if I look at the Elements console, I see that the DOM has all td correctly filled. In fact all works fine, except the JS above. The question is: how to manipulate data that is filled using data attributes? If I use a class for that td I get the same. Any hint?
UPDATE: I've found that when data is dynamically assigned it goes into an HTMLCollection, which I can now read as I found out which attribute to use to select the correct html element. In fact it contains the data I need, with the td cells filled in.
But! don't know how to operate this htmlcollection. I've tried and I'm getting weird results. I've learnt that on htmlcollection foreach does not work. Either transform it into array with Array.from() or use for of loop. When I use any of the two I lose the data and again I get the placeholder {!Last Boot!}. This is how far I got:
`
function tdTextHandler(renderArea){
const today = new Date();
const todayMonth = (today.getMonth())+1;
const todayDay = today.getDate();
const newArr = document.querySelectorAll(`[render-area="${renderArea}"]`);
newArr.forEach(function(e) {
const newArr4 = (Array.from(e.children))[1].children
console.log(newArr4);
for (item of newArr4) {
console.log(item);
const srvDay = parseInt(item.innerHTML.split('/')[1]); // day
if(Number.isInteger(srvDay)){
const srvMonth = parseInt(item.innerHTML.split('/')[0]); //month
// If date contained in td text before current date then apply red background style
if(srvDay != todayDay || srvMonth != todayMonth){
item.style.color = "red";
}
}
if((item.innerHTML.split(' ')[0]).includes('unreachable')){
item.style.color = "purple";
}
};
`
the first console.log tells me that I have a htmlcollection and in the console I can see that its entries have the data. But the second console.log shows that the data is gone, although the structure is there and I'm back to the placeholder.
Solved. As the table is dynamically generated by another JS script, it is in that script (and in its loop) that the JS code above is to be placed.
if you have something like:
<div data-myAttribute="1"></div>
<div data-myAttribute="2"></div>
...
you select them :
const els = document.querySelectAll('div[data-myAttribute');
els.forEach(e => {
...
})
I have a string of text that I want to compare with another string that has HTML code. The problem is that the text I need to compare it to in the HTML code is within different tags. Also, if the string exists in the HTML code then I want to wrap it inside a <mark> tag.
This is the example I am using:
var html = "<h1>This is a heading</h1><div class="subtitle">and this is the subheading</div><p class="small">this is some example text</p>";
var lookup = "is a heading and this is the subheading this is some";
var finalHtml = ""; //will contain new html
//Need to do some comparison and then add a <mark> tag around found string.
console.log(finalHtml);
//This should print "<h1>This <mark>is a heading</h1><div class="subtitle">and this is the subheading</div><p class="small">this is some</mark> example text</p>"
I am using Javascript/Jquery to do this.
This will only help to search your lookup within html (i.e., no marking). I have removed tags-spaces & then checked.
var html = '<h1>This is a heading</h1><div class="subtitle">and this is the subheading</div><p class="small">this is some example text</p>';
//remove html tags & spaces.
cleanHtml = html.replace(/<\/?[^>]+(>|$)/g, "").replace(/\s/g,"");
var lookup = "is a heading and this is the subheading this is some";
lookup = lookup.replace(/\s/g,'');
if(cleanText.includes(lookup)){
//match found
}
I have the following code:
var table = $("#b-table");
table.find('tr').each(function (i) {
var $tds = $(this).find('td'),
qLine = $tds.eq(0).text(),
qPartNumber = $tds.eq(1).text(),
qComments = $tds.eq(5).val();
console.log(qLine);
console.log(qPartNumber);
console.log(qComments);
});
qLine and qPartNumber are copying over fine, as these are text values within the td element, but qComments is not copying over, as within the td element is another input element, like so:
<td><input class="qComments" type="text"></td>
I've tried using:
$tds.eq(5).val();
$tds.eq(5).html();
$tds.eq(5).text();
$tds.input.eq(5).val();
$tds.eq(5).input.val();
and none of these capture the value of the input - and the last two error out for bad syntax.
Try something like this
$tds.eq(5).find("input").val();
I've got a strange question. We have buttons that have data attributes with an id in it. [v1, v2 and v3].
<table id="table-1" data-car-id="v1">
<tr><td>Header1</td></tr>
<tr><td>Content1 <input type="text" name="car[v1][marked][12]" /></td></tr>
<tr><td>Footer</td></tr>
</table>
<button id="copy-2" data-car-id="v2">Copy Table</button>
<table id="table-2">
</table>
<button id="copy-3" data-car-id="v3">Copy Table</button>
<table id="table-3">
</table>
A little piece of Javascript copies the body of the above table to closest next one. (That works).
$("button[id^='copy']").click(function() {
var $carId = $(this).attr('data-car-id');
alert($carId);
var $prevTable = $(this).prev("table[id^='table-']").prop('innerHTML');
var $nextTable = $(this).next("table").html($prevTable);
});
But now the tricky part, the input name of all inputs in that tbody should be replace. While the market should remain unchanged
car[v1][marked][12] => car[v2][marked][12]
How can I do that? Make it yourself easy and use the JSFiddle I created: https://jsfiddle.net/ra35z8ff/
After copying the HTML over to the next table element, select all the children input elements and iterate over them. Use the .replace() method to replace the previous table element's data-car-id attribute with the current button element's data-car-id attribute.
Updated Example
$("button[id^='copy']").on('click', function () {
var id = $(this).attr('data-car-id'),
previousId = $(this).prev('button').attr('data-car-id');
html = $(this).prev("table[id^='table-']").prop('innerHTML');
$(this).next("table").html(html).find('input').each(function () {
this.name = this.name.replace(previousId, id);
});
});
In my sharepoint list, I am dealing with items that should have attachments. I customized the template so that it would allow me to add attachments, but I see no possibilities to mark attachments as mandatory. I managed to check for attachments with the script
<script type="text/javascript" language="javascript">
function PreSaveAction()
{
var elm = document.getElementById("idAttachmentsTable");
if (elm == null || elm.rows.length == 0)
{
document.getElementById("idAttachmentsRow").style.display='none';
alert("Please attach Documents");
return false ;
}
else { return true ;}
}
</script>
but I was only able to use it in a custom form (not the template). Since the template is used for pretty much any interaction with the list, I want to use it and would like to execute the js code after the template has loaded. The template is referenced in between the tags <ZoneTemplate> and </ZoneTemplate>. There's much more code inside that form, but sharepoint-designer won't let me edit anything apart the stuff between those two tags.
It's really frustrating, because I seem to miss an obvious point. Hope I delivered enough information as I am not used to work with sharepoint and it's forms and templates for them...
When you need to add a JavaScript to a list form, you can browse to the form directly. For example, if your list is called MyList, then the new item form would be at http://url/Lists/MyList/newform.aspx and the edit form would be at EditForm.aspx. Browse to the page or pages where you want to insert your javascript code, then under Site Actions, click Edit Page. Add a Content Editor Web Part and either insert the javascript directly into the HTML of the content editor web part or add a link to an HTML file that has the javascript.
As for marking an attachment as mandatory, you may just need to include some wording to the form that will instruct the user to click Attach File button. Maybe something like this that would add a row to the bottom of the form table
<script type="text/javascript">
function addRow() {
var required = document.createTextNode("*");
var table = document.getElementsByClassName("ms-formtable")[0];
var tbody = table.getElementsByTagName("tbody")[0];
var tr = document.createElement("tr");
var td1 = document.createElement("td");
td1.setAttribute("class","ms-formlabel");
td1.setAttribute("vAlign","top");
var h31 = document.createElement("h3");
h31.setAttribute("class","ms-standardheader");
var text1 = document.createTextNode("Attachment");
h31.appendChild(text1);
var span1 = document.createElement("span")
span1.setAttribute("class","ms-formvalidation");
span1.setAttribute("title","This is a required field");
span1.appendChild(required);
h31.appendChild(span1);
var td1.appendChild(h31);
var tr.appendChild(td1);
var td2 = document.createElement("td");
td2.setAttribute("class","ms-formbody");
td2.setAttribute("vAlign","top");
var text2 = document.createTextNode("Click the Attach File button in the ribbon to add an attachment");
var td2.appendChild(text2);
var tr.appendChild(td2);
var tbody.appendChild(tr);
}
</script>
This is pretty ugly and can be simplified with jQuery.
<script type="text/javascript">
function addRow() {
var h3 = $('<h3 class="ms-standardheader">Attachment</h3>').append('<span class="ms-formvalidation">*</span>');
var td1 = $("<td></td>").append(h3);
var td2 = $("<td>Click the Attach File button in the ribbon to add an attachment</td>");
var tr = $("<tr></tr>").append(td1);
$(tr).append(td2);
$(".ms-formtable").first().find("tbody").first().append(tr);
}
</script>
Keep in mind this is untested and probably has some bugs in it.