summary refs log tree commit diff
path: root/webclient/js/autofill-event.js
diff options
context:
space:
mode:
authorErik Johnston <erik@matrix.org>2014-09-12 18:19:32 +0100
committerErik Johnston <erik@matrix.org>2014-09-12 18:19:32 +0100
commite3aec9bc818e203a4883f8863acb96b9c273112a (patch)
tree762f87365f917f510f00bc6aee7a4068cdd56e76 /webclient/js/autofill-event.js
parentfix embarassing bug where in-progress messages get vaped when the previous on... (diff)
parentBump version and change log (diff)
downloadsynapse-e3aec9bc818e203a4883f8863acb96b9c273112a.tar.xz
Merge branch 'release-v0.2.3' of github.com:matrix-org/synapse
Conflicts:
	webclient/room/room-controller.js
Diffstat (limited to 'webclient/js/autofill-event.js')
-rwxr-xr-xwebclient/js/autofill-event.js117
1 files changed, 117 insertions, 0 deletions
diff --git a/webclient/js/autofill-event.js b/webclient/js/autofill-event.js
new file mode 100755
index 0000000000..006f83e1be
--- /dev/null
+++ b/webclient/js/autofill-event.js
@@ -0,0 +1,117 @@
+/**
+ * Autofill event polyfill ##version:1.0.0##
+ * (c) 2014 Google, Inc.
+ * License: MIT
+ */
+(function(window) {
+  var $ = window.jQuery || window.angular.element;
+  var rootElement = window.document.documentElement,
+    $rootElement = $(rootElement);
+
+  addGlobalEventListener('change', markValue);
+  addValueChangeByJsListener(markValue);
+
+  $.prototype.checkAndTriggerAutoFillEvent = jqCheckAndTriggerAutoFillEvent;
+
+  // Need to use blur and not change event
+  // as Chrome does not fire change events in all cases an input is changed
+  // (e.g. when starting to type and then finish the input by auto filling a username)
+  addGlobalEventListener('blur', function(target) {
+    // setTimeout needed for Chrome as it fills other
+    // form fields a little later...
+    window.setTimeout(function() {
+      findParentForm(target).find('input').checkAndTriggerAutoFillEvent();
+    }, 20);
+  });
+
+  window.document.addEventListener('DOMContentLoaded', function() {
+    // The timeout is needed for Chrome as it auto fills
+    // login forms some time after DOMContentLoaded!
+    window.setTimeout(function() {
+      $rootElement.find('input').checkAndTriggerAutoFillEvent();
+    }, 200);
+  }, false);
+
+  return;
+
+  // ----------
+
+  function jqCheckAndTriggerAutoFillEvent() {
+    var i, el;
+    for (i=0; i<this.length; i++) {
+      el = this[i];
+      if (!valueMarked(el)) {
+        markValue(el);
+        triggerChangeEvent(el);
+      }
+    }
+  }
+
+  function valueMarked(el) {
+    var val = el.value,
+         $$currentValue = el.$$currentValue;
+    if (!val && !$$currentValue) {
+      return true;
+    }
+    return val === $$currentValue;
+  }
+
+  function markValue(el) {
+    el.$$currentValue = el.value;
+  }
+
+  function addValueChangeByJsListener(listener) {
+    var jq = window.jQuery || window.angular.element,
+        jqProto = jq.prototype;
+    var _val = jqProto.val;
+    jqProto.val = function(newValue) {
+      var res = _val.apply(this, arguments);
+      if (arguments.length > 0) {
+        forEach(this, function(el) {
+          listener(el, newValue);
+        });
+      }
+      return res;
+    }
+  }
+
+  function addGlobalEventListener(eventName, listener) {
+    // Use a capturing event listener so that
+    // we also get the event when it's stopped!
+    // Also, the blur event does not bubble.
+    rootElement.addEventListener(eventName, onEvent, true);
+
+    function onEvent(event) {
+      var target = event.target;
+      listener(target);
+    }
+  }
+
+  function findParentForm(el) {
+    while (el) {
+      if (el.nodeName === 'FORM') {
+        return $(el);
+      }
+      el = el.parentNode;
+    }
+    return $();
+  }
+
+  function forEach(arr, listener) {
+    if (arr.forEach) {
+      return arr.forEach(listener);
+    }
+    var i;
+    for (i=0; i<arr.length; i++) {
+      listener(arr[i]);
+    }
+  }
+
+  function triggerChangeEvent(element) {
+    var doc = window.document;
+    var event = doc.createEvent("HTMLEvents");
+    event.initEvent("change", true, true);
+    element.dispatchEvent(event);
+  }
+
+})(window);