jQuery UI sortable dynamic target not working - html

I have two tables in my html. The first is loaded on page load, the second is generated on button click.
My sortable function does not apply to the generated table.
Can you explain why?
Here is my Javascript some.js:
// sort all kinds of tables
$(function(){
$('table').sortable();
});
// generate new table
$(document).on('click','#test',function(){
let str = "<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>"
let content = $.parseHTML(str)
$('#main').html(content);
})
And here the actual html file index.html:
<!DOCTYPE html>
<html>
<head>
<script defer src="jquery/3.5.1/jquery-3.5.1.min.js"></script>
<script defer src="jquery/jquery-ui-1.13.1.js"></script>
<script defer src="some.js"></script>
</head>
<body>
<div id="main">
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
<input type="button" id="test" value="Generate Table" onclick="">
</div>
</body>
</html>

The generated table does not exist in the DOM in the ready event when you call $('table').sortable(); The table is added to the DOM later as response to the click event. You should call $('table').sortable(); after you add the table to the dom
This should work:
$(document).on('click','#test',function(){
let str = "<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>"
let content = $.parseHTML(str)
$('#main').html(content);
$('#main table').sortable();
})

Related

XPath find element by position of different element

Example html:
<table>
<thead>
<tr>
<td class="foo"></td>
<td class="bar"></td>
<td class="buzz"></td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</tbody>
</table>
Problem
I have row position (//tbody/tr[X]) and header class (//thead//td[#class="XXX"])
I want to find table data cell using row and column
For example <td>5</td> can be located by //tbody/tr[2] and //thead//td[#class="bar"]
Pseudo-xpath:
//tbody/tr[2]/td[position() = //thead//td[#class="bar"]::position()]
I was tweaking with ancestor:: axis but it was dead end.
Any ideas how to write it properly?
Try to use this XPath to select required node:
//tbody/tr[2]/td[position() = count(//thead/tr/td[#class="bar"]/preceding-sibling::*) + 1]
Instead of position we're checking the count of preceding siblings + 1

Passing HTML to HTML template

I know that if we want to pass variables from .gs to the HTML template, we do this:
On .html (using <?= someVariable ?>:
<div>
<table id="summary">
<thead>
<th>Qty</th>
<th>Item</th>
<th>Price</th>
<th>Subtotal</th>
</thead>
<tbody>
// variable value goes into here
<?= items ?>
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td>Total: </td>
// and into here
<td><b><?= totalCost ?></b></td>
</tr>
</tfoot>
</table>
</div>
And on .gs :
var items = holdSS.getRange(i,5).getValue()
var totalCost = holdSS.getRange(i,6).getValue()
var html = HtmlService.createTemplateFromFile("requestorEmail.html")
// matching the <?= ?> in HTML template
html.items = items
html.totalCost = totalCost
var htmlInString = html.evaluate().getContent()
The size of variable items varies, so I decided to leave it in HTML form, then pass it to the email template. So,
var items = "<tr>
<td>1</td>
<td>3M 500 Scotch Utility Trans. Tape 12mm x 25m</td>
<td>0.98</td>
<td>0.98</td>
</tr>
<tr>
<td>2</td>
<td>3M 558 Bulletin Board - Mocha</td>
<td>19.9</td>
<td>39.80</td>
</tr>
<tr>
<td>1</td>
<td>3M 560RP Post It Marker Rainbow 75mm x 12.5mm 4pad/pkt</td>
<td>3.82</td>
<td>3.82</td>
</tr>"
Resulting in (expected, at least) :
<div>
<table id="summary">
<thead>
<th>Qty</th>
<th>Item</th>
<th>Price</th>
<th>Subtotal</th>
</thead>
<tbody>
// replacing <?= items ?>
<tr>
<td>1</td>
<td>3M 500 Scotch Utility Trans. Tape 12mm x 25m</td>
<td>0.98</td>
<td>0.98</td>
</tr>
<tr>
<td>2</td>
<td>3M 558 Bulletin Board - Mocha</td>
<td>19.9</td>
<td>39.80</td>
</tr>
<tr>
<td>1</td>
<td>3M 560RP Post It Marker Rainbow 75mm x 12.5mm 4pad/pkt</td>
<td>3.82</td>
<td>3.82</td>
</tr>
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td>Total: </td>
// and here
<td><b><?= totalCost ?></b></td>
</tr>
</tfoot>
</table>
</div>
However, console.log(html.evaluate().getContent()) gives :
<tbody>
<tr><td>1</td><td>3M 500 Scotch Utility Trans. Tape 12mm x 25m</td><td>0.98</td><td>0.98</td>
</tr><tr><td>2</td><td>3M 558 Bulletin Board - Mocha</td><td>19.9</td><td>39.80</td></tr>
<tr><td>1</td><td>3M 560RP Post It Marker Rainbow 75mm x 12.5mm 4pad/pkt</td><td>3.82</td><td>3.82</td></tr>
</tbody>
where all the < and > in the HTML tags are escaped. I have read some threads in which they unescape the HTML entities using a textarea element but I also noted I can't execute <script> tags in email clients? What should I do in this case?
When I saw your script, it seems that HTML is put to the template HTML using <?= ... ?> of the printing scriptlets. In this case, such a result in your question is obtained.
In order to put the value as the HTML tag, please use the force-printing scriptlets like <?!= ... ?>. So, please modify it as follows.
From:
<?= items ?>
To:
<?!= items ?>
And, about <?= totalCost ?>, if you want to put the HTML tag, please modify this like <?!= totalCost ?>.
Reference:
HTML Service: Templated HTML

Using this text method with html symbols in jQuery to find td with symbol inside

I am trying to highlight a table row if it has a tick (check mark) in one of the td’s. I am using the jQuery code below, but it will not find a td with a html symbol such as a tick (check mark). It makes no difference if I use .text() or .html(). The code works as expected if I use any other criteria such as text or numbers, but not with html symbols. Is there away round this?
$('#farm td').filter(
function(t) {
if ($(this).text() == "✓") {
$(this).closest('tr').css('background-color', 'Yellow');
return;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="farm" border="1">
<tr>
<th>One</th>
<th>Two</th>
</tr>
<tr>
<td>Cat</td>
<td>Duck</td>
</tr>
<tr>
<td>Pig</td>
<td>✕</td>
</tr>
<tr>
<td>✓</td>
<td>Bull</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
</tr>
</table>
You just need to check for the actual character (✓). jQuery acts on rendered HTML, not markup. I determined this by setting a breakpoint on the line with text() in it and looking at the values that came through.
Also:
.each() makes more sense to me here
no need to return anything in the function
no need to pass in anything (t)
console logs are far nicer than alerts for debugging
$('#farm td').each(function() {
if ($(this).text() == "✓") {
$(this).closest('tr').css('background-color', 'Yellow');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="farm" border="1">
<tr>
<th>One</th>
<th>Two</th>
</tr>
<tr>
<td>Cat</td>
<td>Duck</td>
</tr>
<tr>
<td>Pig</td>
<td>✕</td>
</tr>
<tr>
<td>✓</td>
<td>Bull</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
</tr>
</table>
Mohamed-Yousef suggested a great refinement using an internal selector:
$('#farm td:contains("✓")').closest('tr').css('background-color', 'Yellow');
It's a slightly different selector as it would also match ✓ blah, for example, but maybe it's useful in your case.
https://api.jquery.com/contains-selector/

how to detect multiple clicks on a cell of same row and prevent it in jquery?

I have a table
<table>
<tr>
<th>Heading 1
</th>
<th>Heading 2
</th>
<th>Heading 3
</th>
<th>Heading 4
</th>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
</table>
When I click a particular cell I get its cell value.
$('td').click(function () {
var col_index = $(this).text();
console.log("Text: " + col_index);
});
What I want is, when I click the different cell of same row I want to alert a message that 'You cannot click another value once clicked' or something like that.
For example, if you look in to the table, for the first time I click Value 1, but then if I go click Value 2 it should prevent me to do click.
How do I do that?
You could store a map of clicked cells in a specific row and if something has been already clicked then display an alert:
var td_map = {};
$('td').click(function () {
var $this = $(this);
var $td = $this.parent();
var col_index = $(this).text();
if (td_map[$td.index()] === undefined || td_map[$td.index()] === col_index) {
td_map[$td.index()] = col_index;
console.log("Text: " + col_index);
} else {
alert('You cannot select two cells in one row');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>Heading 1
</th>
<th>Heading 2
</th>
<th>Heading 3
</th>
<th>Heading 4
</th>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
</tr>
</table>

How to xpath values in a dynamic table?

Could please someone help me to xpath values in a dynamic table.
I have the following HTML code and I need to select the values of the cells, as for example:
if a tr-cell contains the text "Values1" then select the first value (0) in td / third value (1) in td of this cell
I would be very thankful.
<table class="DynamicTable">
<tbody>
<tr>
<th>Details</th>
</tr>
<tr>
<td>0</td>
<td>Values1</td>
<td>1</td>
</tr>
<tr>
<td>4</td>
<td>Values2</td>
<td>2</td>
</tr>
<tr>
<td>1</td>
<td>Values6</td>
<td>0</td>
</tr>
</tbody>
</table>