Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Netscape DOM and event handling

Posted on 2002-03-26
13
Medium Priority
?
283 Views
Last Modified: 2013-11-19
I tried this quoestion in the browsers section, but had no luck there, so I try here with the javascript gurus instead :)

I have a problem with events in netscape (NN6.2), when adding and removing nodes in the DOM on a page.

I have made a little sample, that illustrates my problem.
I'm trying to sort the contents of a table in a webpage using the DOM to swap the TR-node.
The sort is working fine, but after having sorted the table, i loose all the eventhandlers that are
associated with the elements/nodes and their children.

In my sample the doSelect() is not called after the sort, but it works fine before the sort.

The sample works fine in IE...

I do not want other solutions on how to sort the contents of the table, as I can find that myself.

The real question is : How do I get NN62 to handle the events after changing the DOM ?

sample start
<!--
<html>
<head>
<title>..::Table Sort::..</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
// global vars
var g_iSortColumn;
var g_iLastSortColumn =-1;
var g_iSortDirection  = 1;

/////////////////////////////////////////////////////////////////////////
//      function sortTable()
//
// function to sort a tab?e in a HTML page
// Sorts the table rows in the table with id as specified in
// strTableId by the column 'iCol'.
// The placement of rows, that does not have at least 'iCol' columns,
// is not specified.
//
// Only 'TR' rows that are inside the first 'TBODY' tag will be sorted.
// Only 'TD' cells are compared, so 'TH' cells first in a table are
// not moved during sort.
//
// HTML for table must be well-formed.
//
// Think twice when using ROWSPAN & COLSPAN, as iCol is used to index
// columns on each row.
//
//     PARAMETERS
//       iCol          : Column index to sort table by.
//       strTableId     : Id of table to sort.
//       iHeaders     : Number of header lines to ignore from sort.
function sortTable(iCol, strTableId, iHeaders) {
     var tbl     = document.getElementById(strTableId);
     var tblBody = tbl.getElementsByTagName("tbody").item(0);
     var tblRows = tblBody.getElementsByTagName("tr");
     
     var arr = new Array( tblRows.length-iHeaders );
     
     // create array of rows so we can sort
     for ( i=iHeaders; i<tblRows.length; i++) {
          arr[i-iHeaders] = tblRows[i].cloneNode(true);
     }
     
     // set column that sort is based on
     g_iSortColumn = iCol;
     
     // find the sort direction
     if (g_iLastSortColumn==iCol)
          g_iSortDirection *= -1;
     else
          g_iSortDirection = 1;
     g_iLastSortColumn=iCol;
     
     // peform the sort
     arr.sort(sortCompare);
     
     // write sorted data from array to table
     for ( i=iHeaders; i < tblRows.length; i++) {
          tblBody.replaceChild( arr[i-iHeaders].cloneNode(true), tblRows[i] );
     }
}

/////////////////////////////////////////////////////////////////////////
// function sortCompare
// internal function used by sortTable function
function sortCompare( val1, val2 ) {
     var cells1= val1.getElementsByTagName("td");
     var cells2= val2.getElementsByTagName("td");
     
     if ( !cells1 || !cells2 ||
          g_iSortColumn < 0 ||
           cells1.length <= g_iSortColumn ||
           cells2.length <= g_iSortColumn  )
     {
          return 0;
     }
     if ( cells1[g_iSortColumn].childNodes[0].nodeValue < cells2[g_iSortColumn].childNodes[0].nodeValue
)
          return -1*g_iSortDirection;
         
     if ( cells1[g_iSortColumn].childNodes[0].nodeValue > cells2[g_iSortColumn].childNodes[0].nodeValue
)
          return g_iSortDirection;
     
     return 0;
}
</script>
<script type="text/javascript">
     function doselect(obj) {
          alert("selection:"+obj.id);
     }
</script>
</style>
</head>

<body bgcolor="#FFFFFF" text="#000000">
<h3>Demonstration of tablesort</h3>
<table border="1" id="theTable">
 <tr>
   <th>
     <input type="button" name="btnSort1" value="Sort" onClick="sortTable(0, 'theTable', 1)">
   </th>
   <th>
     <input type="button" name="btnSort2" value="Sort" onClick="sortTable(1, 'theTable', 1)">
   </th>
 </tr>
 <tr  id="tr1" onclick="doselect(this)">
   <td>a</td>
   <td>13</td>
 </tr>
 <tr  id="tr2" onclick="doselect(this)">
   <td>b</td>
     <td>12</td>
 </tr>
 <tr  id="tr3" onclick="doselect(this)">
   <td>ca</td>
   <td>11</td>
 </tr>

</table>
</body>
</html>

-->
sample end
0
Comment
Question by:klausen
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 2
  • +1
