General Technique for Dynamic Navigation

#1

Hello!

I’ve been doing C and Java for many years but recently I have become more serious about web development and I’m curious about general techniques with respect to security, extensibility and performance.

Specifically, I’m currently using the following strategy for navigation using AJAX:

<html>
<head>
function xhr(el, sel) {

    // install responseText into selected element and register click

    var fe = closest(el, 'form');

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var es = closest(fe, sel);
            var ep = es.parentNode;
            es.insertAdjacentHTML('beforebegin', xhr.responseText);
            ep.removeChild(es);
            regcl(ep);
        }   
    };  

    fe.querySelector('input[name=cmd]').value = el.cmd;

    xhr.open("POST", "/myapp", true);
    xhr.send(new FormData(fe)); 
}
function cmdhdlr(el) {

    // application specific JavaScript goes here

    if (el.cmd == 'foo') {
        xhr(el, 'foo_here');
    }   
}
function regcl(el) {

    // register click for all elements with class beginning with 'cl_'

    var nlist = el.querySelectorAll('[class^=cl_]');
    var ni; 
    for (ni in nlist) {
        var n = nlist[ni];
        if (n.className) {
            var mat = n.className.match(/cl_([_a-z0-9]+)/);
            if (mat) {
                n.cmd = mat[1];
                n.addEventListener('click', cmdhdlr);
            }   
        }   
    }   
}
window.onload = function() {
    regcl(document);
}
</head>
<body>
<form>
<input type='hidden' name='cmd'>

<div class='foo_here'>
<input type='text' name='bar'>
<a class='cl_foo' id='#'>submit</a>
</div>

</form>
</body>
</html>

When the user clicks ‘submit’ (or any link that has a class that begins with ‘cl_’) cmdhdlr() is invoked which submits the form, installs the responseText into the dom indicated by the selector and calls regcl() on that new fragment to register any links in it. The idea is that since XHR reponses cannot contain scripts, regcl() will just look for any nodes with a class that begins with ‘cl_’ and register those for click events. This is somewhat simplified of course but you get the idea.

Is this a typcical technique? Are there any security issues here? If some can inject content into the XHR reponse they will only be able to call code that is pre-defined in cmdhdlr() so it doesn’t seem like a problem to me.

Are there any holes in this?

#2
  1. JS Code should be in tag [script]. Otherwise it will be shown just as plain text.

  2. Better to use external JS-script, than inline script.

#3

Hi @ioplex, the typical technique would be not to send any markup in the AJAX response at all, but just the data (most commonly as JSON) and then modify the DOM accordingly on the client side; you can then add event listeners directly while creating new elements. There’s actually a current discussion on this topic here you might check out.

BTW also note that the selector [class^=cl_] will only match elements where the first class in the list starts with cl_ – elements with say class="foo cl_bar" will not be found.

#4

I am not sure but there is probably a better way to do it than using readyState and status in onreadystatechange. I would look for a more appropriate method than onreadystatechange.