<HTML> <head> <title>DOM1, DOM2, CSS - DynaTable-Light demonstration</title> <script> //////////////////////////////////////////////////////////////////////////// // DynaTable version 1.0 // // Produced by Marcio Galli for Netscape Communications. // // Basic DOM/JS-based demonstration to dynamically create and remove table cells, // edit content, and set table properties. This demonstration uses DOM Core // Level 1 to create, remove and edit HTML elements dynamically. Also uses // DOM Level 2 Event Model to support mouse events like cell selection and // table positioning (drag). // // References: // // http://www.mozilla.org/docs/dom/technote/tn-dom-table/index.html // http://dmoz.org/Computers/Programming/Languages/JavaScript/W3C_DOM/ // http://developer.iplanet.com/viewsource/goodman_w3c/goodman_w3c.html // http://www.geckonnection.com // global_selectedNode=null; // GLOBAL VARIABLE to store the selected // node. //////////////////////////////////////////////////////////////////////////// // dd_dynatable - constructor // // This method creates the table as a child of the body element. The table // is initialized with one cell. It uses DOM1. // function dd_dynatable() { // The following structure is created: // // editcanvas* // | // +---table // | // +---tbody // | // +---tr // | // +---td // | // +---#text // // * - Editcanvas already exists in the document. // See HTML in the end of this file. // Creates separated nodes. // mytable=document.createElement("TABLE"); mytableBody=document.createElement("TBODY"); mycurrentRow=document.createElement("TR"); mycurrentCell=document.createElement("TD"); mycurrentText=document.createTextNode("a generic text"); // Appends each node following the structure. // mycurrentCell.appendChild(mycurrentText); mycurrentRow.appendChild(mycurrentCell); mytableBody.appendChild(mycurrentRow); mytable.appendChild(mytableBody); // mybody receives editcanvas object. // mybody=document.getElementById("editcanvas"); // Adds beginDrag as event listener for mousedown events // over mybody (editcanvas div). // mybody.addEventListener("mousedown",beginDrag, false); // Appends mytable object tree as a child of mybody. // mybody.appendChild(mytable); // Sets table border to 2. // mytable.setAttribute("border","2"); // Assigns global_selectedNode with mycurrentText. // This way, the default selected text is the first // cell's text. global_selectedNode=mycurrentText; //------------------------------------------- // DOM 2 - Usage of addEventListener method //------------------------------------------- // Add refreshContent function as event handler to // receive mousedown events. This way, each time the user clicks // the mouse over mycurrentCell node, refreshContent will be // called and event context information (Event object) will be // passed as arguments. // mycurrentCell.addEventListener("mousedown",refreshContent, false); mycurrentCell.setAttribute("bgcolor","cyan"); //------------------------------------------- // Internal dd_dynatable attributes // this.cursorx=0; // X position for selected cell. this.cursory=0; // Y position for selected cell. this.mytablebody=mytableBody; // Stores mytablebody for later use. this.cols=1; // Number of cols. this.rows=1; // Number of rows. this.createrow = dd_dynatable_createrow; // Method assignment. this.createcol = dd_dynatable_createcol; // Method assignment. this.removerow = dd_dynatable_removerow; // Method assignment. this.removecol = dd_dynatable_removecol; // Method assignment. this.putcontent = dd_dynatable_putcontent; // Method assignment. this.updateSelected = dd_findSelectedCell; // Method assignment. } //////////////////////////////////////////////////////////////////////////// // DD API - dd dynatable method // do not modify // This method creates a row after the current row, based on the current selected cell. // // Note: this method uses this.cursorx and this.cursory attributes. // function dd_dynatable_createrow() { // Creates a new row element with #this.cols cells inside. // mycurrent_row=document.createElement("TR"); // For the number of columns of the table... for(i=0;i<this.cols;i++) { // Creates a TD element. mycurrent_cell=document.createElement("TD"); // Creates a text node object using the form's textfield as text value. // currenttext=document.createTextNode(document.forms[0].tarea.value); // Add refreshContent function as event handler to // receive mousedown events. // mycurrent_cell.addEventListener("mousedown",refreshContent, false); // Makes assignments: currenttext as a child of cell and cell as // a child of row. mycurrent_cell.appendChild(currenttext); mycurrent_row.appendChild(mycurrent_cell); } // Call to dd_findSelectedCell to find the position of the // current selected cell. this.updateSelected(); // updateSelected write the row and // column position of the selected // cell in the this.cursorx and // this.cursory attributes. // Now appending the created row (mycurrent_row) in the table. if(this.cursorx<(this.rows-1)) { // Appends this row before the next row based on the current selected // node position. // myTRs=this.mytablebody.getElementsByTagName("TR"); lastTR=myTRs.item(this.cursorx+1); this.mytablebody.insertBefore(mycurrent_row,lastTR); } else { // If the current selected node is inside the last // row, it uses appendChild to append it to the end of the child // list. this.mytablebody.appendChild(mycurrent_row); } this.rows++; // Updates the row number attribute. } //////////////////////////////////////////////////////////////////////////// // DD API - dd dynatable method // do not modify // This method creates a column right after the next cell based on the // current selected cell. // function dd_dynatable_createcol() { // Call to dd_findSelectedCell to find the position of the // current selected cell. this.updateSelected(); // updateSelected writes the row and // column position of the selected // cell in the this.cursorx and // this.cursory attributes. for(i=0;i<this.rows;i++) { // Creates a TD element mycurrent_cell=document.createElement("TD"); // Creates a text node object using the form's textfield // as text value. // currenttext=document.createTextNode(document.forms[0].tarea.value); // Assigns currenttext as a child of mycurrent_cell mycurrent_cell.appendChild(currenttext); // Add refreshContent function as event handler to // receive mousedown events. // mycurrent_cell.addEventListener("mousedown",refreshContent, false); // Now appending the created cell (mycurrent_cell) in // next right to the selected column. // if(this.cursory<(this.cols-1)) { // Inserts each cell before the next cell based on the // current selected cell. // myTRs=this.mytablebody.getElementsByTagName("TR"); currentTR=myTRs.item(i); myTDs=currentTR.getElementsByTagName("TD"); nextTD=myTDs.item(this.cursory+1); currentTR.insertBefore(mycurrent_cell,nextTD); } else { // If the current selected cell is in the last // column, then append the child to the // end. // myTRs=this.mytablebody.getElementsByTagName("TR"); currentTR=myTRs.item(i); currentTR.appendChild(mycurrent_cell); } } this.cols++; // Updates the col number attribute. } //////////////////////////////////////////////////////////////////////////// // DD API - dd dynatable method // do not modify // This method removes a row which contains the current selected cell. // function dd_dynatable_removerow() { // Call to dd_findSelectedCell to find the position of the // current selected cell. this.updateSelected(); // updateSelected writes the row and // column position of the selected // cell in the this.cursorx and // this.cursory attributes. myTRs=this.mytablebody.getElementsByTagName("TR"); // Finds the item (selected X) currentTR=myTRs.item(this.cursorx); // Removes the element this.mytablebody.removeChild(currentTR); // Updates the row attribute. this.rows--; } //////////////////////////////////////////////////////////////////////////// // DD API - dd dynatable method // do not modify // This method removes a column which contains the current selected cell. // function dd_dynatable_removecol() { // Call to dd_findSelectedCell to find the position of the // current selected cell. this.updateSelected(); // updateSelected writes the row and // column position of the selected // cell in the this.cursorx and // this.cursory attributes. // For each row, remove a TD. for(i=0;i<this.rows;i++) { // Stores in currentTR the current TR object for each row. // myTRs=this.mytablebody.getElementsByTagName("TR"); currentTR=myTRs.item(i); myTDs=currentTR.getElementsByTagName("TD"); // oldTD assigns the TD in the same column of the selected cell. // oldTD=myTDs.item(this.cursory); // Removes the oldTD from the currentTD. currentTR.removeChild(oldTD); } // Updates the columns number attribute. this.cols--; } //////////////////////////////////////////////////////////////////////////// // DD API - dd dynatable method // do not modify // function dd_findSelectedCell() { // This method is a Tree Walker: // // It walks the table tree to find the position of the selected // cell (global_selectedNode.parentNode) and stores the result // in the this.cursorx and this.cursory attributes. // // Marks the selected cell with an attribute and a value. selectedTD=global_selectedNode.parentNode; selectedTD.setAttribute("mark","mark"); // walks the table tree looking for the mark. myTRs=this.mytablebody.getElementsByTagName("TR"); foundx=0; foundy=0; for(i=0;i<myTRs.length;i++) { currentTR=myTRs.item(i); myTDs=currentTR.getElementsByTagName("TD"); for(j=0;j<myTDs.length;j++) { currentTD=myTDs.item(j); temp=currentTD.getAttributeNode("mark"); // If found a TD with attribute named mark... if(temp) { // and a value also named mark... if(temp.value=="mark") { // then stores the values! foundx=i; foundy=j; } } } } // Cleaning house! - removing the mark attribute. selectedTD.removeAttribute("mark"); // Stores the found values so external methods can use them!! this.cursory=foundy; // Stores the x and y position this.cursorx=foundx; // for external use. } //////////////////////////////////////////////////////////////////////////// // DD API - dd dynatable method // do not modify // This event handler function is called when the user clicks over // function refreshContent(e) { if(e.target.parentNode.nodeName=="TD") { // Paints the parent's node of the // selected node. This is the // UI feedback to unselect the cell. // currentTD=global_selectedNode.parentNode; currentTD.setAttribute("bgcolor","white"); // Designates event's target node as the // selected node. // global_selectedNode=e.target; // UI feedback - selects the cell // Sets attribute to cyan. // currentTD=e.target.parentNode; currentTD.setAttribute("bgcolor","cyan"); list=currentTD.childNodes; // Assigns form's textfield with // data value of the text node. // objq=list.item(0); document.forms[0].tarea.value=objq.data; } } //////////////////////////////////////////////////////////////////////////// // DD API - dd dynatable method // do not modify // function dd_dynatable_putcontent() { // currentTD is assigned with the selectedNode's parent object. // Note that selectedNode is the event target. It's not the // TD but the text whose the user clicked over. // currentTD=global_selectedNode.parentNode; // Makes bgcolor attribute value equals to red. It's a visual // feedback to the user. // currentTD.setAttribute("bgcolor","red"); // Removes the child elements of currentTD // for(i=0;i<currentTD.childNodes.length;i++) { mycelnode=currentTD.childNodes.item(i); currentTD.removeChild(mycelnode); } // Creates a new text node with textfield value as a content. currenttext=document.createTextNode(document.forms[0].tarea.value); // Updates the selected node. global_selectedNode=currenttext; // Appends currenttext as a child of currentTD. currentTD.appendChild(currenttext); } // *************************************************************************** // When page is loaded this is called. // See onload event in the body tag. // function start() { mytableobject=new dd_dynatable(); // Call the dd_dynatable // object constructor to // create the table and // dynatable attributes. animate_start(); // Spawn simple animation for the editcanvas // div. Note: editcanvas includes the table // that was generated in dd_dynatable function. } // *************************************************************************** // Just a call to mytableobject method. Originated from link onclick. // function create_row() { mytableobject.createrow(); } // *************************************************************************** // Just a call to mytableobject method. Originated from link onclick. // function create_col() { mytableobject.createcol(); } // *************************************************************************** // Just a call to mytableobject method. Originated from link onclick. // function remove_col() { mytableobject.removecol(); } // *************************************************************************** // Just a call to mytableobject method. Originated from link onclick. // function remove_row() { mytableobject.removerow(); } // *************************************************************************** // Just a call to mytableobject method. Originated from link onclick. // function put_content() { mytableobject.putcontent(); } //*************************************************************** // Starts the animation process for the edit element. // aa=26; // global attributes posleft=0; postop=0; function animate_start() { // aa counter decreases... aa--; // posleft and posttop receive the editcanvas left and top position. posleft=parseInt(document.getElementById("editcanvas").style.left); postop=parseInt(document.getElementById("editcanvas").style.top); // posleft and postop is increased by aa value. Note that it's a // "soft" animation. In the beginning the animation is speedy, // but in the end it's slow because aa (speed) is decreasing. // posleft+=aa; postop+=aa; // Style attributes of editcanvas are updated with posleft and // postop values. document.getElementById("editcanvas").style.left=posleft+"px"; document.getElementById("editcanvas").style.top=postop+"px"; // The animation ends when aa equals to zero. if(aa>0) { setTimeout("animate_start()",30); } } //------------------------------------------------------------------------------------- // DOM2/Event Model - Drag Support the Dynamic Table // These three methods are event handlers: // doDrag(e), beginDrag(e) and endDrag(e) // // beginDrag was registered in the table constructor function (dd_dynatable). // doDrag and endDrag are registered in beginDrag function. //------------------------------------------------------------------------------------- // doDrag event - called when dragging // function doDrag(e) { // Calculates the difference from the last stored position to // the current position. // var difX=e.clientX-window.lastX; var difY=e.clientY-window.lastY; // Retrieves the X and Y position of editcanvas. // var newX = parseInt(document.getElementById("editcanvas").style.left)+difX; var newY = parseInt(document.getElementById("editcanvas").style.top)+difY; // Sets the new position for the editcanvas div element. // Note: the table was created inside editcanvas div element; // this way, all editcanvas's child elements are affected by // positioning. // document.getElementById("editcanvas").style.left=newX+"px"; document.getElementById("editcanvas").style.top=newY+"px"; // Stores the current mouse position as last position. // window.lastX=e.clientX; window.lastY=e.clientY; } //---------------------------------------------------------------------------- // When drag begins, this function is called. // This event handler was registered in the table constructor function (dd_dynatable). // function beginDrag(e) { // Stores the current mouse position window.lastX=e.clientX; window.lastY=e.clientY; // Registering doDrag event handler to receive onmousemove events. window.onmousemove=doDrag; // Registering endDrag event handler to receive onmouseup events. window.onmouseup=endDrag; } //---------------------------------------------------------------------------- // Called when the mouse button is released. // This event handler was registered in beginDrag function. // function endDrag(e) { // Release doDrag event handler assignment. window.onmousemove=null; } </script> </head> <body onload="start()"> <div id="editcanvas" style="position:absolute;top:0px;left:0px"> </div> <div id="tedit" style="position:absolute;top:0px;left:0px"> <table border=1> <tr> <td> <li><a href="javascript:" onclick="create_row();">create row</a><br> <li><a href="javascript:" onclick="create_col();">create col</a><br> <li><a href="javascript:" onclick="remove_row();">remove row</a><br> <li><a href="javascript:" onclick="remove_col();">remove col</a><br> <li><a href="javascript:" onclick="put_content();">put content</a><br> <form name="content" onsubmit="javascript:put_content();return false;"> <input type=text name="tarea" value="text" style="background-color:#88AA88;width:290px;height:25px;"> </form> note: you can drag the table </td> </tr> </table> </div> </body> </HTML>