Conclusion
At this point, we’re finished with the tutorial. I hope that this information was helpful. I’m certain that there are other ways of accomplishing the goal we’ve achieved here; if you want to improve the code or expand it, feel free. One thing that I haven’t yet incorporated is a method to handle row spans. Perhaps that will be the next step. Good luck!
Meanwhile, Listing 7 shows the entire TableViewer.as class. The source.zip file contains all of the source code for downloading.
Listing 7 The TableViewer.as class.
import com.xfactorstudio.xml.xpath.XPath; class com.extension.TableViewer { // define global variables private var TableFile:XML; private var TimeLine:MovieClip; private var Base_mc:MovieClip; private var Border_mc:MovieClip; private var Boxes_mc:MovieClip; private var AllBoxes:Array; private var AllTexts:Array; private var Rows:Array; private var Cells:Array; private var CellsMax:Array; private var CellNumbers:Array; private var AllTextBoxes:Array; private var BackgroundColor:Number; private var CellWidth:Number; private var TableWidth:Number; private var TableHeight:Number; private var TablePadding:Number; //********************************** // pass in a movie clip, the xml, and the desired width of the table //********************************** public function TableViewer(mc:MovieClip, xml:XML, tableWidth:Number, maxTableHeight:Number) { TimeLine = mc; TableFile = new XML(xml.toString()); AllBoxes = new Array(); AllTexts = new Array(); Cells = new Array(); CellsMax = new Array(); CellNumbers = new Array(); AllTextBoxes = new Array(); BackgroundColor; TableWidth = tableWidth; TablePadding; // create necessary clips Base_mc = TimeLine.createEmptyMovieClip("base_clip", TimeLine.getNextHighestDepth() ); Border_mc = Base_mc.createEmptyMovieClip("borders_clip", Base_mc.getNextHighestDepth() ); Boxes_mc = Base_mc.createEmptyMovieClip("boxes_clip", Base_mc.getNextHighestDepth() ); TableController(); } private function ExtractColor(color:Array):Number { // removes the # sign and returns hex value as a Number type if(color) { var colorStr:String = color[0].toString(); var stringTest:Number = colorStr.indexOf("#"); if (stringTest != -1) { var colorValue:String = "0x"+colorStr.substring(stringTest+1, colorStr.length); } } var returnColor:Number = parseInt(colorValue); return returnColor; } //********** // TableController method ensures that methods are called in the proper order //********** private function TableController() { var tableBuilt:Boolean = TableBuilder(); if (tableBuilt == true) { CreateTextBoxes(); CreateAndPositionGrid(); } } //********** // gather all of the table data from the table source file and write that data into arrays //********** private function TableBuilder():Boolean { // if TableWidth has not been set, look for a width attribute, capture it, else set the table to 20 less than the Stage.width if (!TableWidth) { var tempWidth:Array = XPath.selectNodes(TableFile.firstChild, "/table/@width"); if (tempWidth[0] != undefined) { TableWidth = parseInt(tempWidth[0]); } else { TableWidth = Stage.width - 20; } } // if the table has a padding attribute set, capture it, else set the padding to 0 var tempPadding:Array = XPath.selectNodes(TableFile.firstChild, "/table/@padding"); if (tempPadding[0] != undefined) { TablePadding = parseInt(tempPadding[0]); } else { TablePadding = 0; } // get the background color for entire table, else set it to white var bg = XPath.selectNodes(TableFile.firstChild, "/table/@bgcolor"); if (bg.length > 0 ) { BackgroundColor = ExtractColor(bg); } else { BackgroundColor = 0xffffff; } // grab all the rows into an array, then use rows to grab all the cells into an array Rows = XPath.selectNodes(TableFile.firstChild, "/table/tr"); // foreach row, get all the values for all the cells for (var x:Number = 0; x< Rows.length; x++) { var currentRow:Number = x+1; // get cells from td and th tags Cells.push(XPath.selectNodes(TableFile.firstChild, "/table/tr[position() = "+ currentRow +"]/td | /table/tr[position() = "+ currentRow +"]/th")); } //*********************** // goal: determine which row has the most cells so we can calculate how wide to make individual cells // how: // push number of cells per row onto CellsTotal // sort by number :NUMERIC // reverse to put highest number first... // use CellWidth to calculate max cell widths... //*********************** for (var x:Number = 0; x<Cells.length; x++) { CellsMax.push(Cells[x].length); CellNumbers.push(Cells[x].length); } CellsMax.sort(Array.NUMERIC); CellsMax.reverse(); CellWidth = Math.floor(TableWidth / CellsMax[0]); return true; } //********** // create the text boxes based on the Cells multidimensional array (tr1(td1,td2), tr2(td1,td2) ... //********** private function CreateTextBoxes() { for (var x:Number = 0; x<Cells.length; x++) { // used to create multi-dimensional array AllTextBoxes at the end of the for loop var textBoxArray:Array = new Array(); var cellAlignment:String = "center"; var boxArray:Array = new Array(); var textBoxArray:Array = new Array(); // create textboxes and insert values for (var i:Number = 0; i<Cells[x].length; i++) { var currentCell:Number = i + 1; // create text clips and populate var currentBox:MovieClip = Boxes_mc.createEmptyMovieClip("box"+x+"_"+i, Boxes_mc.getNextHighestDepth()); var currentText:Object = currentBox.createTextField("cell_txt", currentBox.getNextHighestDepth(), 0, 0, CellWidth, 125); boxArray.push(currentBox); textBoxArray.push(currentText); currentText.multiline = true; currentText.wordWrap = true; currentText.autoSize = "center"; currentText.border = false; currentText.html = true; var formatting = new TextFormat(); formatting.color = 0x333333; formatting.font = "verdana"; formatting.size = 10; formatting.align = cellAlignment; currentText.htmlText = Cells[x][i]; currentText.setTextFormat(formatting); } // textBoxArray contains all movieClip path for the textFields in a particular row // push these onto AllTextBoxes to have them all in one place // for use in CreateAndPositionGrid AllBoxes.push(boxArray); AllTexts.push(textBoxArray); } } private function CreateAndPositionGrid() { var rHeight:Number = 0; var finalRowHeights:Array = new Array(); finalRowHeights.push(0); var finalCellWidths:Array = new Array(); for (var x:Number = 0; x < Cells.length; x++) { var colCounter:Number = 0; var cellHeights:Array = new Array(); var cellWidths:Array = new Array(); for (var i:Number = 0; i < Cells[x].length; i++) { var curRow:Number = x+1; var curCell:Number = i+1; var colspanValue:Array = XPath.selectNodes(TableFile.firstChild, "/table/tr[position() = "+ curRow +"]/td[position() = "+ curCell +"]/@colspan"); var colSpan:Number = 1; // if colspan exists if (colspanValue.length != 0) { colSpan = parseInt(colspanValue[0]); } AllBoxes[x][i]._x = (colCounter*CellWidth)*colSpan; AllBoxes[x][i]._y = rHeight; var calTextWidth:Number; if (colspanValue.length != 0) { colCounter = colSpan; calTextWidth = colCounter*CellWidth; AllTexts[x][i]._width = calTextWidth; } else { colCounter++; } cellHeights.push(AllTexts[x][i]._height); cellWidths.push(AllTexts[x][i]._width); } // sort rowHeights to find the highest cell height cellHeights.sort(Array.NUMERIC); cellHeights.reverse(); var curRowMaxHeight:Number = Math.floor(cellHeights[0]); // increment rHeight with current row’s maximum height rHeight = rHeight + curRowMaxHeight; finalRowHeights.push(rHeight); finalCellWidths.push(cellWidths); // draw the outer and row borders Border_mc.lineStyle(1, 0x999999, 100); Border_mc.moveTo(0, 0); Border_mc.lineTo(TableWidth, 0); Border_mc.lineTo(TableWidth, rHeight); Border_mc.lineTo(0, rHeight); Border_mc.lineTo(0, 0); } // draw inner vertical lines for (var n:Number = 0; n<finalRowHeights.length; n++) { Border_mc.lineStyle(1, 0x999999, 100); var cellCalc:Number = 0; for (var z:Number = 0; z<finalCellWidths[n].length-1; z++) { cellCalc = cellCalc + parseInt(finalCellWidths[n][z]); Border_mc.moveTo(cellCalc, finalRowHeights[n]); Border_mc.lineTo(cellCalc, finalRowHeights[n+1]); } } } }