<h1>Patrón Publicador/suscriptor o Publisher/subscriber</h1>
<button id="add">Agregar nuevo checkbox</button>
<input id="control" type="checkbox"/> Seleccionar

<h2>Nuevos checkboxes</h2>
<div id="container"></div>
input[type="checkbox"] {
  width: 20px;
  height: 20px;
}
const publisher = {
    // Array que guardara los suscriptores interesados en alguna actividad del Publicador
    subscribers: {
      any: [] //Cualquier actividad del publicador
    },
    // agregar nuevo suscriptor para ser notificado de cambios en la actividad 'type'
    subscribe (type, subscriberFn, context) {
      if(!this.subscribers[type]) {
        this.subscribers[type] = [];
      }
      this.subscribers[type].push({ fn: subscriberFn, context, type });
    },
    // Eliminar suscriptor de la actividad 'type' del Publicador
    unsubscribe (type, subscribeFn, context) {
      this.subscribers[type] = this.subscribers[type].filter(subscriber => {
        if(subscriber.fn === subscribeFn && subscriber.context === context ) {
          return false
        }
        return true;
      });
    },
    // notificar a todos los observadores de un cambio, para esto recorre el arreglo
    // de 'subscribers[type]' e invoca el método update de cada uno
    publish (type, arg) {
      this.subscribers[type].forEach( subscriber => {
        subscriber.fn.call(subscriber.context, arg);
      });
    }
  };

// Un observador con su método 'update'
const subscriber = {
  update (context) {
    console.log(context);
  }
};

// Reusu de código copiando propieades, para extender objetos del DOM y puedan ser SUSCRIBER y/o PUBLISHER
function extend(child, parent) {
  child = child || {};
  for(const prop in parent) {
    // evitar revisar la cadena de prototipos
    if (parent.hasOwnProperty(prop)) {
      child[prop] = parent[prop];  
    }
  }
  return child;
}

let addButton = document.querySelector('#add');
let control = document.querySelector('#control');
let container = document.querySelector('#container');

// El checkbox 'seleccionar' convertido en PUBLISHER
const publisherSeleccionar = extend(control, publisher);

publisherSeleccionar.addEventListener('click', function(e) {
  this.publish('check', this.checked);
});

addButton.addEventListener('click', (e) => {
  const check = document.createElement('input');
  check.type = "checkbox";
  // Cada checkbox creado sera convertido a SUBSCRIBER
  const subscriberCheckbox = extend(check, subscriber);
  subscriberCheckbox.update = function (value) {
    this.checked = value;
  };
  
  subscriberCheckbox.addEventListener('click', () => {
    publisherSeleccionar.unsubscribe('check', subscriberCheckbox.update, subscriberCheckbox);
  });
  
  publisherSeleccionar.subscribe('check', subscriberCheckbox.update, subscriberCheckbox);
  container.append(subscriberCheckbox);
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.