ASP.NET: Inserting table cells programmatically - html

I have a method which returns a List<string> which my code uses to populate a table:
string[] siteNames;
siteNames = client.GetListSiteElementNames();
foreach (string siteName in siteNames)
{
TableCell tempCell = new TableCell();
tempCell.Text = siteName;
this.sitesTableRow.Cells.Add(tempCell);
}
This inserts the cells on to a single row, so the cells are presented horizontally across the screen (how I would like), but because they are 20 or so of them, they go off the page meaning you need to scroll across to view the rest.
Is there any way I can do this so that the cells cut off at the edge of the window and onto a new line?

To do this you will need to add a new row after a certain cut off point (i.e. certain number of columns)
In the example below I use a cut off of 5 :
string[] siteNames;
siteNames = client.GetListSiteElementNames();
// Number of cells on each row
int cutOffPoint = 5;
int currentNum = 1;
foreach (string siteName in siteNames) {
TableCell tempCell = new TableCell();
tempCell.Text = siteName;
if (currentNum > cutOffPoint) {
currentNum = 1;
// Code to add new row to table
}
this.sitesTableRow.Cells.Add(tempCell);
currentNum++;
}
Because I'm not sure what the this object is referring to or the sitesTableRow I can't include the code to add the row, but the idea would be that after 6 cells you would reset the currentNum variable and add a new row, and append the cells to this new row.

Related

Copy table with inline images

I am trying to copy the contents of a GDoc into another GDoc. This works pretty well for all the different element types. Including a table (Enum DocumentApp.ElementType.TABLE). However, if the table contains an inline image (Enum DocumentApp.ElementType.INLINE_IMAGE) the image is not copied correctly.
Here is a link to the source GDoc example. https://docs.google.com/document/d/14kXjC0CTkEgmD7Ttv0YKL9ubfDRHbL1hCVOqOiyiEDU/edit#. Find the row in the table with the New Zealand flag. The flag is not copied correctly into the target GDoc's new table.
I am simply finding the table object in the source document (above) and using Body::insertTable(childIndex,table) to insert it into the target GDoc's Body. Most other elements in the table copy OK. Including an embedded Google Drawing. But not the inline image.
I had a similar problem and in my case, the GLYPH_TYPE of numbered lists got lost, too. But I detected that the images will be fine copied if the CellChildren are copied one by one.
So I solved my problem by copying the new table at whole and then replacing the contents of each dstTable cell one by one from the original table.
This works fine now even with nested tables, since the function calls itself, if another table within the table is detected.
And the problem with the lost ListItem attribute is solved, too by setting the attributes additionally after the insert.
Here is my well working code segment:
Firstly I detect the table and insert it in the dstBody ...
...
dstChild = srcChild.copy();
switch( dstChild.getType() ) {
case DocumentApp.ElementType.PARAGRAPH:
...
case DocumentApp.ElementType.LIST_ITEM:
...
case DocumentApp.ElementType.TABLE:
var newTable =
dstBody.insertTable( dstBody.getNumChildren()-1, dstChild );
copyTableCellByCell( dstChild, newTable );
break;
....
}
And this is the maybe recursive function that replaces each cell by first clearing it and copying the content from the original table:
function copyTableCellByCell( srcTable, dstTable ) {
var numRows = dstTable.getNumRows();
var dstRow, numCells, dstCell, actCellIndex;
for ( var actRowIndex = 0; actRowIndex < numRows; actRowIndex++ ) {
dstRow = dstTable.getRow( actRowIndex );
numCells = dstRow.getNumCells();
for ( actCellIndex = 0; actCellIndex < numCells; actCellIndex++ ) {
dstCell = dstRow.getCell( actCellIndex );
dstCell.clear();
var srcCell = srcTable.getCell( actRowIndex, actCellIndex );
var numCellChildren = srcCell.getNumChildren();
for ( var y = 0; y < numCellChildren; y++ ) {
var cellChild = srcCell.getChild( y );
var childCopy = cellChild.copy();
switch( childCopy.getType() ) {
case DocumentApp.ElementType.PARAGRAPH:
dstCell.insertParagraph( y, childCopy );
break;
case DocumentApp.ElementType.LIST_ITEM:
// that the GLYPH_TYPE doesn't get lost
var atts = childCopy.getAttributes();
var
newListItem = dstCell.insertListItem( y, childCopy );
newListItem.setAttributes( atts );
break;
case DocumentApp.ElementType.TABLE:
var newTable =
dstCell.insertTable( y, childCopy );
copyTableCellByCell( cellChild, newTable );
break;
}
}
// remove the very first empty paragraph in the cell
while ( (y = dstCell.getNumChildren()) > numCellChildren ) {
dstCell.getChild( y - 1 ).removeFromParent();
}
}
}
}
This could be fine tuned, of course.
You could just search and pick out the inline images, if you want the servers have to do less work.
Methods that you can use to copy an Inline Image can be found in Class InlineImage and there are even additional methods if an inline image was contained within a ListItem or Paragraph.
I found a none coding solution to this bug.
Insert the image as a "drawing" in the source document.
Click the table cell where images needs to be inserted.
Click "insert" on the document's menu.
Click "insert drawing".
In drawing pane add image to be inserted.
Save and close.
The result will be an image in the table that gets copied perfectly along with the type TABLE.

