Ajax-os tennivalók

TODO lista építése a PHP és a JavaScript erejével.

A minap találkoztam össze a twofifty.org oldallal, ahol az ember trendi Ajax-os rendszer segítségével kihuzogathatja az IMDb 250-es listából azokat a filmeket, amiket látott. Meg mellesleg kommenteket is lehet hozzá fűzni, meg vannak statisztikák is nem, kor szerinti bontásban. Amellett, hogy meglepően kevés filmet láttam ebből a listából, eszembe jutott, hogy mekkora jó lenne már egy olyan kis alkalmazás, ahol az ember a tennivalóit tudná hasonló módon kihuzogatni. Gyorsan össze is dobtam egy ilyen kis oldalacskát a Prototype és a PDO segítségével.

Először talán kezdjük az adatbázis táblával, ami roppant egyszerű lesz, mivel nem akartam a dolgot túlbonyolítani, csak egyszerűen kedvet éreztem egy ilyen kis rendszer megvalósításához:

CREATE TABLE `todo` (
    `ID` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `description` TEXT NOT NULL,
    `status` ENUM('0', '1') NOT NULL DEFAULT '0'
) ENGINE = MYISAM;

Persze adatok se ártanak bele:

INSERT INTO `todo` (`ID`, `description`, `status`) VALUES
    (NULL, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit.', '0'),
    (NULL, 'Suspendisse luctus, sem at pretium interdum, dolor velit pellentesque turpis, eu volutpat velit neque vel nulla.', '0'),
    (NULL, 'Praesent ligula dolor, vehicula sed, facilisis ac, gravida et, elit. Morbi id urna.', '0');

Aztán a HTML-PHP vonallal folytattam a munkát, a következő pár soros kód legenerálja nekünk a listát (aki esetleg nem mozog annyira otthonosan a PDO világában, annak tudom ajánlani egy régebbi bevezető jellegű írásomat):

print '<div id="error">&nbsp;</div>';
print '<ul id="todo">';
$db = new PDO('mysql:host=localhost;dbname=database', 'user', 'password');
foreach ($db->query("SELECT * FROM `todo`") as $row) {
    print '<li id="task-'.$row['ID'].'"'.($row['status'] === '1' ? ' class="done"' : ' class="not-done"').'>'.htmlspecialchars($row['description']).'</li>';
}
$db = NULL;
print '</ul>';

Ez után már tényleg nincs is más hátra, mint a Prototype segítségével megírni a szükséges JavaScript kódot. Először is az oldal betöltődése után az összes listatagnak elkezdjük figyelni a click eseményét:

Event.observe(window, 'load', function(e) {
    var todos = $('todo').getElementsByTagName('li');
    
    for (var i = 0; i < todos.length; ++i) {
        Event.observe(todos[i], 'click', listElementClick);
    }
});

Miután ez megvan, már nincs más dolgunk, mint a listElementClick nevezetű függvény, ami annyit tesz, hogy az adott ID-jű feladat státuszát az adatbázisban megváltoztatja, majd siker esetén a listaelem stílusát az új státuszhoz igazítja (ha 'done' volt akkor 'not-done' lesz, ha 'not-done' volt, akkor pedig 'done').

function listElementClick(e) {
    $('error').innerHTML = '&nbsp;';
    
    var t;
    if (e.srcElement) t = e.srcElement;
    else t = e.target;
    
    var tmp = t.id.split('-');
    var ID = tmp[1];
    var status = 0;
    
    if (t.className == 'not-done') status = 1;
    else status = 0;
    
    /* ... */
}

Nos, ezzel így még nem sok mindent csináltunk, csak előkészítettük a terepet a /* ... */ helyére kerülő Ajax kérésnek, ami pedig a következő lesz:

var req = new Ajax.Request(
    'process.php',
    {
        method     : 'post',
        parameters : 'ID='+ID+'&status='+status,
        onComplete : function(req) {
            var response_status = req.responseText.split(',');
            
            if (response_status[0] == '1') {
                $('task-'+response_status[1]).className = response_status[2];
            }
            else {
                $('error').innerHTML = 'Nem sikerült módosítani a tennivaló státuszát!';
            }
        }
    }
);

Már csak a process.php tartalma van hátra, ami tulajdonképpen elvégzi a szükséges adatbázis műveleteket és visszatér egy [módosítás státusza],[feladat ID-je],[új css osztály neve] formátumú listával.

header('Content-Type: text/plain');

if (isset($_POST['ID']) && isset($_POST['status'])) {
    try {
        $db = new PDO('mysql:host=localhost;dbname=database', 'user', 'password');
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        
        $db->query("UPDATE `todo` SET `status`='".(int)$_POST['status']."' WHERE `ID`='".(int)$_POST['ID']."'");
        
        echo '1,'.$_POST['ID'].','.($_POST['status'] === '1' ? 'done' : 'not-done');
    }
    catch (PDOException $e) {
        echo '0';
    }
}
else {
    echo '0';
}

És ha minden kis darabkát sikerült a megfelelő helyre illesztenünk, akkor az oldalt betöltve kattintgathatjuk is a feladatokat, ami nagyszerűen látszik is, ha megfelelő CSS-t is csatolunk a dokumentumunkhoz. Valami ilyesmi egyszerű meg is teszi:

#todo li {
    cursor: pointer;
}
.done {
    color: gray;
    text-decoration: line-through;
}
.not-done {
    color: black;
    text-decoration: none;
}
#error {
    font-size: 14px;
    color: red;
    font-weight: bold;
}

Ezzel meg is volnánk. Mint azt az elején is említettem, nem bonyolítottam túl a dolgokat semmiféle extrával. A működő példa megtekinthető itt.

Hozzáfűznél valamit?

Dobj egy emailt a blog kukac deadlime pont hu címre.

Feliratkoznál?

Az RSS feed-et ajánljuk, ha kedveled a régi jó dolgokat.