Typeahead and first cell selector - javascript

I have this table
<table id="vehicleParamTable" class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
When a click on a link, I add a row. That work fine.
In the first column of the row, I add an jquery-typehead
Selector is not working, also would like to avoid it for first row (th header)
$('#vehicleParamTable tr td:first-child').typeahead({
minLength: 2,
display: "name",
mustSelectItem: true,
emptyTemplate: function(query) {
//must reset current element here
return 'No result for "' + query + '"';
},
source: {
vehicleParam: {
ajax: {
url: "/rest/vehicleparam",
path: "content"
}
}
},
callback: {
onEnter: function(node, a, item, event) {
//must assign item.id to current current element id
},
onResult: function(node, query, result, resultCount, resultCountPerGroup) {
if (resultCount < 1) {
//must reset current element here
}
}
}
});
Edit
$('#vehicleParamTable tr td:first-child')
seem good, but with the rest(typeahead init..) that return undefined
Edit 2 because I add dynamicly row, need to refresh typehead...

I am assuming you are using this https://github.com/running-coder/jquery-typeahead?
This plugin needs to be initialized on an input field.
So, given that your input field is in the first column of the first row after the header, the selector would be
$('#vehicleParamTable tbody tr td:first-child input').typeahead({ ...options })

Related

Adding select menu to multiple tables with jquery data tables pluglin

I've got two tables (table1,table2) that are structurally the same, but fed from different sources. Both tables share the class 'display' which I use to initialise the plugin for both tables. This works great for the most part, however the column filters select menu for table2 is duplicated on table1.
I've tried to fix this by using 'this' keyword to indicate a particular instance of the toolbar each of the filters need applying to, but not had much success.
The code that works is:
HTML:
<table id="table1" class="display table-striped table-borded table-hover" cellspacing="0" width="100%">
<thead>
<tr>
<th>Report Name</th>
<th>Year</th>
<th>Montly Snapshot</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Date of Last Refresh --var from warehouse-- </th>
</tr>
</tfoot>
</table>
<table id="table2" class="display table-striped table-borded table-hover" cellspacing="0" width="100%">
<thead>
<tr>
<th>Report Name</th>
<th>Year</th>
<th>Montly Snapshot</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Date of Last Refresh --var from warehouse-- </th>
</tr>
</tfoot>
</table>
JS:
//initialise data tables plugin and apply custom settings.
var reportstable = $('table.display').DataTable({
"sDom": '<"toolbar">Bfrtlp',
"searchCols": [
null, {
'sSearch': 'Current'
}
],
language: {
search: "_INPUT_",
searchPlaceholder: "Search for a Report..."
},
// create select form controls
initComplete: function() {
this.api().columns([1, 2]).every(function() {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo($('.toolbar'))
.on('change', function() {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search(val ? '^' + val + '$' : '', true, false)
.draw();
});
column.data().unique().sort().each(function(d, j) {
select.append('<option value="' + d + '">' + d + '</option>')
if ($('#info').css('display') == 'block') {
$("#reports_wrapper").css('display', 'none');
}
// add bootstrap classes and placeholder property to form controls to add style
$('.toolbar select').addClass('selectpicker');
$('.dt-button').addClass('btn btn-danger').removeClass('dt-button');
$('.toolbar select').attr('id', 'year');
$('#year').prop('title', 'Financial Year');
$("#year option:contains('Current')").remove();
$('.toolbar select:nth-of-type(2)').attr('id', 'month');
$('#month').prop('title', 'Monthy Snapshot');
$("#month option:contains('undefined')").remove();
});
});
},
// create clear filter button
buttons: [
{
text: 'Clear Filters',
action: function(e, dt, node, config) {
$('select').val('').selectpicker('refresh');
// set Current Year as default filter
reportstable
.search('')
.columns([1]).search('Current')
.columns([2]).search('')
.draw();
}
}
],
//hide specified columns
"columnDefs": [
{
"targets": [1],
"visible": false,
"searchable": true
}, {
"targets": [2],
"visible": false,
"searchable": true
}
]
});
I've updates your jsfiddle and created a new jsfiddle. It's now appending 2 select menus in both tables's wrapper div. I've found why it's appending 4 select menus instead of 2 on the table1's wrapper div. It's because of this code: .appendTo($('.toolbar')). When initComplete callback function is called for table1 there is only one div with class=toolbar, and when the initComplete callback function is called for table2 there is two div with class=toolbar, one in table1's wrapper div and one in table2's wrapper div. that's why on table2's initComplete callback function it append select menus to all divs with class=toolbar. We should rather append to the current table wrapper's div with class=toolbar.