13 Comments
 
LVL 23

Expert Comment

by:b1xml2
ID: 6896065
Amended Script
==============
<html>
<head>
<title>..::Table Sort::..</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
// global vars
var g_iSortColumn;
var g_iLastSortColumn =-1;
var g_iSortDirection  = 1;

/////////////////////////////////////////////////////////////////////////
//      function sortTable()
//
// function to sort a tab?e in a HTML page
// Sorts the table rows in the table with id as specified in
// strTableId by the column 'iCol'.
// The placement of rows, that does not have at least 'iCol' columns,
// is not specified.
//
// Only 'TR' rows that are inside the first 'TBODY' tag will be sorted.
// Only 'TD' cells are compared, so 'TH' cells first in a table are
// not moved during sort.
//
// HTML for table must be well-formed.
//
// Think twice when using ROWSPAN & COLSPAN, as iCol is used to index
// columns on each row.
//
//     PARAMETERS
//       iCol          : Column index to sort table by.
//       strTableId     : Id of table to sort.
//       iHeaders     : Number of header lines to ignore from sort.
function sortTable(iCol, strTableId, iHeaders) {
    var tbl     = document.getElementById(strTableId);
    var tblBody = tbl.getElementsByTagName("tbody").item(0);
    var tblRows = tblBody.getElementsByTagName("tr");
   
    var arr = new Array( tblRows.length-iHeaders );
   
    // create array of rows so we can sort
    for ( i=iHeaders; i<tblRows.length; i++) {
         arr[i-iHeaders] = tblRows[i].cloneNode(true);
    }
   
    // set column that sort is based on
    g_iSortColumn = iCol;
   
    // find the sort direction
    if (g_iLastSortColumn==iCol)
         g_iSortDirection *= -1;
    else
         g_iSortDirection = 1;
    g_iLastSortColumn=iCol;
   
    // peform the sort
    arr.sort(sortCompare);
   
    // write sorted data from array to table
    for ( i=iHeaders; i < tblRows.length; i++) {
         tblBody.replaceChild( arr[i-iHeaders].cloneNode(true), tblRows[i] );
    }
    //for NS 6.x
    if (document.getElementById && ! document.all) {
                  var oNodeList = tblBody.getElementsByTagName("tr");
                  var szId;
                  for (var i=0;i<oNodeList.length;i++) {
                        szId = oNodeList.item(i).id;
                        if (szId.indexOf("tr") != -1) oNodeList.item(i).onclick = doselect;
                  }
    }
   
}

/////////////////////////////////////////////////////////////////////////
// function sortCompare
// internal function used by sortTable function
function sortCompare( val1, val2 ) {
    var cells1= val1.getElementsByTagName("td");
    var cells2= val2.getElementsByTagName("td");
   
    if ( !cells1 || !cells2 ||
         g_iSortColumn < 0 ||
          cells1.length <= g_iSortColumn ||
          cells2.length <= g_iSortColumn  )
    {
         return 0;
    }
    if ( cells1[g_iSortColumn].childNodes[0].nodeValue < cells2[g_iSortColumn].childNodes[0].nodeValue

)
         return -1*g_iSortDirection;
         
    if ( cells1[g_iSortColumn].childNodes[0].nodeValue > cells2[g_iSortColumn].childNodes[0].nodeValue

)
         return g_iSortDirection;
   
    return 0;
}
</script>
<script type="text/javascript">
    function doselect(obj) {
                  if ("string" == typeof(this.tagName) && this.tagName == "TR") obj = this;
                  alert("selection:"+obj.id);
    }
</script>
</style>
</head>

<body bgcolor="#FFFFFF" text="#000000">
<h3>Demonstration of tablesort</h3>
<table border="1" id="theTable">
<tr>
  <th>
    <input type="button" name="btnSort1" value="Sort" onClick="sortTable(0, 'theTable', 1)">
  </th>
  <th>
    <input type="button" name="btnSort2" value="Sort" onClick="sortTable(1, 'theTable', 1)">
  </th>
</tr>
<tr  id="tr1" onclick="doselect(this)">
  <td>a</td>
  <td>13</td>
</tr>
<tr  id="tr2" onclick="doselect(this)">
  <td>b</td>
    <td>12</td>
</tr>
<tr  id="tr3" onclick="doselect(this)">
  <td>ca</td>
  <td>11</td>
</tr>

</table>
</body>
</html>

Notes
=====
1. You may be surprised by the results shown in NS <GRIN>
0
 

Author Comment

by:klausen
ID: 6896316
hehe - yes this works fine ! (thanks b1xml2)
But does that mean, that I have to check all childs of my <TR> nodes (recursive) to check for other event too, if I want my sortTable() to work on other tables as well.

