简体   繁体   中英

JavaScript code works on chrome, doesn't work on IE and firefox

I created this script for educational reasons in pure JS. It adds sorting to tables (when a header is clicked). I decided that it's quite useful and tried to use it in my project. It works fine on Google Chrome (I used this browser when I was creating the script), but doesn't on IE and Firefox. Can you help me?

alert("Remember to add LoadSetup function to window.onload event and to remove this alert.\nAlso remember that table you want to sort must have class 'sortable' and an unique id.\nThe table must be build properly using <thead> and <tbody> tags.")


function addLoadEvent(func) {
// Dobra funkcja która radzi sobie z dodawaniem nowych funkcji do zdażenia window.onload
    var oldonload = window.onload;
    if (typeof window.onload != 'function') window.onload = func;
    else {
        window.onload = function() {
            if (oldonload) oldonload();
            func();
        }
    }
}

window.onload = LoadSetup;

function LoadSetup()
{
    //find sortable tables and set sorting state to 0 (not sorted)  
    tables = document.getElementsByTagName("table");
    tablesStates = new Array(tables.length);

    for(var i=0;i<tables.length;i++){
        tableName = tables[i].getAttribute("id");
        if(hasClass(tables[i], "sortable") && tableName != null){
            tablesStates[tableName] = new Array();

            thead = tables[i].getElementsByTagName("thead")[0];
            header = thead.getElementsByTagName("tr")[0].getElementsByTagName("th");

            for(var j=0; j<header.length; j++){
                if(!hasClass(header[j], 'notsortable')){
                    tablesStates[tableName][header[j].innerHTML] = 0;
                    header[j].removeAttribute("onclick");
                    header[j].setAttribute("onclick", "sortTable('"+tableName+"', '"+header[j].innerHTML+"')");
                }
            }
        }
    }
}

function hasClass(ele, cls)
{
    return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}

String.prototype.capitalize = function() {
// fajna funkcja
    return this.charAt(0).toUpperCase() + this.slice(1);
}
String.prototype.capitalizeAll = function() {
// fajna funkcja
    result = '';
    for(var i=0; i< this.length;i++)
        result += this.charAt(i).toUpperCase();
    return result;
}

function prepareStringForCmp(s){
    en = ['a','c','e','l','n','o','s','z','z','A','C','E','L','N','O','S','Z','Z'];
    pl = ['ą','ć','ę','ł','ń','ó','ś','ź','ż','Ą','Ć','Ę','Ł','Ń','Ó','Ś','Ź','Ż'];

    for(var i=0;i<pl.length;i++){
        regex = new RegExp(pl[i],"g");
        s = s.replace(regex,en[i]);
    }
    return s.capitalizeAll();
}

function cmpStr(a, b){
    //a=prepareStringForCmp(a);
    //b=prepareStringForCmp(b);
    if(a == b)return 0;
    else if(a > b) return 1;
    else return -1;
}
function cmpStrRev(a, b){return cmpStr(b, a);}

function cmpNum(a, b){ return a - b;}
function cmpNumRev(a, b){return cmpNum(b, a);}

function cmp(a,b,type,asc)
{
// returns -1 if a < b ---- in ascending mode ( asc=true)
// returns 1 is a > b ---- in ascending mode ( asc=true)
// returns 0 if a == b

    if(type == "number"){
        if(asc == true) return cmpNum(a,b);
        else return cmpNumRev(a,b);
    }
    else if(type == "date"){
        if(asc == true) return 0;
        else return 0;
    }
    else{
        if(asc == true) return cmpStr(a,b);
        else return cmpStrRev(a,b);

    }
}

/////////////////////////////////////////////////////////////
// Bubble Sort

function bubbleSortTable(tab, col, type, asc) {
    for(var i=0; i < tab.length; i++){
        for(var j=0; j< tab.length-1; j++){
            if(cmp(tab[j].getElementsByTagName("td")[col].innerText, tab[j+1].getElementsByTagName("td")[col].innerText, type, asc) > 0)
            {
                buf = tab[j].innerHTML;
                tab[j].innerHTML = tab[j+1].innerHTML;
                tab[j+1].innerHTML = buf;
            }
        }
    }
}

/////////////////////////////////////////////////////////////
// Quick Sort

function partitionTable(l, r, A, col, type, asc)
{
    x = A[l].getElementsByTagName("td")[col].innerText;
    i = l-1;
    j = r+1;
    while(true){
        while(true){
            j = j-1;
            if(cmp(A[j].getElementsByTagName("td")[col].innerText, x, type, asc) <= 0) break;
        }
        while(true){
            i = i+1;
            if(cmp(A[i].getElementsByTagName("td")[col].innerText, x, type, asc) >= 0) break;
        }

        if(i<j){
            buf = A[i].innerHTML;
            A[i].innerHTML = A[j].innerHTML;
            A[j].innerHTML = buf;
        }
        else return j;
    }

}

