Мля, а круто получается, вот весь код (пока быдлокод рефакторинг дело последнее)
<script>
//noinspection JSCheckFunctionSignatures
(function(window, document, undefined) {
  var ui = {};
  ui.module = {};
  document.addEventListener('DOMContentLoaded', function() {
    initModules();
  });
  function initModules(appContainer, scope) {
    appContainer = appContainer || document.body;
    scope = scope || {};
    var children = appContainer.children;
    for (var i = 0; i < children.length; i++) {
      var child = children[i];
      var uiAttr = child.getAttribute('ui');
      // мы наткнулись на декларацию модуля
      if (uiAttr && /^\w+$/.test(uiAttr)) {
        var name = uiAttr;
        if (!ui.module[name]) continue;
        var container = child;
        var widgets = findWidgets(child, uiAttr);
        var newScope = Object.create(scope);
        var module = new ui.module[name](newScope, widgets, container);
        ui[name] = ui[name] || [];
        ui[name].push(module);
      }
      initModules(child, scope);
    }
  }
  function findWidgets(moduleElement, moduleName) {
    function widget(name, handler) {
      if (widget[name]) widget[name].forEach(handler);
    }
    findIn(moduleElement);
    function findIn(element) {
      var children = element.children;
      for (var i = 0; i < children.length; i++) {
        var child = children[i];
        var uiAttr = child.getAttribute('ui');
        var regExp = new RegExp(moduleName + ':(\\w+)');
        if (uiAttr === moduleName) continue;
        if (uiAttr && regExp.test(uiAttr)) {
          var widgetName = regExp.exec(uiAttr)[1];
          widget[widgetName] = widget[widgetName] || [];
          widget[widgetName].push(child);
        }
        findIn(child);
      }
    }
    return widget;
  }
  window['ui'] = ui;
})(window, document);
ui.module['window'] = function($scope, $widget, $moduleElement) {
  var animationId;
  var dragging = false;
  var clickX = 0, clickY = 0;
  var x = 0, y = 0;
  $widget('close', function(close) {
    close.addEventListener('click', function() {
      $moduleElement.style.display = 'none';
    });
  });
  $widget('title', function(title) {
    title.addEventListener('mousedown', function(event) {
      var rect = $moduleElement.getBoundingClientRect();
      clickX = event.clientX - rect.left;
      clickY = event.clientY - rect.top;
      dragging = true;
      event.preventDefault();
      render();
    });
  });
  window.addEventListener('mousemove', function(event) {
    x = event.clientX;
    y = event.clientY;
  });
  window.addEventListener('mouseup', function() {
    dragging = false;
    cancelRequestAnimationFrame(animationId);
  });
  function render() {
    animationId = requestAnimationFrame(render, $moduleElement);
    if (!dragging) return;
    $moduleElement.style.left = x - clickX + 'px';
    $moduleElement.style.top = y - clickY + 'px';
  }
};
ui.module['chat'] = function($scope, $widgets, $moduleElement) {
  $widgets('input', function(input) {
    input.addEventListener('input', function(event) {
      $widgets('post', function(post) {
        post.innerHTML = event.target.value;
      });
    });
  });
};
</script>
<style type="text/css">
  .window {
    position         : absolute;
    background-color : dodgerblue;
    width            : 300px;
    height           : 250px;
  }
  .window_header {
    cursor           : pointer;
    background-color : coral;
  }
</style>
<div ui="window" class="window">
  <h1 ui="window:title" class="window_header">Заголовок окна</h1>
  <button ui="window:close">Закрыть</button>
  <h2 ui="window:title" class="window_header">Тоже заголовок окна</h2>
  <div ui="chat">
    <div ui="chat:post"></div>
    <input ui="chat:input">
  </div>
</div>