f.ex. is there any 'onmouseover' or 'onclick' eventhandlers on any of the <TD> elements or maybe events for another element inside one of the <TD> elements. If there is, then I need to check all childs for all possible eventhandlers which is a shame when moving elements in the DOM (changing the page) is so easy.

In think that this makes, managing the DOM in netscape, less usefull than it needs to be. Can this really be right ?
0
 
LVL 23

Accepted Solution

by:
b1xml2 earned 1200 total points
ID: 6898022
klausen, it would appear that the cloneNode() method does not properly clone the events, in NS 6. Either this is an oversight on part the developers, (raise a Bugzilla Report with them if that is the case), or MSIE has implemented extensions to the W3C (which is more than likely).

>>
But does that mean, that I have to check all childs of my <TR> nodes (recursive) to check for other event too, if I want my sortTable() to work on other tables as well.
<<

Unfortunately, yes =(

>>
In think that this makes, managing the DOM in netscape, less usefull than it needs to be. Can this really
be right ?
<<

Not necessarily. If you assign functions to events thru script, rather than thru HTML, you'd be alright. It would appear that you have stumbled on a great weakness of the DOM Implementation under 6.2.


0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:klausen
ID: 6898698
well - it seems like there is a problem with the DOM :(

It seems that transforming XML to HMTL using XSLT also means the event are not generated - but i will ask about this in another question.

Thanks for your answer and time on this question.
Even though i'm not happy about the result - you shall have the point that i promised for an answer.

thanks...
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6898733
welcome =)
0
 
LVL 12

Expert Comment

by:ahosang
ID: 6900976
Or just don't use cloneNode() function when building array arr. Try:

arr[i-iHeaders] = tblRows[i];

and:

for ( i=iHeaders; i < tblRows.length; i++) {
         tblBody.replaceChild( arr[i-iHeaders], tblRows[i] );
    }

I used a similar sortable table once, but with innerHTML instead of replaceChild and it worked in NS6, but not in IE!

The trials and tribulations of catering to these browsers!!
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6901013
ahosang, the problem is not with the cloneNode() method, the problem is with the propagation of the events which do not work with NS 6.x

There's nothing wrong with klausen's code. It is rather elegant.
0
 
LVL 12

Expert Comment

by:ahosang
ID: 6901962
Didn't say the code was bad. My last sentence shows exactly what my point is :-)
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6901995
rofl, can we line all the developers of these browsers and send them off to siberia *Grin*
0
 

Author Comment

by:klausen
ID: 6912238
Thought that I had already accepted your answer - but I must have forgot to press some button :)

Again - Thanks for answering, nice to have 'all-knowing' allies on this site...
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 6912244
klausen, check my responses in the Browser section on Netscape, XML Transforms and XHTML. Thanx
0
 

Expert Comment

by:EasyDesigns
ID: 7374523
This script works great, but I have one complaint and that is that it does not address sorting of numeric values as appropriate (i.e. 200 comes before 50 because 2 is less than 5). Consider adding

  if (isNumber(cells1[g_iSortColumn].childNodes[0].nodeValue) && isNumber(cells2[g_iSortColumn].childNodes[0].nodeValue)) {
     diff =  cells1[g_iSortColumn].childNodes[0].nodeValue - cells2[g_iSortColumn].childNodes[0].nodeValue;
     if (diff > 0) return g_iSortDirection;
     if (diff < 0) return -1*g_iSortDirection;
     return 0;
  }

at the beginning of the sortCompare() function to add in sort functionality for numeric values.

isNumber() is a simple evaluation of whether or not the value passed to it is a number of any sort. email me if you need/want the script.
0
 

Author Comment

by:klausen
ID: 7377543
Sounds great that you can use this. I have already created different kinds of sort functions (which is why if made it easy to change the sort function).
I have sortCompare(), sortCompareLocale(), sortCompareNumericLocale() fumctions to use with this script.
instead of isNumeric() is just use parseFloat() so that any text that begins with numbers, are sorted based on the numrric value as you suggest.
I did it like this
    try {
        var f1 = parseFloat(cells1[g_iSortColumn].childNodes[0].nodeValue);
        var f2 = parseFloat(cells2[g_iSortColumn].childNodes[0].nodeValue);
       
       
        if ( !isNaN(f1) && !isNaN(f2) ) {
            var result = (f1 - f2)*g_iSortDirection;
            if ( result != 0 )
                return result;
        }
    } catch ( E ) { }

I have also solved my original problem, by avoiding the use of cloneNode() which is causing the problem with the lost event handlers.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will receive an overview of the basics of CSS showing inline styles. In the head tags set up your style tags: (CODE) Reference the nav tag and set your properties.: (CODE) Set the reference for the UL element and styles for it to ensu…

688 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question