counting the number of columns in a row of a HTML table using selenium xpath

I have to fetch the count of the columns present in a particular row using the selenium Xpath.
Following the code which I wrote for this:
WebElement table = CoreCommands.locateElement(context, By.xpath("//table[#id='addRowTable_selected_a']"));
if (table != null) {
List<WebElement> ts_rows = CoreCommands.locateElementList(context, table,By.xpath("//table[#id='addRowTable_selected_a']/tbody/tr"));
int ts_cntRows = ts_rows.size();
for(int i=4;i<=ts_cntRows;i++)
{
List<WebElement> ts_cols = CoreCommands.locateElementList(context, table,By.xpath("//table[#id='addRowTable_selected_a']/tbody/tr[i]/td"));
int ts_cntCols = ts_cols.size();
for(int j=1;j<=ts_cntCols;j++)
{
String str= CoreCommands.locateElement(context, By.xpath("//table[#id='addRowTable_selected_a']/tbody/tr[i]/td[j]")).getText();
System.out.println(str);
}
}
It is returning zero in ts_cntCols for any row.
There is problem with xpath used i hope.. Lets see in above used "//table[#id='addRowTable_selected_a']/tbody/tr[i]/td" which is nothing but string and not passing dynamic i value, correct? so try like below
"//table[#id='addRowTable_selected_a']/tbody/tr["+i+"]/td"
similarly do same for columns xpath also to get text.
Thank You,
Murali
An example counting the number of cells for each row from row 3:
WebDriver driver = new FirefoxDriver();
driver.get("http://the-internet.herokuapp.com/tables");
// iterate each row from row 3
List<WebElement> rows = driver.findElements(By.xpath("//table[#id='table1']/tbody/tr[position() > 2]"));
for (WebElement row : rows) {
// get all the cells from the row
List<WebElement> cells = row.findElements(By.cssSelector("td"));
// print the number of columns
System.out.printf("columns: %d%n", cells.size());
// iterate each column
for (WebElement cell : cells) {
// print the content
System.out.println(cell.getText());
}
}
driver.quit();

How do I select a part of an array? Or match parts of one array with parts of another?

I have some drag and drop function where there are 8 items (dragArray) that can be dropped onto 2 big 'landing zones' (matchArray). But since I don't want them lie on top of each other, I've made an array where they are given positions (posArray).
var dragArray:Array = [drag_1, drag_2, drag_3, drag_4, drag_5, drag_6, drag_7, drag_8];
var matchArray:Array = [drop_1, drop_1, drop_1, drop_1, drop_2, drop_2, drop_2, drop_2];
var posArray:Array = [{x:412,y:246},{x:530,y:218},{x:431,y:186},{x:470,y:152},{x:140,y:111},{x:108,y:162},{x:179,y:210},{x:113,y:254}];
When all 8 items are dropped, a check button appears and I want to check if they are dropped onto the correct big landing zone. I tried using the following:
if (posArray[i].x != dragArray[i].x || dragArray[i].y != posArray[i].y )
But then, not only the landing zone must match, but the positions must also match.
When I use
if (matchArray[i].x != dragArray[i].x || dragArray[i].y != matchArray[i].y )
it doesn't work, because the positions of the (dragArray) items don't match with the registration points of the (matchArray) landing zones.
Is there any way of checking if the first 4 (drag_1, drag_2, drag_3, drag_4) items match with ANY of the first 4 posArray positions and the last 4 (drag_5, drag_6, drag_7, drag_8) match with ANY of the last 4 posArray positions?
If the goal is to check each element of one set against all elements of another set then you'll need to have two loops, one "nested" within the other. The general form of this algorithm in AS3 looks like
var allMatched:Boolean = true;
for(var i:Number=0; i<array1.length; i++)
{
var matchFound:Boolean = false;
for(var j:Number=0; j<array2.length; j++)
{
if(array1[i]==array2[j])
{
matchFound=true;
break; //exit the inner loop we found a match
}
}
if(!matchFound)
{
allMatched=false;
break; //we found an element in one set not present in the other, we can stop searching
}
}
if(allMatched)
trace("Everything from array1 was found somewhere in array2"); //For an element a in the set A there exists an element b in set B such that a = b
Let me know if this helps

Remove multiple rows in a single pass in JTable AbstractDataModel

i've got an issue with Jtable and my dataModel.
My table model extends AbstracttableModel, the datas are stored in a Vector.
I'have a function witch is suppose to remove one or more row.
These rows are not necessarily contiguous because my jtable set a selectionMode as this:
jTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
The function to remove row (one by one):
public void removeMessageRow(Integer p_idMessage) {
Enumeration<MlMessage> alldatas = vData.elements();
while (alldatas.hasMoreElements()) {
MlMessage m = alldatas.nextElement();
if (m.getIdMessage() == p_idMessage) {
int idx = vData.indexOf(m);
boolean result = vData.remove(m);
// fireTableDataChanged();
// fireTableRowsDeleted(idx, idx);
fireTableStructureChanged();
return;
}
}
When i launch the function, i execute the loop without problem, in step-by-step mode, i can see the vData object updated and if i execute this only one time there is no probleme with the GUI. The problem appear when i select more than one row.
For example, i selected row number 0 and number 1 in my table and i lauch the function removeMessageRow, at the first execution, the vDataObject is correctly updated (all the datas are shiffted and the last elements of this vector is set to null by the call to vData.remove(m).
So in my case, i expect that at the second execution, the object to find should be at position 0 but it's at position 1 as the vData Object as never been updated.
Does anybody have an idea about that?
I've tried many on fire... stuff but no one semms to execute immediatly.
Thanks for any help by advance and sorry for my Shakespeare's language.
Add a method in your model taking a collection of indices to remove (Set<Integer>, or int[]), sort this collection, iterate backwards in this collection, and remove the elements in the list of objects of your model:
public void removeRows(int[] indices) {
Arrays.sort(indices);
for (int i = indices.length - 1; i >= 0; i--) {
this.data.remove(indices[i]);
fireTableRowsDeleted(indices[i], indices[i]);
}
}
int[] selectedRow = tblUsuarios.getSelectedRows();
int del=1;
for(int j=0; j<selectedRow.length; j++){
modTabla.removeRow(selectedRow[j]);
if(j<selectedRow.length-1){
selectedRow[j+1] = selectedRow[j+1]-del;
del = del+1;
}
}
//modTabla = defaultTableModel
//tblUsuarios = jtable

Show "no rows found" inside a JTable row if not found entry while filtering

i have a JTable with row filter.
once fitered if i didn't get any row then i have to show a string like "Nothing found to display " inside table as first row.
please do needful.
Thanks ,
Narasimha
I needed to solve this exact problem today and wasn't able to find a good answer online. In the end I came up with my own solution, which I think may be exactly what you want. I don't know if this is too late for your project, but perhaps it can help others:
JTable.paintComponent(Graphics g) will not be called unless the table has a height that is greater than 0. This causes a problem for empty tables, so we expand the JTable height if needed so that it will always be at least the size of the JViewport that is it's parent.
JTable tableName = new JTable() {
public boolean getScrollableTracksViewportHeight() {
if(getParent() instanceof JViewport)
return(((JViewport)getParent()).getHeight() > getPreferredSize().height);
return super.getScrollableTracksViewportHeight();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(getRowCount() == 0) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.drawString("Nothing found to display.",10,20);
}
}
}
containerName.add(new JScrollPane(tableName));
To show a line of text in the multicolumn table can be quite difficult, the span AFAIK is not supported.
One possibility would be to hide all data columns (to show them later you have to memorize them somewhere) and show one column for the message.
An easier way would be to create a JPanel with CardLayout, add 2 cards - one containing table and one containing your empty data warning. If the filter returns empty result, show the card with empty warning, in other case - show the table.
If the filter has excluded all rows, the result returned by getViewRowCount() will be zero. You can update the GUI accordingly; setToolTipText() is handy if screen space is lacking.
Here's an example:
TableModel model = ...
JTable table = new JTable(model);
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane pane = new JScrollPane(table);
JLabel label = new JLabel("");
...
String s = "Rows: " + sorter.getViewRowCount()
pane.setToolTipText(s);
label.setText(s);