diff --git a/themes/bootstrap3/js/common.js b/themes/bootstrap3/js/common.js
index a7c50bcd250b5476631bcf0e69a503efc4bef08c..b88af888756e5ebbdb5869acb917d62a6a0e8e64 100644
--- a/themes/bootstrap3/js/common.js
+++ b/themes/bootstrap3/js/common.js
@@ -2,7 +2,7 @@
 /*exported VuFind, htmlEncode, deparam, moreFacets, lessFacets, getUrlRoot, phoneNumberFormHandler, recaptchaOnLoad, resetCaptcha, bulkFormHandler */
 
 // IE 9< console polyfill
-window.console = window.console || {log: function polyfillLog() {}};
+window.console = window.console || { log: function polyfillLog() {} };
 
 var VuFind = (function VuFind() {
   var defaultSearchBackend = null;
@@ -11,6 +11,22 @@ var VuFind = (function VuFind() {
   var _submodules = [];
   var _translations = {};
 
+  // Emit a custom event
+  // Recommendation: prefix with vf-
+  var emit = function emit(name, detail) {
+    if (typeof detail === 'undefined') {
+      document.dispatchEvent(new Event(name));
+    } else {
+      var event = document.createEvent('CustomEvent');
+      event.initCustomEvent(name, true, true, detail); // name, canBubble, cancelable, detail
+      document.dispatchEvent(event);
+    }
+  };
+  // Listen shortcut to put everyone on the same element
+  var listen = function listen(name, func) {
+    document.addEventListener(name, func, false);
+  };
+
   var register = function register(name, module) {
     if (_submodules.indexOf(name) === -1) {
       _submodules.push(name);
@@ -73,6 +89,8 @@ var VuFind = (function VuFind() {
 
     addTranslations: addTranslations,
     init: init,
+    emit: emit,
+    listen: listen,
     refreshPage: refreshPage,
     register: register,
     translate: translate