Wrox Programmer Forums
| Search | Today's Posts | Mark Forums Read
BOOK: Professional JavaScript for Web Developers ISBN: 978-0-7645-7908-0
This is the forum to discuss the Wrox book Professional JavaScript for Web Developers by Nicholas C. Zakas; ISBN: 9780764579080
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Professional JavaScript for Web Developers ISBN: 978-0-7645-7908-0 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
  #1 (permalink)  
Old May 16th, 2005, 12:05 AM
Registered User
 
Join Date: May 2005
Location: Raleigh, NC, USA.
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Default sorting tables enhancement

The final code for sorting tables (chapter 12) does not handle empty cells well. A couple minor changes make the code more forgiving.

I made a couple minor changes to the code you provided.
- the first change was to move the method of accessing the objects value into the convert function.
- the second change was to add checks to make sure that the object existed before the convert function accesses the value. In the case that the object is non-existant, the convert function returns an empty string.

The code snippets below can probably be cleaned up some, but I believe the basic functionality is now improved.

The only other enhancement that would be nice is the capability to sort a table entry that is hyperlinks ( a href's) by the link's text.
<a href="somelink">link text</a>



---- changed code below

   function convert(sCell, sDataType) {
      var sValue;

      if (sCell == null) return "";
      if (sCell.getAttribute("value")) sValue = sCell.getAttribute("value");
      if (sCell.firstChild == null) return "";
      if (sCell.firstChild.nodeValue) sValue = sCell.firstChild.nodeValue;
      if (sValue == "&nbsp;") return "";
      switch(sDataType) {
          case "int":
              return parseInt(sValue);
          case "float":
              return parseFloat(sValue);
          case "date":
              return new Date(Date.parse(sValue));
          default:
              return sValue.toString();

      }
  }

  function generateCompareTRs(iCol, sDataType) {

      return function compareTRs(oTR1, oTR2) {
                  var vValue1, vValue2;

                  vValue1 = convert(oTR1.cells[iCol], sDataType);
                  vValue2 = convert(oTR2.cells[iCol], sDataType);

                  if (vValue1 < vValue2) {
                      return -1;
                  } else if (vValue1 > vValue2) {
                      return 1;
                  } else {
                      return 0;
                  }
              };
  }


  #2 (permalink)  
Old May 16th, 2005, 08:56 AM
nzakas's Avatar
Wrox Author
 
Join Date: Dec 2004
Location: Peabody, MA, USA.
Posts: 217
Thanks: 0
Thanked 5 Times in 5 Posts
Default

Yes, the code in chapter 12 did make several assumptions about the format of the table, not the least of which was assuming that there wouldn't be any empty cells. Your code updates work well, if there's a second edition of the book, I'll try to incorporate your insights.

Thanks!

Nicholas C. Zakas
Author, Professional JavaScript for Web Developers (ISBN 0764579088)
http://www.nczonline.net/
  #3 (permalink)  
Old July 8th, 2006, 08:55 PM
Registered User
 
Join Date: Jul 2006
Location: Alpharetta, GA, .
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Default

:)Chapter 12 sorting tables examples doesn't handle nested <input> boxes. If you create editable tables using <input type="text"> you need to go deeper into the dom. Additionally, the current sort routine only sorts a column once, subsequent column selections only REVERSE the current display order. If you enable changes to a given column and click the column expecting a new sort you will find that sorting will occur according to the first sorted positions and not the new values.

Below are changes to the example code that allow changes to the displayed values via nested <input> tags and a new sort for every column selection , still preserving the ascending / descending toggle.

I added an additional function call to pull the value from any given column and row in the array. This allows for a quick test to determine if the column is currently in ascending or descending order
(most of the time, the exception being that an initial random ordering may produce an ascending or descending initial sort.).

The following code was tested only on IE6, but meets my needs for inclusion in autogenerated header/detail tables directly from a database using Cold Fusion or .Net2.0.





================ Modified Code =====================


