I use Vue 2.
I generate table from the collection:
<table class="table table-striped table-bordered">
<tbody>
<tr v-for="(type, typeIndex) in getAllUpgradeTypes" :key="typeIndex">
<td>
<imageDesc
style="margin-left: 10px"
:title="type"
:text="'Select an Option'"
:zoneId="selectedZone.id"
/>
</td>
</tr>
</tbody>
</table>
Currently, the table created with multiple rows, each row has only one column and shows one item inside the column.
My question how can I generate a table which will contain 3 columns per row?
There at least a couple of different patterns you could use for this. One involves rearranging your data before iterating it in the template, another doesn't. I'll show you both.
In both cases, use a data property to hold the number of columns:
data: () => ({
numCols: 3
})
Reorganize the data into a 2D array
Instead of one array with all your items, use a computed to reorganize the data into a multi-dimensional array of rows and columns:
computed: {
arrangedData() {
const arrangedData = [];
this.getAllUpgradeTypes.forEach((item, index) => {
if (index % this.numCols === 0) {
arrangedData.push([])
}
arrangedData[arrangedData.length - 1].push(item);
});
return arrangedData;
}
}
Iterate the data like this:
<table class="table table-striped table-bordered">
<tr v-for="(row, rowIndex) in arrangedData" :key="rowIndex">
<td v-for="(type, typeIndex) in row" :key="`${rowIndex}:${typeIndex}`">
{{ type }}
</td>
</tr>
</table>
Here's a demo:
new Vue({
el: "#app",
data: () => ({
getAllUpgradeTypes: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'],
numCols: 3
}),
computed: {
arrangedData() {
const arrangedData = [];
this.getAllUpgradeTypes.forEach((item, index) => {
if (index % this.numCols === 0) {
arrangedData.push([])
}
arrangedData[arrangedData.length - 1].push(item);
});
return arrangedData;
}
}
});
td { width: 40px }
<div id="app">
<table class="table table-striped table-bordered">
<tr v-for="(row, rowIndex) in arrangedData" :key="rowIndex">
<td v-for="(type, typeIndex) in row" :key="`${rowIndex}:${typeIndex}`">
{{ type }}
</td>
</tr>
</table>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
-or-
Calculate the number of rows
The other way involves using a computed to calculate the number of rows. It's less code, but then type gets an ugly syntax in the template:
computed: {
numRows() {
return Math.ceil(this.getAllUpgradeTypes.length / this.numCols);
}
}
Iterate the data like this:
<table class="table table-striped table-bordered">
<tr v-for="(row, indexRow) in numRows">
<td v-for="(col, indexCol) in numCols">
{{ getAllUpgradeTypes[(indexRow * numCols) + indexCol] }}
</td>
</tr>
</table>
Here's a demo:
new Vue({
el: "#app",
data: () => ({
getAllUpgradeTypes: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'],
numCols: 3
}),
computed: {
numRows() {
return Math.ceil(this.getAllUpgradeTypes.length / this.numCols);
}
}
});
td { width: 40px; }
<div id="app">
<table>
<tr v-for="(row, indexRow) in numRows" :key="indexRow">
<td v-for="(type, indexCol) in numCols" :key="`${rowIndex}:${typeIndex}`">
{{ getAllUpgradeTypes[(indexRow * numCols) + indexCol] }}
</td>
</tr>
</table>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
There are probably some variations on these options but I think the first is probably the best for the template clarity.
Here is my solution to a similar issue. I needed to generate a printable page and display information from a table in our database. The appearance of the page required me to have 3 fixed-size rows and 3 fixed-size columns per row.
I added styling to give it a grid-like appearance, but here is how I generated the table with page breaks after 3 rows:
This is where I have the table setup in the HTML (cshtml) file:
<table id="employee-table" class="m-auto">
</table>
Here is my JavaScript function which is located in an external JS file (don't forget to reference the file in your HTML if that's how you're setting it up)
function GeneratePrintablePDF(employeeData) {
document.getElementById('loader').classList.add('hidden'); //this is just the "loading" spinner for when the page is loading
dataContainer = document.getElementById('employee-table');
numberOfRows = employeeData.length / 3;
if (employeeData % 3 != 0) {
numberOfRows = Math.trunc(numberOfRows);
numberOfRows += 1;
}
var emp = 0;
do
{
for (var row = 1; row <= numberOfRows; row++) {
var tableRowDiv = document.createElement('div');
dataContainer.appendChild(tableRowDiv);
var tableRow = document.createElement('tr');
tableRowDiv.appendChild(tableRow);
for (var col = 1; col < 4; col++)
{
if (emp < employeeData.length) {
var tableCol = document.createElement('td');
tableCol.className = 'pdf-employee-box';
tableRow.appendChild(tableCol);
var empName = document.createElement('div');
empName.className = 'fw-bold';
empName.innerHTML = `${employeeData[emp].firstName} ${employeeData[emp].lastName}`;
tableCol.appendChild(empName);
var empPhoto = document.createElement('img');
var employeePhotoUrl = employeeData[emp].azurePhotoURL;
if (employeePhotoUrl == null) {
empPhoto.src = '/Images/lg_unavailable.jpg';
} else {
empPhoto.src = employeePhotoUrl;
}
var empPhotoOnError = document.createAttribute('onerror');
empPhotoOnError.value = "this.onerror=null;this.src='/Images/lg_unavailable.jpg';";
empPhoto.setAttributeNode(empPhotoOnError);
empPhoto.alt = 'Employee Photo';
empPhoto.className = 'employee-photo-pdf pdf-image';
tableCol.appendChild(empPhoto);
var empTitle = document.createElement('div');
empTitle.innerHTML = employeeData[emp].title != null ? `Title: ${employeeData[emp].title}` : 'Title: Unknown';
empTitle.className = 'pdf-details';
tableCol.appendChild(empTitle);
var empDept = document.createElement('div');
empDept.innerHTML = employeeData[emp].department != null ? `Department: ${employeeData[emp].department}` : 'Department: Unknown';
empDept.className = 'pdf-details';
tableCol.appendChild(empDept);
var empEmail = document.createElement('div');
empEmail.innerHTML = (employeeData[emp].emailAddress != null && !employeeData[emp].emailAddress.toLowerCase().includes('no ')) ? `Email: ${employeeData[emp].emailAddress}` : 'Email: Unknown/None';
empEmail.className = 'pdf-details';
tableCol.appendChild(empEmail);
var empStartDate = document.createElement('div');
empStartDate.innerHTML = employeeData[emp].startDate != null ? `Start Date: ${employeeData[emp].startDate}` : 'Start Date: Unknown';
empStartDate.className = 'pdf-details';
tableCol.appendChild(empStartDate);
var empLocation = document.createElement('div');
empLocation.innerHTML = employeeData[emp].location != null ? `Location: ${employeeData[emp].location}` : 'Location: Unknown';
empLocation.className = 'pdf-details';
tableCol.appendChild(empLocation);
if (col == 2) tableCol.className = tableCol.className + ' pdf-grid-lines';
emp++;
}
}
if (emp % 9 == 0) {
tableRowDiv.className += 'page-break-after';
}
}
} while (emp < employeeData.length)
}
I decided to calculate the number of rows I need based on how many employee records we have. So, if we have 436 employees, then I'm determining that I need 146 rows. So I'm programming it to generate the precise number of rows I need, and only put 3 items (columns) in each row. The 146th row in this case only has 1 record.
As you can see, I have the code in a loop only running until it reaches the last employee, so that it doesn't throw an index out of range exception.
This particular code is where I am telling the table to break to the next page, so that employee records aren't running over onto another page and splitting up the information.
if (emp % 9 == 0) {
tableRowDiv.className += 'page-break-after';
}
Here is the CSS that I'm referencing in an external CSS file:
#media print {
.page-break-after {
break-after: page;
}
}
I understand that I am by no means the ultimate programming kingpin, so there could be better or easier ways of doing this. However, this is how I made it work with my environment and it does exactly what I need it to do without using some framework or library.
I found in my research that many PDF generator frameworks, libraries, etc. now require licensing. So if generating a printable document is your goal, then this could work for you too. Anyways, good luck and I hope I have helped someone.
Related
I'm receiving an array of objects in form of a json file, and using ajax to display certain key-value pairs in a table. My next step is to sort the rendered table, but I'm unsure of how to proceed.
<div id="data-table">
<table id="html-data-table">
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</table>
</div>
Javascript code which creates the table:
newData.map(row => {
let newRow = document.createElement("tr"); // new row is created
Object.values(row).map((value) => {
//console.log(value);
let cell = document.createElement("td"); // new data for the row is added
cell.innerText = value;
newRow.appendChild(cell);
})
mytable.appendChild(newRow);
});
I want to sort this both columns individually. What method can I use?
You can use Array.sort() to sort your data, in this example I added two buttons to handle sorting by name and age:
const newData = [
{ name: "dave", age: 22 },
{ name: "charlie", age: 32 },
{ name: "eve", age: 19 },
{ name: "alice", age: 27 },
{ name: "bob", age: 20 }
]
const mytable = document.querySelector("#html-data-table tbody")
const btnSortName = document.getElementById("sortName")
const btnSortAge = document.getElementById("sortAge")
// RENDER UNSORTED TABLE
renderTable(newData)
btnSortName.addEventListener('click', (e) => {
const sorted = newData.sort((a,b) => a.name.localeCompare(b.name))
renderTable(sorted)
})
btnSortAge.addEventListener('click', (e) => {
const sorted = newData.sort((a,b) => a.age - b.age)
renderTable(sorted)
})
function renderTable(data) {
mytable.innerHTML = ''
data.map(row => {
let newRow = document.createElement("tr"); // new row is created
Object.values(row).map((value) => {
//console.log(value);
let cell = document.createElement("td"); // new data for the row is added
cell.innerText = value;
newRow.appendChild(cell);
})
mytable.appendChild(newRow);
});
}
<div id="data-table">
<table id="html-data-table">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<button id="sortName">Sort by Name</button>
<button id="sortAge">Sort by Age</button>
Here is a method of sorting the table in place, independent of any generating data structures. The only additionally required information is the sortmode array that specifies whether a text sort or a numeric sort is wanted for a particular column.
const data=[{name:"Harry",age:32, height:183},{name:"Hermione",age:30, height:175},{name:"Ron",age:31,height:187},{name:"Hagrid",age:53,height:180},{name:"Ginny",age:27,height:170},{name:"Dumbledore",age:273,height:185}],
sortmode=[0,1,1]; // 0: text, 1: numeric
mytable=document.querySelector("#data-table tbody");
// fill table: code from OP
data.map(row => {
let newRow = document.createElement("tr"); // new row is created
Object.values(row).map((value) => {
//console.log(value);
let cell = document.createElement("td"); // new data for the row is added
cell.innerText = value;
newRow.appendChild(cell);
})
mytable.appendChild(newRow);
});
// sorting: my code
document.querySelector("#data-table thead").onclick=ev=>{
let col=[...ev.target.parentNode.children].indexOf(ev.target);
[...mytable.children]
.sort((a,b)=>
sortmode[col]
? a.children[col].textContent - b.children[col].textContent
: a.children[col].textContent.localeCompare(b.children[col].textContent)
)
.forEach(tr=>mytable.append(tr))
}
td:nth-child(n+2) {text-align:right}
<div id="data-table">
Please click on the column headings to sort the table:
<table id="html-data-table">
<thead>
<tr><th>Name</th><th>Age</th><th>Height</th></tr>
</thead><tbody></tbody>
</table>
</div>
I have the following vue template
<div v-for="(v, k, i) in subs" :key="index">
<table>
<thead>
<tr>
<th>Barang</th>
<th>Satuan</th>
<th>Jumlah</th>
</tr>
</thead>
<tbody>
<tr v-for="j in ranges[k]">
<td><Select2 :options="goods" #change="fill_units(i)" /></td>
<td><Select2 ref="units" :options="[]" /> </td>
<td></td>
</tr>
</tbody>
</table>
<button #click="ranges[k]++">Add row</button>
</div>
and the data
data(){
return {
ranges: {
makanan: 1,
minuman: 1,
dll: 1
}
subs: {
makanan: 'Makanan',
minuman: 'Minuman',
dll: 'Dan lain-lain'
}
}
}
what I want is, when first Select2 element change its value, this will trigger the next Select2 element to fill its options based on it's ref. the problem is, i is not the correct index for the next Select2, since there might be more row added by the user. I think temporary variable that can hold the total rows on each table can solve the problem, but I don't know how to make that variable inside the template.
equivalent in vanilaJS loop, look like this
let total_rows = 0;
for(let i = 0; i < 3; i++){
for(let j = 0; j < 5; j++){
total_rows++; // i need this variable
fill_units(total_rows);
}
}
I am so sorry if my question isn't clear enough
edit: add select2 code
fill_units(value, i){
const types = this.goods.filter(type => type.id == value);
if(types.length > 0){
const units = types[0].units;
// delete all previous selections
this.$refs.units[i].select2.empty();
// append new selections
this.$refs.units[i].select2.append(`<option value="">Pilih Unit</option>`);
units.forEach(unit => {
this.$refs.units[i].select2.append(`<option value="${unit.id}">${unit.name}</option>`);
})
// this.$refs.units[i].select2.trigger('change');
}
}
I have an html table in my view that I want to filter with multiple filters. In this case, I have 3 filters, but I can have much more.
Here is a little part of the code, to show the problem
$(document).ready(function () {
$('#datefilterfrom').on("change", filterRows);
$('#datefilterto').on("change", filterRows);
$('#projectfilter').on("change", filterProject);
$('#servicefilter').on("change", filterService);
});
function filterRows() {
var from = $('#datefilterfrom').val();
var to = $('#datefilterto').val();
if (!from && !to) { // no value for from and to
return;
}
from = from || '1970-01-01'; // default from to a old date if it is not set
to = to || '2999-12-31';
var dateFrom = moment(from);
var dateTo = moment(to);
$('#testTable tr').each(function (i, tr) {
var val = $(tr).find("td:nth-child(2)").text();
var dateVal = moment(val, "DD/MM/YYYY");
var visible = (dateVal.isBetween(dateFrom, dateTo, null, [])) ? "" : "none"; // [] for inclusive
$(tr).css('display', visible);
});
}
function filterProject() {
let dumb = this.options.selectedIndex;
dumb = this.options[dumb].innerHTML;
var filter, table, tr, td, i;
filter = dumb.toUpperCase();
table = document.getElementById("testTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[2];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "table-row";
} else {
tr[i].style.display = "none";
}
}
}
}
function filterService() {
let dumb = this.options.selectedIndex;
dumb = this.options[dumb].innerHTML;
var filter, table, tr, td, i;
filter = dumb.toUpperCase();
table = document.getElementById("testTable");
tr = table.getElementsByTagName("tr");
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[3];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "table-row";
} else {
tr[i].style.display = "none";
}
}
}
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/moment/moment/2.2.1/min/moment.min.js"></script>
<div class="row">
<div class="col-md-3">
<h4>Date from</h4>
<input type="date" class="form-control" id="datefilterfrom" data-date-split-input="true">
</div>
<div class="col-md-3">
<h4>Date to</h4>
<input type="date" class="form-control" id="datefilterto" data-date-split-input="true">
</div>
<div class="col-md-2">
<h4>Project</h4>
<select id="projectfilter" name="projectfilter" class="form-control"><option value="1">Test project</option><option value="2">Test2</option></select>
</div>
<div class="col-md-2">
<h4>Service</h4>
<select id="servicefilter" name="servicefilter" class="form-control"><option value="1">Test service</option><option value="2">Test2 service</option></select>
</div>
</div>
<table id="testTable" class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Date</th>
<th scope="col">Project</th>
<th scope="col">Service</th>
</tr>
</thead>
<tbody id="report">
<tr>
<td class="proposalId">9</td><td> 17/07/2018</td> <td> Test project</td><td> Test service</td>
</tr>
<tr><td class="proposalId">8</td><td> 18/07/2018</td><td> Test project</td><td> Test2 service</td></tr>
<tr><td class="proposalId">7</td><td> 17/07/2018</td><td> Test2</td><td> Test2 service</td></tr>
<tr style=""><td class="proposalId">3</td><td> 19/07/2018</td><td> Test2</td><td> Test service</td></tr>
</tbody>
</table>
If you set filters like this
You will have this
This is not right. Because I need to have only test 2 project, so one row.
Where is my problem and How I can solve it?
Here is codepen for code
https://codepen.io/suhomlineugene/pen/pZqyEN
Right now you have a separate function for each of your filters, each of which ignores the settings from the other filters and overwrites their results.
Instead you'll need to combine those into a single function which takes all the filters into account.
Rather than literally combining all the code into one complex function, which would be difficult to maintain, one approach would be to have a single master function that makes all the rows visible, then calls each of the other filter functions in turn; those functions would only hide the rows they're filtering out. What's left visible at the end would be the rows that match all the filter selections.
$(document).ready(function () {
$('#datefilterfrom, #datefilterto, #projectfilter, #servicefilter').on("change", filterAll);
});
function filterAll() {
$('#testTable tr').show();
filterRows();
filterProject();
filterService();
// ...etc
}
function filterRows() { // repeat for filterProject(), filterService(), etc
// same as your original code, except only hide non-matching rows, do not
// show matching rows (because filterAll() already took care of that, and
// you don't want to undo what other filters may have hidden.)
}
(Alternatively, instead of showing everything and then having each individual filter hide rows incrementally, you could have filterAll() build an array of all the rows, pass it to the individual filter functions which will remove items from it, then use the end result to show/hide the appropriate rows in one go.)
Not going to rewrite this all for you but will give you a basic outline for the text only searches:
Create array of the filter data from the top inputs. By adding a data-col to each of those filter controls you can easily determine which column in table to match to
So the filters array would look something like:
[
{col:3, value:'test project'}
]
Then use jQuery filter() on the rows and use Array#every() on the filterValues array and look for the matching cell text using the column index from each filter object
var $rows = $('tbody#report tr')
// add a class `table-filter` to all the top filtering elements
var $filters = $('.table-filter').change(function() {
// create array of filter objects
var filterArr = $filters.filter(function() {
return this.value
}).map(function() {
var $el = $(this);
var value = $el.is('select') ? $el.find(':selected').text() : $el.val()
return {
col: $el.data('col'),
value: value.toLowerCase()
}
}).get();
if (!filterArr.length) {
// no filters show all rows
$rows.show()
} else {
// hide all then filter out the matching rows
$rows.hide().filter(function() {
var $row = $(this);
// match every filter to whole row
return filterArr.every(function(filterObj, i) {
var cellText = $row.find('td').eq(filterObj.col).text().trim().toLowerCase();
return cellText.includes(filterObj.value);
})
})
// show the matches
.show()
}
});
Working demo for the two text search fields
To make sure two arrays are the same in Javascript, this is what I do:
(inserting zeroes where there is missing data in item1)
var viewModel = #Html.Raw(Json.Encode(Model));
var items = viewModel.Date1;
var items2 = viewModel.Date2;
items = items2.map( row =>
//is there a matching row in items?
items.filter( r => r.theString == row.theString).length == 0 ?
//if not, fill with zeros
{theString:0, theCount:0} :
//if there is, return the items' row
items.filter( r => r.theString == row.theString)[0] );
I use that data for the barchart as percentages. I need to display the results in table form with the actual count numbers like this:
<div style="padding-top: 30px">
<table id="table_id" class="display">
<thead>
<tr>
<th>Month</th>
<th>Cancelled</th>
<th>Total</th>
</tr>
</thead>
<tbody>
#using (var e1 = Model.Date1.Reverse().GetEnumerator())
{
using (var e2 = Model.Date2.Reverse().GetEnumerator())
{
while (e1.MoveNext() && e2.MoveNext())
{
var item1 = e1.Current;
var item2 = e2.Current;
<tr>
<td>#item1.theDate.Value.ToString("MMMM-yyyy") </td>
<td>#item1.theCount</td>
<td>#item2.theCount</td>
</tr>
}
}
}
</tbody>
</table>
</div>
Problem is that those arrays haven't been fixed to match eachother, so the data it's displaying is incorrect. The dates (theDate) are not matching the values.
Or could I just use items and items2 from the javascript to make a table?
Something like this should work:
#foreach (var item1 in Model.Date1.Reverse())
{
var item2Count = Model.Date2.Where(i2 => i2.theDate == item1.theDate)
.Select(i2 => i2.theCount)
.FirstOrDefault();
<tr>
<td>#item1.theDate.Value.ToString("MMMM-yyyy") </td>
<td>#item1.theCount</td>
<td>#item2Count</td>
</tr>
}
This has the same n² asymptotic complexity as the JavaScript you posted, so if you had a very large number of items there's a chance you'd see slow performance. This could be resolved by creating a lookup of the Date2 values, like so:
#{
var item2CountsByDate = Model.Date2.ToLookup(i => i.theDate, i => i.theCount);
foreach (var item1 in Model.Date1.Reverse())
{
var item2Count = item2CountsByDate[item1.theDate]
.FirstOrDefault();
<tr>
<td>#item1.theDate.Value.ToString("MMMM-yyyy") </td>
<td>#item1.theCount</td>
<td>#item2Count</td>
</tr>
}
}
I have a table with following columns: checkbox, text, text, ...
For every selected checkbox I need to get the 2nd text value and test if contains some value.
My code so far
$('input:checkbox').each(function () {
var current = $(this);
if (current.is(':checked')) {
var txt = current.next('.inf-name').text();
if (txt.contains(inf) { ... }
}
});
razor code:
<table class="table table-bordered table-modified">
<thead>
<tr>
<th></th>
<th>State</th>
<th>Lookup Type</th>
<th>Plates</th>
<th>Notices</th>
</tr>
</thead>
<tbody>
#Html.HiddenFor(p => p.OrgUnitID, new { #Value = orgUnitId })
#for(var ind = 0; ind < records.Count(); ++ind)
{
var r = records[ind];
var i = ind;
#Html.HiddenFor(p => p.Comp[i].State, new { #Value = #r.State })
<tr>
<td>#Html.CheckBoxFor(p => p.Comp[i].Checked)</td>
<td>#r.State</td>
#if (dict.ContainsKey(r.State))
{ <td class="inf-name">#dict[r.State].ToString()</td> }
else
{ <td class="inf-name"></td> }
<td>#Html.ActionLink(#r.Plates.ToString(CultureInfo.InvariantCulture), "Plates", new { controller = "Lookup", state = #r.State})</td>
<td>#Html.ActionLink(#r.Notices.ToString(CultureInfo.InvariantCulture), "Plates", new { controller = "Lookup" }, new { state = #r.State })</td>
</tr>
}
</tbody>
</table>
where inf-name is the class on 2nd element. I can't get it done. Anyone know a solution?
using next() will get the direct sibling , you need to get parent for check box which is a <td> find the next next sibling using nextAll().eq(1) , get the text inside the that sibling using .text()
Edit :
if you want your target using classes ( provided classes will never change later ) , then just change your code to be :
$('input:checkbox').each(function () {
var current = $(this);
if (current.is(':checked')) {
var txt = current.next('.inf-name').eq(1).text();
if (txt.contains(inf) { ... }
}
});
var currentRows = $('.table tbody tr');
$.each(currentRows, function () {
$(this).find(':checkbox').each(function () {
if ($(this).is(':checked')) {
console.log($(currentRows).eq(1).val());
}
});
});