Crear elementos html dinámicos desde JavaScript

Crear elementos html dinámicos desde JavaScript y aderirle eventos.

HTML

<form action="/" method="post">
        <div>
            <label for="titulo">T&iacute;tulo:</label>
            <input type="text" name="titulo" id="titulo" />
        </div>
        <div>
            <label for="descripcion">Descripci&oacute;n:</label>
            <textarea id="descripcion"></textarea>
        </div>
        <div>
            <label for="tipo">Tipo:</label>
            <select id="tipo">
                <option value="1">Tipo 1</option>
                <option value="2">Tipo 2</option>
                <option value="3">Tipo 3</option>
            </select>
        </div>
        <div>
            <button type="button" id="agregar">Agregar</button>
        </div>
    </form>

    <table>
        <thead>
            <tr>
                <th>Titulo</th>
                <th>Descripcion</th>
                <th>Tipo</th>
                <th></th>
            </tr>
        </thead>
        <tbody id="tabla-elementos">
            
        </tbody>
    </table>

JavaScript

var tablaElementos = document.getElementById('tabla-elementos');

var txtTitulo = document.getElementById('titulo');
var txtDescripcion = document.getElementById('descripcion');
var ddlTipo = document.getElementById('tipo');

var btnAgregar = document.getElementById('agregar');

var datos = [];

function btnEditar_Click(event) {

    txtTitulo.value = this.elemento.titulo;
    txtDescripcion.value = this.elemento.descripcion;
    ddlTipo.value = this.elemento.tipo;

}

function btnAgregar_Click(event) {

    var titulo = txtTitulo.value || '';
    var descripcion = txtDescripcion.value || '';
    var tipo = ddlTipo.value || '';

    if (!titulo || !titulo.trim().length) {
        alert('debe ingresar un titulo');
        return;
    }
    
    if (!descripcion || !descripcion.trim().length) {
        alert('debe ingresar una descripcion');
        return;
    }

    txtTitulo.value = '';
    txtDescripcion.value = '';

    txtTitulo.focus();

    // JSON

    var item = {
        titulo: titulo.trim(),
        descripcion: descripcion.trim(),
        tipo: tipo,
        fecha: new Date()
    };

    datos.push(item);
    
    //tablaElementos.innerHTML = '';

    while (tablaElementos.childElementCount > 0) {
        tablaElementos.removeChild(tablaElementos.firstElementChild);
    }

    for (var i = 0; i < datos.length; i++) {

        var elemento = datos[i];

        /*
        var fila = '<tr><td>' + elemento.titulo +
                    '</td><td>' + elemento.descripcion +
                    '</td><td>' + elemento.tipo + '</td></tr>';

        tablaElementos.innerHTML += fila;
        */

        var tr = document.createElement('tr');
        var td1 = document.createElement('td');
        var td2 = document.createElement('td');
        var td3 = document.createElement('td');
        var td4 = document.createElement('td');

        tr.appendChild(td1);
        tr.appendChild(td2);
        tr.appendChild(td3);
        tr.appendChild(td4);

       ...