CasperJS getElementsByXPath only returning first element - javascript

I use the following code to get all table cells in the first table row. I'd like to then check the innerHTML of every single table cell. But in the object returned by this function only the first table cell is actually there, all the other properties are null:
firstRow = this.evaluate(function () {
return __utils__.getElementsByXPath('//tbody/tr[1]/td');
});
utils.dump(firstRow);
The output from utils.dump is:
[
{
"abbr": "",
"align": "",
"attributes": {...}
},
null,
null,
null
]
I also tried with utils.findAll and it was the same. How can I get all the matched elements?

With Casper/PhantomJS evaluate() functions, you have to map native DOM elements and lists of elements to something JSON-serializable:
var firstRow = this.evaluate(function () {
var elements = __utils__.getElementsByXPath('//tbody/tr[1]/td');
return [].map.call(elements, function(element) {
return element.outerHTML;
});
});
utils.dump(firstRow);

Related

Jquery data tables need to show only selected rows from an integer array of IDs

I have a drop down with checkboxes in it. When I select multiple items, I have a method which gets those IDs in an integer array. In my data table one of the column, lets say 'User_ID:name' has those IDs. I want to loop through the data table and show only rows of selected IDs in the integer array. If array is empty, no rows should be visible.
I wrote a method, but it's only showing me only 1 row and it keeps overwriting that row when looping through.
var Gridupdate = function () {
int[] checked = Checkbox.getCheckedIds(); /// integer array of selectedIDs from a checkbox
if (dtable) {
for (i = 0; i < checked.length; i++) {
dtable.column("User_ID:name").search(checked[i].toString()).draw();
}
}
}
You can use regex in "DataTables" to achieve this. Add this to your "DataTables' initialisation options".
"search": {
"regex": true, // enables the table to be filtered using regular expresion
"smart": false // disables the table's "smart search" ability. Ensures a more accurate search.
}
Example:
$('#example').DataTable( {
"search": {
"regex": true,
"smart": false
}
});
And change your method to this
var Gridupdate = function () {
var checked = Checkbox.getCheckedIds(); /// integer array of selectedIDs from a checkbox
if (dtable) {
dtable.column("User_ID:name").search(checked.join('|')).draw(); // eg .search(1|2|4)
}
};

Finding Table Start Location Index using Google Docs API