function qsortTable(l, r, A, col, type, asc)
{
//qsort(tablica, 0, tablica.lenght -1);
    if(l<r){
        q = partitionTable(l, r, A, col, type, asc);
        qsortTable(l, q, A, col, type, asc);
        qsortTable(q+1, r, A, col, type, asc);
    }
}

/////////////////////////////////////////////////////////////

function sortTable(id, colName){
// sorts table
// returns true if sorting done; otherwise false
// works for strings and numbers


    if(tablesStates[id][colName] >= 0) asc = true;
    else asc = false;

    tab = document.getElementById(id);
    thead = tab.getElementsByTagName("thead")[0];
    header = thead.getElementsByTagName("tr")[0].getElementsByTagName("th");
    tbody = tab.getElementsByTagName("tbody")[0];
    rows = tbody.getElementsByTagName("tr");

    col = -1;
    for(var i=0; i < header.length; i++){
        if(header[i].innerHTML == colName){
            col = i;
            colType = header[i].getAttribute("class");      
            break;
        }
    }
    if(col == -1) return false;

    // demanded header found

    bubbleSortTable(rows, col, colType, asc);
    //qsortTable(0, rows.length-1,rows, col, colType, asc);
    if(tablesStates[id][colName] >= 0) tablesStates[id][colName] = -1;
    else tablesStates[id][colName] = 1;
}

And also a simple html for this:

<!DOCTYPE html PUBLIC 
"-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
xml:lang="pl" lang="pl">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="sortTable.js"></script>
    <link rel="stylesheet" type="text/css" href="x.css" />
</head>
<body>
<div id="content_box">

<table class="sortable"  id="tabela1">
<thead>
    <tr><th>name</th><th class="number">age</th><th>city</th></tr>
</thead>
<tbody>
    <tr> <td>Jan</td> <td>21</td> <td>Gdańsk</td> </tr>
    <tr> <td>Andrzej</td> <td>17</td> <td>Warszawa</td> </tr>
    <tr> <td>Paweł</td> <td>112</td> <td>toruń</td> </tr>
    <tr> <td>Mateusz</td> <td>43</td> <td>Łomża</td> </tr>
        <tr> <td>ADAM</td> <td>21</td> <td>Gdańsk</td> </tr>
    <tr> <td>ŻANETA</td> <td>17</td> <td>Warszawa</td> </tr>
    <tr> <td>Paweł</td> <td>112</td> <td>toruń</td> </tr>
    <tr> <td>LEON</td> <td>43</td> <td>Łomża</td> </tr>
        <tr> <td>Jan</td> <td>21</td> <td>Gdańsk</td> </tr>
    <tr> <td>Andrzej</td> <td>17</td> <td>Warszawa</td> </tr>
    <tr> <td>FRYDERYK</td> <td>112</td> <td>toruń</td> </tr>
    <tr> <td>Mateusz</td> <td>43</td> <td>Łomża</td> </tr>
        <tr> <td>Jan</td> <td>21</td> <td>Gdańsk</td> </tr>
    <tr> <td>BALBINA</td> <td>17</td> <td>Warszawa</td> </tr>
    <tr> <td>ADAM</td> <td>112</td> <td>toruń</td> </tr>
    <tr> <td>TERESA</td> <td>43</td> <td>Łomża</td> </tr>
</tbody>
</table>
</div>
</body>
</html>

More detailed description:

LoadSetup - works (and adds sorting functionality) When header is clicked it should do the sorting and it does on Chrome. Than it goes like this: sortTable >> bubbleSortTable >> cmp in cmp(a,b,type,asc) a and b are 'undefined' in Firefox and IE and than the script somewhere breaks and nothing gets sorted.

I'm not going through all your code, especially since your description is rather vague: "doesn't work" is obvious - you wouldn't ask here if everything works, so being a little more specific and trying to narrow the problem down (thus posting less code) is probably a good idea. But from the three second glance that I gave I see you're setting event handlers with setAttribute . Not a good idea (for example, see this post ). That doesn't work in some versions of IE (again, versions are something you didn't specify).

To add one more thing: even doing elem.onclick = ... isn't really recommended. It's the old HTML 4.0 method. Using the DOM Event Model is recommended, ie ( addEventListener etc.). But then there are endless cross-browser issues, which is why there are js libraries. As such, I suggest porting your code to jQuery or some other such library to make things truly portable.

It's a good idea because otherwise you'll just end up reinventing the wheel, and probably not as well as years of experienced developers have already done. Moreover, you will probably add to this code and it will grow. js libraries used properly will help the scalability of the code.

No, this isn't an answer to your question. And if you're looking for a quick fix to the issue, this isn't it. But I strongly feel that this advice, while harder (much harder) to implement in the short term, is your best bet if you want that code to be truly usable and maintainable.

One problem is that you are using the innerText property which isn't supported in Firefox. See 'innerText' works in IE, but not in Firefox for (loads) of details.

Edit: I tested your code in Firefox and the only change I made was from innerText to textContent and it worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM