Witam,
Niedawno zacząłem swoją przygodę a JavaScript i napotkałem na pewien problem, chcąc dołożyć funkcjonalność do TreeView, która zapewnia zaznaczenie/odznaczenie gałęzi potomnych po kliknięciu na gałąź główna. W momencie przerobienia drzewa na doczytywanie gałęzi (nie jestem pewien czy w tym tkwi problem). Przestał mi działać skrypt „Asp.Net 2.0 Treeview Checkbox Check/Uncheck All script”, http://pushpontech.blogspot.com/2007/06/treeview-checkuncheck-all-script.html.
Więc zostałem zmuszony do napisania czegoś własnego, z czym chciałbym się podzielić bo zajęło mi to trochę czasu. Wszyscy którzy też mają problem z kodem podanym w linku, a ich znajomość JavaScript jest nie wielka, mogą skorzystać z mojego gotowca. Natomiast wszyscy, którzy z JavaScript mają więcej odczynienia i chcieliby wnieść jakieś poprawki i uwagi, to bardzo proszę, może powstanie z tego coś madrego :).
Dodałem do kodu parę komentarzy, dla tych którzy reprezentują jak ja słaby poziom, a chcieliby się dowiedzieć o co w kodzie chodzi.

 


function OnTreeNodeChecked()
{
    /// <summary>Funkcja zaznzcza i odzncza chenkBox-y na drzewie</summary>
    /// <summary>Po zaznaczeniu wszystkich potomkow automatycznie zostaje zaznaczony przodek</summary>
    /// <summary>Po odznaczeniu chociaz jednego potomka odznacza sie przodek</summary>

    // pobieram zdarzenie z okna
    var obj = window.event.srcElement;
    // stan checkBox-a, (zaznaczony = true, odznaczony = false) 
    var checkedState;
    // sprawdzam czy zdarzenie dotyczy kontrolki (input) i czy jest to chekcBox  
    if (obj.tagName == "INPUT" && obj.type == "checkbox")
    {
        // zaznaczony checkBox
        var treeNode = obj;
        checkedState = treeNode.checked;
        // szukam tagu o nazwie table
        do
        {
            obj = obj.parentElement;
        } while (obj.tagName != "TABLE")
        
        // funkcja zaznacza/odznacza wszystkich potomkow
        CheckUncheckAllChildrens(obj, checkedState);

        // finkcja zaznacza odznacza przodkow 
        CheckUncheckParents(obj, checkedState);
    }
}

function CheckUncheckAllChildrens(obj, checkedState)
{
    /// <summary>Funkcja zaznacza i odznacza wszystkich potomkow</summary>
    /// <param name="obj" type="var">aktualn obj.tagName = "TABLE"</param>
    /// <param name="checkedState" type="bool">stan checkBox-a</param>

    // Poziom drzewa na ktorym znajduje sie zaznaczony checkBox 
    var parentTreeLevel = obj.rows[0].cells.length;
    var parentTreeNode = obj.rows[0].cells[0];
    // tabela z wszystkimi elementami drzewa
    var tables = obj.parentElement.getElementsByTagName("TABLE");
    // sprawdza czy galaz zostala odnaleziona
    var treeNodeFound = false;
    // liczba elementow drzewa
    var numTables = tables.length;
    if (numTables > 0)
    {
        for (i = 0; i < numTables; i++)
        {
            // szukam zaznaczonego elementu
            if (tables[i] == obj)
            {
                treeNodeFound = true;
                // zmieniam index zeby dostac pierwsze dziecko
                i++;
                // sprawdzam czy po zmianie indeksu elementy drzewa sie nie koncza
                if (i == numTables)
                {
                    return;
                }
            }
            // obiekt zaznaczony odnaleziony
            if (treeNodeFound == true)
            {
                var childTreeLevel = tables[i].rows[0].cells.length;
                // sprawdzam poziom kolejnych elementow drzewa
                if (childTreeLevel > parentTreeLevel)
                {
                    var cell = tables[i].rows[0].cells[childTreeLevel - 1];
                    var inputs = cell.getElementsByTagName("INPUT");
                    // zaznaczam/odznaczam
                    inputs[0].checked = checkedState;
                }
                else
                {
                    return;
                }
            }
        }
    }
}