I want to make a InsertTableRow Request via Docs API and it requires a TableStartLocation.
I used
var tableName = table[0];
foreach (var element in document.Body.Content)
if (element.Table != null)
{
var checkTable = element.Table.TableRows[0].TableCells[0].Content[0].Paragraph.Elements[0]
.TextRun.Content.TrimEnd('\n'); //Get Text Value in first cell of the table
if (tableName.Equals(checkTable)) // Check if the table is the table that I want to add rows
{
Console.WriteLine("Add Table Row");
TableUpdateRequest(ref requests, table, element.StartIndex); // Using element(StructuralElement) to get StartIndex
break;
}
}
To find all table in a document and tried to use the element.StartIndex as Table Start Location but i got: Google.GoogleApiException : Google.Apis.Requests.RequestError Invalid requests[5].insertTableRow: Invalid table start location. Must specify the start index of the table. [400]
What is a suitable index for Table Start Location?
The tableStartLocation is necessary to identify the correct table
A way to retrieve it is e.g. with documents.get. To narrow down the results you can specify fields, e.g. body/content(startIndex,table).
This will return you a resource of the type
{
"body": {
"content": [
{},
{
"startIndex": 1
},
{
"startIndex": 2,
"table": {
"rows": 4,
"columns": 3,
"tableRows": [
{
...
In other words: You know now that your tableStartLocation is 2 - same as the table's startIndex.
Sample
var resource = { "requests": [
{
"insertTableRow": {
"tableCellLocation": {
"tableStartLocation": {
"index": 2
}
},
"insertBelow": false
}
}
]
}
Docs.Documents.batchUpdate(resource, documentId);
Now, depending on your document, you might have several tables and might want to compare names etc. before deciding which is the start index of the correct able.

JQuery Datatables Row Data From AJAX Source

In the past I've always used this to get a hidden column's data. I would hide the column with a css class, but the responsive feature doesn't work well with these.
var td = $('td', this);
var ID = $(td[0]).text();
So I found an alternative, by hiding the columns with these classes with the responsive feature.
"columnDefs": [
//Responsive classes
{ className: 'never', targets: 0 }, //Hide on all devices
{ className: 'all', targets: 1 }, //Show on all devices
]
and then I use either one of these.
var rowData = oTable1.fnGetData(this);
var rowData = oTable1.api().row(this).data();
//Grab the first indexed item in the list
var ID = rowData[0];
That works well if you don't have an AJAX source. It will return a comma separated list of the row data. However, when I try to use this with an AJAX source I just get [object Object] back (instead of a comma separated list) if I output the rowData variable in an alert.
How do I get the row data out of a table with an AJAX source?
It seem to be stored as string so [1, 2, 3] became [object Object] when you turn it into string. Do yourString = yourList.join(',') and store yourString to keep the coma-separated string.
For an object:
yourString = (function () {
var list = [];
for(var i in yourList)
if(yourList.hasOwnProperty(i))
list.push(yourList[i]);
return list.join(',');
})();
The function is not needed, it's just to limit the variables scope.
I ended up using an answer I found here.
Converting a JS object to an array
I can pull the entire row data from the table with this.
var rowData = oTable1.api().row(this).data();
In the console log I can see that it returns a javascript object like this.
Object { id="123456", full_name="Samuel Smith", Last_name="Smith" }
I use this function to convert the object into an array.
var array = $.map(rowData, function (value, index) {
return [value];
});
In the console log, my array would appear like this.
["123456", "Samuel Smith", "Smith"]
I can then extract any item from the array like this.
alert(array[0]);
Simplifying madvora's example:
var rowData = oTable1.api().row(this).data().to$();
rowDataArray = rowData.toArray();

Get value from nested JavaScript object in CasperJS

I'm trying to dig into a nested javascript array to grab the first instance of an object. Here's the code:
var utils = require('utils');
var casper = require('casper').create();
casper.start('http://en.wikipedia.org/wiki/List_of_male_tennis_players', function() {
this.echo(this.getTitle());
// Get info on all elements matching this CSS selector
var tennis_info_text = this.evaluate(function() {
var nodes = document.querySelectorAll('table.sortable.wikitable tbody tr');
return [].map.call(nodes, function(node) { // Alternatively: return Array.prototype.map.call(...
return node.textContent;
});
});
// Split the array into an array of object literals
var tennis_data = tennis_info_text.map(function(str) {
var elements = str.split("\n");
var data = {
name : elements[1],
birth : elements[2],
death : elements[3],
country : elements[4]
};
return data;
});
// Dump the tennis_names array to screen
utils.dump(tennis_data.slice(1,5));
});
casper.run();
The result of stdout is this:
{
"name": "Acasuso, JoséJosé Acasuso",
"birth": "1982",
"death": "–",
"country": " Argentina"
},
{
"name": "Adams, DavidDavid Adams",
"birth": "1970",
"death": "–",
"country": " South Africa"
},...
For the name element, I'm getting everything from the tr row, which matches 2 elements when you look at the target url source. What I want is just the second part of the name element with class "fn"; for instance: "David Adams", "José Acasuso". I'm thinking something like name:elements[1].smtg should work, but I've had no luck.
Additionally, how would I print the available object keys from the elements object?
The problem is that the first cell contains two elements which contain the name and first name of the player with different ordering. When taking the textContent of the whole cell, both name representations are put into the same string, but in the browser only one of them is visible. If you want only to access the visible one, you need to explicitly crawl it.
You could write a custom function that removes the duplicate name from the string, but it is easier to just take the correct element's textContent.
This can be easily done in the page context:
var tennis_data = this.evaluate(function() {
var nodes = document.querySelectorAll('table.sortable.wikitable tbody tr');
return [].map.call(nodes, function(node) {
var cells = [].map.call(node.querySelectorAll("td"), function(cell, i){
if (i === 0) {
return cell.querySelector(".fn").textContent;
} else {
return cell.textContent;
}
});
return {
name: cells[0],
birth: cells[1],
...
}
});
});
Additionally, how would I print the available object keys from the elements object?
elements is an array of strings so there are no keys that you can access besides the array indexes and array functions.

Jquery: Autocomplete with label

I am trying to learn website development.
While learning autocomplete feature of jquery, I tried to put in the labels.
function autocomplete (data) {
var data = data.toString();
var availableTags = data.split(',');
var autocompleteData = [];
for (var i = 0; i < availableTags.length; i++){
autocompleteData[i] = {};
autocompleteData[i].label = i.toString();
autocompleteData[i].value = availableTags[i];
}
$("#tags").autocomplete({
source: autocompleteData,
select: function (event, ui) {
printautocomplete(event, ui)
}
});
};
The autocomplete[i].value is a valid string.
autocompleteData[0]
Object {label: 0, value: "Peter"}
However, I do not see any suggestions.
What is wrong with the way I am using the API?
The API says:
"Array: An array can be used for local data. There are two supported formats:
An array of strings: [ "Choice1", "Choice2" ]
OR An array of objects with label and value properties: [ { label: "Choice1", value: "value1" }, ... ]
The label property is displayed in the suggestion menu. The value will be inserted into the input element when a user selects an item. If just one property is specified, it will be used for both, e.g., if you provide only value properties, the value will also be used as the label. "
Thank you.
$('#sidebarSearch').autocomplete(
{
source: function(query, result)
{
var query = $('#sidebarSearch').val ();
$.ajax(
{
url:"sidebarSearchFetch.php",
method:"POST",
data:{query:query},
dataType:"json",
success:function(data)
{
result($.map(data, function(item)
{
return {
label: item.name,
value: item.usrId
};
}));
}
})
},
appendTo: "#sidebar-form"
});
I am skeptical of line 2 in your code (var data = String()data;) I would use: var data = data.toString();
But if you are sure that the autocompleteData elements do indeed have valid strings, then my best guess would be that perhaps you forgot to give the '#tags' id to your html entry field element.
Finally, if this is not it, to troubleshoot, I would try removing the select: option from the object you are passing to autocomplete() in the line that begins: $("#tags").autocomplete(... so that only the source options is passed.
Another thing to check out is when the code is being run. It is possible that a document.ready() function is needed to ensure that that when the autocomplete feature is added to the DOM element with the id '#tags', that the element has already been created.
The autocomplete works fine. Instead of completing "value", it completes "label".
So when I type in "1", it suggests "1", "10", "11", etc.
Autocomplete applying value not label to textbox answers how to change to to by-value.

Categories

Resources