Extremely simplified Terrific.js module simulation in pure modern JS and DOM

HTML

<div class="mod mod-example">
    <button id="button1">1: Bad id</button>
    <button id="button2">2: Correct id</button>
    <button id="button3">3: Button id</button>
</div>

JavaScript

// Extremely simplified Terrific.js module simulation in pure *modern* JS and DOM :)
// Mozilla, Chrome, Opera

// Let's make a selector engine. A bit like jQuery. Just for fun. :)
// S returns an element, to keep it simple.
var S = function(selector, context) {
    context = context || document;
    return context.querySelector(selector);
};

// Module constructor
function Module(ctx) {
    this.init(ctx);
    this.on();
}

// "DOM ready"
document.addEventListener('DOMContentLoaded', function() {
    new Module( S('.mod-example') );
});

// This is what a Namics Frontender uses everyday
Module.prototype = {
    
    init: function(ctx) {
        // there is no super class here
        // could do this in the constructor, but hey, realism!
        this.ctx = ctx;
        
        // bind event handlers to module scope.
        this.onClickButton2 = this.onClickButton2.bind(this);
        this.onClickButton3 = this.onClickButton3.bind(this);
    },
    
    on: function() {
        S('#button1', this.ctx).addEventListener('click', this.alertThisId); // bad
        S('#button2', this.ctx).addEventListener('click', this.onClickButton2);
        S('#button3', this.ctx).addEventListener('click', this.onClickButton3);
    },
    
    id: 'module',
    
    onClickButton2: function(ev) {
        this.alertThisId();
    },
    
    onClickButton3: function(ev) {
        this.alertButtonId(ev.target);
    },
    
    alertThisId: function() {
        alert('this.id == "'+ this.id +'"');
    },
    
    alertButtonId: function(button) {
        alert('element.id == "'+ button.id +'"');
    }
};