function CheckUncheckParents(obj, checkedState)
{
    /// <summary>Funkcja zaznacza i odznacza przodkow w zaleznosci od zaznaczonych potomkow</summary>
    /// <param name="obj" type="var">obj.tagName = "TABLE"</param>
    /// <param name="checkedState" type="bool">stan checkBox-a</param>

    // szukam rodzica
    var searchParent = true;
    do
    {
        // Pobieram obiekt rodzica
        var obj = FindParent(obj, checkedState)
        if (obj != null)
        {
            // jezeli zaznaczam wszystkie dzieci lub odznaczam chociaz jedno
            if (IsChangeStatusParent(obj, checkedState) || !checkedState)
            {
                var childTreeLevel = obj.rows[0].cells.length;
                var cell = obj.rows[0].cells[childTreeLevel - 1];
                var inputs = cell.getElementsByTagName("INPUT");
                // zaznaczam/odznaczam
                inputs[0].checked = checkedState;
            }
            else
            {
                searchParent = false;
            }
        }
        else
            searchParent = false;
    } while (searchParent)
}

function IsChangeStatusParent(obj, checkedState)
{
    /// <summary>Funkcja sprawdza czy trzeba zmienic status przodkow</summary>
    /// <param name="obj" type="var">obj.tagName = "TABLE"</param>
    /// <param name="checkedState" type="bool">stan checkBox-a</param>
    /// <returns type="Boolen">zmienic/nie zmieniac</returns>

    var parentTreeLevel = obj.rows[0].cells.length;
    var parentTreeNode = obj.rows[0].cells[0];
    var tables = obj.parentElement.getElementsByTagName("TABLE");
    var treeNodeFound = false;
    var numTables = tables.length;
    // liczba zaznaczonych - nie zaznaczonych potomkow 
    var numCheckBox = 0;
    // ilosc potomkow, danego przodka
    var numChecedkUnChecked = 0; 
    if (numTables > 0)
    {
        for (i = 0; i < numTables; i++)
        {
            if (tables[i] == obj)
            {
                treeNodeFound = true;
                i++;
                if (i == numTables)
                {
                    return false;
                }
            }
            if (treeNodeFound == true)
            {
                var childTreeLevel = tables[i].rows[0].cells.length;
                if (childTreeLevel > parentTreeLevel)
                {
                    var cell = tables[i].rows[0].cells[childTreeLevel - 1];
                    var inputs = cell.getElementsByTagName("INPUT");
                    numCheckBox++;
                    if (inputs[0].checked == true)
                        numChecedkUnChecked++;
                    else
                        numChecedkUnChecked--;
                }
                else
                {
                    // jezeli liczba potomkow wieksza od 0 i liczba zaznaczonych rowna jest wszystkim
                    if (numCheckBox > 0 && numChecedkUnChecked == numCheckBox)
                        return true;
                    else
                        return false;
                }
            }
        }
        // jezeli liczba potomkow wieksza od 0 i liczba zaznaczonych rowna jest wszystkim
        if (numCheckBox > 0 && numChecedkUnChecked == numCheckBox)
            return true;
        else
            return false;
    }
}

function FindParent(obj, checkedState)
{
    /// <summary>Funkcja wyszukuje przodka</summary>
    /// <param name="obj" type="var">obj.tagName = "TABLE"</param>
    /// <param name="checkedState" type="bool">stan checkBox-a</param>
    /// <returns type="var">przodek - obj.tagName = "TABLE"</returns>

    var parentTreeLevel = obj.rows[0].cells.length;
    var parentTreeNode = obj.rows[0].cells[0];
    var tables = obj.parentElement.getElementsByTagName("TABLE");
    var treeNodeFound = false;
    var numCheckedTables = 0;
    var numTables = tables.length;
    if (numTables > 0)
    {
        // zaczynam przeszukiwanie od lisci do korzenia
        for (i = numTables - 1; i != -1; i--)
        {
            if (tables[i] == obj)
            {
                treeNodeFound = true;
                // zmieniam indeks i ustawiam przodka
                i--;
                if (i == -1)
                {
                    return null;
                }
            }
            if (treeNodeFound == true)
            {
                var childTreeLevel = tables[i].rows[0].cells.length;
                if (childTreeLevel < parentTreeLevel)
                {
                    return tables[i];                    
                }
            }
        }
    }
}