<html>
    <head>
    <title>Table Sort Example</title>
        <script type="text/javascript">

            function convert(sValue, sDataType) {
                switch(sDataType) {
                    case "int":
                        return parseInt(sValue);
                    case "float":
                        return parseFloat(sValue);
                 case "number":
                        return parseFloat(sValue);
                     case "num":
                        return parseFloat(sValue);
                    case "date":
                        return new Date(Date.parse(sValue));
                    default:
                        return sValue.toString();

                }
            }

            function generateCompareTRs(iCol, sDataType) {

                return function compareTRs(oTR1, oTR2) {
                            var vValue1, vValue2;

                            if (oTR1.cells[iCol].getAttribute("value")) {
                                vValue1 = convert(oTR1.cells[iCol].getAttribute("value"),
                                              sDataType);
                                vValue2 = convert(oTR2.cells[iCol].getAttribute("value"),
                                              sDataType);
                            }
                            else if(oTR1.cells[iCol].firstChild.nodeValue) {
                                vValue1 = convert(oTR1.cells[iCol].firstChild.nodeValue,
                                              sDataType);
                                vValue2 = convert(oTR2.cells[iCol].firstChild.nodeValue,
                                              sDataType);
                            }
                            else {
                                vValue1 = convert(oTR1.cells[iCol].firstChild.getAttribute("value"),
                                              sDataType);
                                vValue2 = convert(oTR2.cells[iCol].firstChild.getAttribute("value"),
                                              sDataType);
                            }



                            if (vValue1 < vValue2) {
                                return -1;
                            } else if (vValue1 > vValue2) {
                                return 1;
                            } else {
                                return 0;
                            }
                        };
            }

            function sortTable(sTableID, iCol, sDataType) {
                var oTable = document.getElementById(sTableID);
                var oTBody = oTable.tBodies[0];
                var colDataRows = oTBody.rows;
                var aTRs = new Array;

                for (var i=0; i < colDataRows.length; i++) {
                    aTRs[i] = colDataRows[i];
                }

                //rVal = aTRs.cells[2].firstChild.getAttribute("value");
                //alert(rVal + " Datatype = " + sDataType);

                if (oTable.sortCol == iCol) {
                // We need to sort always and then set to the reverse order
                // that the column is in. So get the first value then sort so that
                // the new value does not equal the incoming first. this preserves the
                // toggle action

                    curVal = getValByColumn(aTRs, 0, iCol);

                    // Perform the sort and test for ordering
                     aTRs.sort(generateCompareTRs(iCol, sDataType));
                    if (getValByColumn(aTRs, 0, iCol) == curVal){
                        aTRs.reverse();}

                    }
                 else {
                    aTRs.sort(generateCompareTRs(iCol, sDataType));
                }


                var oFragment = document.createDocumentFragment();
                for (var i=0; i < aTRs.length; i++) {
                    oFragment.appendChild(aTRs[i]);
                }

                oTBody.appendChild(oFragment);
                oTable.sortCol = iCol;
            }

            function getValByColumn(aR, iRow, iCol)
            {
            var colVal = "";
                            if (aR[iRow].cells[iCol].getAttribute("value")) {
                                colVal = aR[iRow].cells[iCol].getAttribute("value");

                            }
                            else if(aR[iRow].cells[iCol].firstChild.nodeValue) {
                                colVal = aR[iRow].cells[iCol].firstChild.nodeValue;

                            }

                            else {
                                colVal = aR[iRow].cells[iCol].firstChild.getAttribute("value");

                            }


            return colVal;
            }

        </script>
    </head>
    <body>
        <p>Click on the table header to sort.</p>
        <table border="1" id="tblSort">
            <thead>
                <tr>
                    <th onClick="sortTable('tblSort', 0)" style="cursor:pointer">Type</th>
                    <th onClick="sortTable('tblSort', 1)" style="cursor:pointer">Filename</th> <th onClick="sortTable('tblSort', 2, 'int')" style="cursor:pointer">Seq Num</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td value="doc"><img src="images/wordicon.gif"/></td>
                    <td>My Resume.doc</td>
                    <td><input type="text" value="1"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
                <tr>
                    <td value="xls"><img src="images/excelicon.gif"/></td>
                    <td>Fall Budget.xls</td>
                    <td><input type="text" value="2"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
                <tr>
                    <td value="pdf"><img src="images/acrobaticon.gif"/></td>
                    <td>How to be a better programmer.pdf</td>
                    <td><input type="text" value="3"
                         onDblClick="javascript:alert(this.value);"></input></td>
                                    </tr>
                <tr>
                    <td value="doc"><img src="images/wordicon.gif"/></td>
                    <td>My Old Resume.doc</td>
                    <td><input type="text" value="4"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
                <tr>
                    <td value="txt"><img src="images/notepadicon.gif"/></td>
                    <td>Notes from Meeting.txt</td>
                    <td><input type="text" value="5"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
                <tr>
                    <td value="zip"><img src="images/zippedfoldericon.gif"/></td>
                    <td>Backups.zip</td>
                    <td><input type="text" value="6"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
                <tr>
                    <td value="xls"><img src="images/excelicon.gif"/></td>
                    <td>Spring Budget.xls</td>
                    <td><input type="text" value="7"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
                <tr>
                    <td value="doc"><img src="images/wordicon.gif"/></td>
                    <td>Job Description - Web Designer.doc</td>
                    <td><input type="text" value="8"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
                <tr>
                    <td value="pdf"><img src="images/acrobaticon.gif"/></td>
                    <td>Saved Web Page.pdf</td>
                    <td><input type="text" value="16"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
                <tr>
                    <td value="doc"><img src="images/wordicon.gif"/></td>
                    <td>Chapter 1.doc</td>
                    <td><input type="text" value="9"
                         onDblClick="javascript:alert(this.value);"></input></td>
                </tr>
            </tbody>
        </table>
    </body>
</html>








  #4 (permalink)  
Old July 9th, 2006, 09:24 AM
nzakas's Avatar
Wrox Author
 
Join Date: Dec 2004
Location: Peabody, MA, USA.
Posts: 217
Thanks: 0
Thanked 5 Times in 5 Posts
Default

You are correct, the first sorder is kept in the example in the book. That is because the example was based around a table with static values. For your case, using input text boxes, you are correct that the code won't serve your purposes.

As a note, when generating the table you can put whatever you want in the value attribute and the code should work appropriately.

Nicholas C. Zakas
Author, Professional JavaScript for Web Developers (ISBN 0764579088)
http://www.nczonline.net/
  #5 (permalink)  
Old August 6th, 2006, 05:15 PM
Registered User
 
Join Date: Aug 2006
Location: Bellingham, MA, USA.
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I can not get this to work on OSC with Safari

seem Safari does not like return function, any ideas

Thanks

  #6 (permalink)  
Old August 6th, 2006, 06:47 PM
nzakas's Avatar
Wrox Author
 
Join Date: Dec 2004
Location: Peabody, MA, USA.
Posts: 217
Thanks: 0
Thanked 5 Times in 5 Posts
Default

If you could explain the error you're getting, perhaps we can figure it out. What are you doing?

Nicholas C. Zakas
Author, Professional JavaScript for Web Developers (ISBN 0764579088)
http://www.nczonline.net/
  #7 (permalink)  
Old August 6th, 2006, 07:34 PM
Registered User
 
Join Date: Aug 2006
Location: Bellingham, MA, USA.
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

function generateCompareTRs(iCol, sDataType) {

    return function compareTRs(oTR1, oTR2) {
                var vValue1, vValue2;

                if (oTR1.cells[iCol].getAttribute("value")) {
                    vValue1 = convert(oTR1.cells[iCol].getAttribute("value"),
                                  sDataType);
                    vValue2 = convert(oTR2.cells[iCol].getAttribute("value"),
                                  sDataType);
                } else {
                    vValue1 = convert(oTR1.cells[iCol].firstChild.nodeValue,
                                  sDataType);
                    vValue2 = convert(oTR2.cells[iCol].firstChild.nodeValue,
                                  sDataType);
                }

                if (vValue1 < vValue2) {
                    return -1;
                } else if (vValue1 > vValue2) {
                    return 1;
                } else {
                    return 0;
                }
            };
}
I'm sorting tables, the code works correctly in OSX firefox but does not under Safari. Safari sees the "return function" as a syntax error and none of the javascript on that pages works, if I remove this function then the rest of my Javascript works as it should but of course the sort table does not. is there a way of writting this for safari.

Thanks

  #8 (permalink)  
Old August 8th, 2006, 07:39 PM
Registered User
 
Join Date: Aug 2006
Location: , , .
Posts: 4
Thanks: 0
Thanked 0 Times in 0 Posts
Send a message via AIM to albeik Send a message via MSN to albeik Send a message via Yahoo to albeik
Default

@Dean Holmes

just replace "return" with var result = ...
then at the end "return result" --- that should make Safari happy... :)

function generateCompareTRs(iCol, sDataType) {
    var result = function compareTRs(oTR1, oTR2) {
        ...
    };
    return result;
}

hope that helps.

  #9 (permalink)  
Old August 9th, 2006, 03:08 PM
Registered User
 
Join Date: Aug 2006
Location: Bellingham, MA, USA.
Posts: 3
Thanks: 0
Thanked 0 Times in 0 Posts
Default

HI Nicholas

Great thanks for that, it works just fine. Great book, looking forward for more like this from you

Thanks
Dean



Similar Threads
Thread Thread Starter Forum Replies Last Post
Opinion Polls enhancement void BOOK: ASP.NET 2.0 Website Programming Problem Design Solution ISBN: 978-0-7645-8464-0 2 July 12th, 2006 10:42 PM
Sorting Tables and Safari HomersGhost BOOK: Professional JavaScript for Web Developers ISBN: 978-0-7645-7908-0 4 March 18th, 2006 07:09 PM
Mysql Sorting results from multiple tables dcb22 SQL Language 8 October 25th, 2004 10:57 AM
Enhancement Request Ben Horne Forum and Wrox.com Feedback 4 March 30th, 2004 08:13 PM
Enhancement Request Imar Forum and Wrox.com Feedback 8 March 16th, 2004 01:43 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.