Selecting a row in table based on content and clicking link from selected row - Protractor

I have a page object that looks like this:
<table border>
<th>Email</th>
<th>action</th>
<tr current-page="adminUsers.meta.page">
<td>admin#example.com</td>
<td>Delete permanently</td>
</tr>
<tr current-page="adminUsers.meta.page">
<td>matilda#snape.com</td>
<td>Delete permamently</td>
</tr>
</table>
I want to create a method that will enable me to delete a user based on his email address.
This is what I came up with, basing on How to find and click a table element by text using Protractor?:
describe('Admin panel', function() {
it('admin deletes a user', function() {
var re = new RegExp("matilda#snape.com");
var users_list = element.all(by.xpath("//tr[#current-page='adminUsers.meta.page']"));
var delete_btn = element(by.xpath("//a[contains(text(), 'Delete permamently')]"));
users_list.filter(function(user_row, index) {
return user_row.getText().then(function(text) {
return re.test(text);
});
}).then(function(users) {
users[0].delete_btn.click();
});
// some assertion, not relevant right now
});
});
First I'm trying to filter the row in which there's a user I want delete (array with all rows fitting my filter, then selecting the first row - should be one row anyway) and then click corresponding Delete button.
However, from my debugging I know that the method ignores the filtering and clicks the first Delete button available in the table and not the first from filtered elements.
What am I doing wrong?
In this particular case, I would use an XPath and its following-sibling axis:
function deleteUser(email) {
element(by.xpath("//td[. = '" + email + "']/following-sibling::td/a")).click();
}
I agree with #alexce's short & elegant answer but #anks, why don't you delete inside your filter??
describe('Admin panel', function() {
it('admin deletes a user', function() {
var re = new RegExp("matilda#snape.com");
var users_list = element.all(by.xpath("//tr[#current-page='adminUsers.meta.page']"));
var delete_btn = element(by.xpath("//a[contains(text(), 'Delete permamently')]"));
users_list.filter(function(user_row, index) {
return user_row.getText().then(function(text) {
return if(re.test(text)) { //assuming this checks the match with email id
user_row.delete_btn.click();
}
});
})
// some assertion, not relevant right now
});
});

bootstrap-table: how to nest one table into another?

I'm using this bootstrap-table. I'd like to nest one table into another.
$(document).ready(function() {
var t = [{
"id": "1",
"name": "john",
}, {
"id": "2",
"name": "ted"
}];
//TABLE 1
$('#summaryTable').bootstrapTable({
data: t,
detailFormatter: detailFormatter
});
function detailFormatter(index, row, element) {
$(element).html(row.name);
$(element).html(function() {
//I was thinking of putting the code here, but I don't know how to do it so it will work,
//except javascript, it needs to be put this html code <table id="detailTable"></table>
});
// return [
// ].join('');
}
//TABLE 2
var t2 = [{
"id": "1",
"shopping": "bike",
}, {
"id": "2",
"shopping": "car"
}];
$('#detailTable').bootstrapTable({
data: t2,
columns: [{
field: 'id',
title: 'id'
}, {
field: 'shopping',
title: 'Shopping detail'
}, {
field: 'status',
checkbox: true
}],
checkboxHeader: false
});
$('#detailTable').on('check.bs.table', function(e, row, $el) {
alert('check index: ' + row.shopping);
});
$('#detailTable').on('uncheck.bs.table', function(e, row, $el) {
alert('uncheck index: ' + row.shopping);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.10.0/bootstrap-table.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.10.0/bootstrap-table.min.js"></script>
<div class="container">
<p>TABLE 1</p>
<table id="summaryTable" data-detail-view="true">
<thead>
<tr>
<th data-field="id" data-align="center" data-width="20px">id</th>
<th data-field="name" data-align="center">Name</th>
</tr>
</thead>
</table>
<br>
<p>TABLE 2</p>
<table id="detailTable"></table>
</div>
Here is the link of my demo: fiddle
There are two tables. Table 1 has expandable rows and I want to put Table 2 into every row of table 1. There is this function called detailFormatter which does this and where you can return a string or render an element (I was playing with it, but I can't make it work). For this demo the table 1 is created with some html code and the table 2 uses only javascript, but there is this initiating div <table id="detailTable"></table> (it doesn't matter for me which way is done). So, the question is how to put the table 2 into table 1 with possibility of using its events (like check or uncheck checkbox) as the demo shows for table2? Later on, I'd like to use this event onExpandRow so when the user expands the row of table 1 it will get the data from a database and it'll fill out the table 2.
Well just clone your detailTable and put it in each row with detailFormatter as below:
function detailFormatter(index, row, element) {
$(element).html($('#detailTable').clone(true));
}
Now there will be duplicate id's created when you do clone, so you just remove it by changing its id as below:
function detailFormatter(index, row, element) {
$(element).html($('#detailTable').clone(true).attr('id',"tbl_"+row.id));
}
Also, you can hide the #detailTable since you are just having it to append it in another table and once you hide it you need to add show to cloned tables as all the properties will be copied to in clone(true) which can be done as below:
function detailFormatter(index, row, element) {
$(element).html($('#detailTable').clone(true).attr('id',"tbl_"+row.id).show());
}
//.....
//.....
//.....
//At the end
$("#detailTable").hide();
A complete DEMO
I found another way of nesting one table into another using (partly) dynamic table creation (referring to my posted question when using bootstrap-table).
var expandedRow = row.id;
$(element).html(
"<table id='detailTable"+expandedRow+"'><thead><tr><th data-field='id2' data-align='center' data-width='20px'>id2</th>" +
"<th data-field='shopping' data-align='center'>Shopping detail</th>" +
"<th data-field='status' data-checkbox='true'></th>" +
"</tr></thead></table>");
$('#detailTable'+expandedRow).bootstrapTable({
data: t2,
checkboxHeader: false
});
I think this way is more independent. There is no need to have one panel opened at the time. The events and methods seems to be working fine.
Full code here.

How do I get the id for a <tr> in when using jQuery DataTables?

I am adding a button that will "approve" all rows in the table (call a URL to process the record). I generate the table then attach the DataTable to the prefilled table. On each tr I have the id number of the record.
<tr id="11309742">
<td>blah</td>
<td>blah</td>
<td>blah</td>
</tr>
<tr id="11309743">
<td>blah</td>
<td>blah</td>
<td>blah</td>
</tr>
Here is what I have so far:
$.each(table.fnGetData(), function (i, row) {
var id = $(this).attr("id");
$.get(myUrl, { id: id },
function (json) {
if (json.Sucess) {
// TODO remove from the page
}
}, "json");
});
var id = $(this).attr("id"); worked before I switched to the datatable plugin (and I know it won't work now). Everything I have seen is either setting the id or getting the index from a click in the row. How do I get that id attribute in a loop?
Instead of using .fnGetData(), I should have used .fnGetNodes().
$.each(table.fnGetNodes(), function (i, row) {
var id = $(this).attr("id");
$.get(myUrl, { id: id },
function (json) {
if (json.Sucess) {
//table.fnDeleteRow(i);
}
}, "json");
});
Now it works as expected.

JQuery loop through table get ID and change values in a specific column

I have a page with 2-3 tables. In those tables I want to change the text of a specific column located in <thead> and also a value in each <td> line, and I would like to get the id from each line.
What is the fastest way to do this, performance-wise?
HTML
Table-Layout:
<table class="ms-viewtable">
<thead id="xxx">
<tr class ="ms-viewheadertr">
<th>
<th>
<tbody>
<tr class="ms-itmHover..." id="2,1,0">
<td>
<td>
<tr class="ms-itmHover..." id="2,2,0">
<td>
<td>
</table>
JavaScript
Script with that I started:
$('.ms-listviewtable').each(function () {
var table = $(this);
$table.find('tr > th').each(function () {
//Code here
});
$table.find('tr > td').each(function () {
//Code here
});
How can I get the Id? Is this there a better way to do what I want?
You can get the id of an element by calling .attr on "id" i.e. $(this).attr("id");.
In jquery the best way to get to any element is by giving it an ID, and referencing it.
I would structure it the other way around - give the table elements meaningful IDs, and then put the information that I'd like to retrieve in their class attributes.
<tr id="ms-itmHover..." class="2,2,0">
And then retrieve it as follows: $('#ms-itmHover...').attr('class');
You can get the IDs by "mapping" from table row to associated ID thus:
var ids = $table.find('tbody > tr').map(function() {
return this.id;
}).get();
You can access individual cells using the .cells property of the table row:
$table.each('tbody > tr', function() {
var cell = this.cells[i]; // where 'i' is desired column number
...
});
Go thru all tables, collect all rows and locate their identifiers by your needs:
$('table.ms-viewtable').each(function(){
$(this).find('tr').each(function(){
var cells = $(this).children(); //all cells (ths or tds)
if (this.parentNode.nodeName == 'THEAD') {
cells.eq(num).html('header row '+this.parentNode.id);
} else { // in "TBODY"
cells.eq(num).html('body row '+this.id);
}
});
});
jsfiddle

Categories