diff --git a/core/misc/machine-name.js b/core/misc/machine-name.js
index 2b304bf..28fe7f1 100644
--- a/core/misc/machine-name.js
+++ b/core/misc/machine-name.js
@@ -38,6 +38,7 @@
      *   - field_suffix: The #field_suffix of the form element.
      */
     attach: function (context, settings) {
+<<<<<<< HEAD
       var self = this;
       var $context = $(context);
       var timeout = null;
@@ -49,109 +50,194 @@
         data.$target.trigger('focus');
         data.$suffix.hide();
         data.$source.off('.machineName');
+=======
+      var sourceId;
+
+      for (sourceId in settings.machineName) {
+        Drupal.MachineName.names.push(new Drupal.MachineName(sourceId, settings, context));
+>>>>>>> Issue #1686174 by lorique, mikeker, Temoor, Manjit.Singh: Refactor machine-name.js
       }
+    }
+  };
 
-      function machineNameHandler(e) {
-        var data = e.data;
-        var options = data.options;
-        var baseValue = $(e.target).val();
+  function MachineName(sourceId, settings, context) {
 
-        var rx = new RegExp(options.replace_pattern, 'g');
-        var expected = baseValue.toLowerCase().replace(rx, options.replace).substr(0, options.maxlength);
+    /**
+     *  @var self
+     *    javascript object containing the current Drupal.machineName for later use.
+     */
+    var self = this;
 
-        // Abort the last pending request because the label has changed and it
-        // is no longer valid.
-        if (xhr && xhr.readystate !== 4) {
-          xhr.abort();
-          xhr = null;
-        }
+    /**
+     *  @var options
+     *    An object of options used for retrieving machine name options
+     *  @var machine
+     *    A string containing the current machine name
+     */
+    var options, machine;
 
-        // Wait 300 milliseconds since the last event to update the machine name
-        // i.e., after the user has stopped typing.
-        if (timeout) {
-          clearTimeout(timeout);
-          timeout = null;
-        }
-        timeout = setTimeout(function () {
-          if (baseValue.toLowerCase() !== expected) {
-            xhr = self.transliterate(baseValue, options).done(function (machine) {
-              self.showMachineName(machine.substr(0, options.maxlength), data);
-            });
-          }
-          else {
-            self.showMachineName(expected, data);
-          }
-        }, 300);
+    // Get options from the settings object using the sourceId
+    options = settings.machineName[sourceId];
+
+    var $context = $(context);
+
+    if (settings.machineName.hasOwnProperty(sourceId)) {
+      // Get eventData object
+      var eventData = this.eventData(sourceId, options, $context);
+
+      // Figure out the maximum length for the machine name.
+      options.maxlength = eventData.$target.attr('maxlength');
+      // Hide the form item container of the machine name form element.
+      eventData.$wrapper.hide();
+      // Determine the initial machine name value. Unless the machine name form
+      // element is disabled or not empty, the initial default value is based on
+      // the human-readable form element value.
+      if (eventData.$target.is(':disabled') || eventData.$target.val() !== '') {
+        machine = eventData.$target.val();
       }
+      else {
+        machine = self.transliterate(eventData.$source.val(), options);
+      }
+      // Append the machine name preview to the source field.
+      var preview_text = options.field_prefix + Drupal.checkPlain(machine) + options.field_suffix;
+      var $preview = $('<span class="machine-name-value">' + preview_text + '</span>');
+      eventData.$preview = $preview;
+      eventData.$suffix.empty();
+      if (options.label) {
+        eventData.$suffix.append(' ').append('<span class="machine-name-label">' + options.label + ':</span>');
+      }
+      eventData.$suffix.append(' ').append(eventData.$preview);
 
-      Object.keys(settings.machineName).forEach(function (source_id) {
-        var machine = '';
-        var eventData;
-        var options = settings.machineName[source_id];
-
-        var $source = $context.find(source_id).addClass('machine-name-source').once('machine-name');
-        var $target = $context.find(options.target).addClass('machine-name-target');
-        var $suffix = $context.find(options.suffix);
-        var $wrapper = $target.closest('.form-item');
-        // All elements have to exist.
-        if (!$source.length || !$target.length || !$suffix.length || !$wrapper.length) {
-          return;
-        }
-        // Skip processing upon a form validation error on the machine name.
-        if ($target.hasClass('error')) {
-          return;
-        }
-        // Figure out the maximum length for the machine name.
-        options.maxlength = $target.attr('maxlength');
-        // Hide the form item container of the machine name form element.
-        $wrapper.addClass('visually-hidden');
-        // Determine the initial machine name value. Unless the machine name
-        // form element is disabled or not empty, the initial default value is
-        // based on the human-readable form element value.
-        if ($target.is(':disabled') || $target.val() !== '') {
-          machine = $target.val();
-        }
-        else if ($source.val() !== '') {
-          machine = self.transliterate($source.val(), options);
+      // If the machine name cannot be edited, stop further processing.
+      if (eventData.$target.is(':disabled')) {
+        return;
+      }
+
+      // If it is editable, append an edit link.
+      var $link = $('<span class="admin-link"><a href="#">' + Drupal.t('Edit') + '</a></span>').on('click', eventData, self.clickEditHandler);
+      eventData.$link = $link;
+
+      eventData.$suffix.append(' ').append(eventData.$link);
+
+      // Preview the machine name in realtime when the human-readable name
+      // changes, but only if there is no machine name yet; i.e., only upon
+      // initial creation, not when editing.
+      if (eventData.$target.val() === '') {
+        eventData.$source.on('keyup.machineName change.machineName input.machineName', eventData, self.machineNameHandler)
+          // Initialize machine name preview.
+          .trigger('keyup');
+      }
+    }
+  }
+
+  // Used for caching objects
+  $.extend(MachineName, {
+    names : []
+  });
+
+  $.extend(MachineName.prototype, {
+
+    /**
+     *  Handler for generating default eventData object.
+     *
+     *  @param sourceId
+     *    ID of source element
+     *
+     *  @param $context
+     *    Context element for finding elements
+     */
+    eventData: function (sourceId, options, $context) {
+      var $source = $context.find(sourceId).addClass('machine-name-source').once('machine-name');
+      var $target = $context.find(options.target).addClass('machine-name-target');
+      var $suffix = $context.find(options.suffix);
+      var $wrapper = $target.closest('.form-item');
+
+      var errors = [];
+
+      // All elements have to exist.
+      if (!$source.length || !$target.length || !$suffix.length || !$wrapper.length) {
+        if (!$source.length) {
+          errors.push('Source element is missing.');
         }
-        // Append the machine name preview to the source field.
-        var $preview = $('<span class="machine-name-value">' + options.field_prefix + Drupal.checkPlain(machine) + options.field_suffix + '</span>');
-        $suffix.empty();
-        if (options.label) {
-          $suffix.append('<span class="machine-name-label">' + options.label + ': </span>');
+
+        if (!$target.length) {
+          errors.push('Target element is missing.');
         }
-        $suffix.append($preview);
 
-        // If the machine name cannot be edited, stop further processing.
-        if ($target.is(':disabled')) {
-          return;
+        if (!$suffix.length) {
+          errors.push('Suffix element is missing.');
         }
 
-        eventData = {
-          $source: $source,
-          $target: $target,
-          $suffix: $suffix,
-          $wrapper: $wrapper,
-          $preview: $preview,
-          options: options
-        };
-        // If it is editable, append an edit link.
-        var $link = $('<span class="admin-link"><button type="button" class="link">' + Drupal.t('Edit') + '</button></span>').on('click', eventData, clickEditHandler);
-        $suffix.append($link);
-
-        // Preview the machine name in realtime when the human-readable name
-        // changes, but only if there is no machine name yet; i.e., only upon
-        // initial creation, not when editing.
-        if ($target.val() === '') {
-          $source.on('formUpdated.machineName', eventData, machineNameHandler)
-            // Initialize machine name preview.
-            .trigger('formUpdated.machineName');
+        if (!$wrapper.length) {
+          errors.push('Wrapper element is missing.');
         }
+      }
 
-        // Add a listener for an invalid event on the machine name input
-        // to show its container and focus it.
-        $target.on('invalid', eventData, clickEditHandler);
-      });
+      // Skip processing upon a form validation error on the machine name.
+      if ($target.hasClass('error')) {
+        errors.push('Machine name could not be validated.');
+      }
+
+      if (errors.length) {
+        throw new Error(errors.join(', '));
+      }
+
+      return {
+        $source: $source,
+        $target: $target,
+        $suffix: $suffix,
+        $wrapper: $wrapper,
+        options: options
+      };
+    },
+
+    /**
+     *  Edit button action for when editing a transliterated machine name.
+     *
+     *  @param e
+     *    A jQuery event object.
+     *    - data: the event data
+     *      - $wrapper: Wrapping form item div element.
+     *      - $target: Target input form item element.
+     *      - $suffix: Mandetory suffix to be added to the transliterated machine name.
+     *      - $source: Source input form item element of the machine name.
+     */
+    clickEditHandler: function (e) {
+      var data = e.data;
+      e.preventDefault();
+      data.$wrapper.show();
+      data.$target.trigger('focus');
+      data.$suffix.hide();
+      data.$source.off('.machineName');
+    },
+
+    /**
+     *  Machine name handler for generating the machine name from a human readable name.
+     *  @param e
+     *    A jQuery event object.
+     *    - data: the event data
+     *      - $wrapper: Wrapping form item div element.
+     *      - $target: Target input form item element.
+     *      - $suffix: Mandetory suffix to be added to the transliterated machine name.
+     *      - $source: Source input form item element of the machine name.
+     *      - $preview: Preview html element containing the machine name.
+     */
+    machineNameHandler: function (e) {
+      var data = e.data;
+      var options = data.options;
+      var baseValue = $(e.target).val();
+
+      var rx = new RegExp(options.replace_pattern, 'g');
+      var expected = baseValue.toLowerCase().replace(rx, options.replace).substr(0, options.maxlength);
+
+      if (baseValue.toLowerCase() !== expected) {
+        Drupal.MachineName.prototype.transliterate(baseValue, options).done(function (machine) {
+          Drupal.MachineName.prototype.showMachineName(machine.substr(0, options.maxlength), data);
+        });
+      }
+      else {
+        Drupal.MachineName.prototype.showMachineName(expected, data);
+      }
     },
 
     showMachineName: function (machine, data) {
@@ -190,14 +276,42 @@
      *   The transliterated source string.
      */
     transliterate: function (source, settings) {
-      return $.get(Drupal.url('machine_name/transliterate'), {
+
+      var now = Date.now();
+
+      // Number of milliseconds to wait between calls to the server. This avoids
+      // flooding the server with requests as a user is typing.
+      // @TODO: make this configurable?
+      this.delay = 250;
+
+      if ('undefined' != typeof this.lastCalled && 'undefined' != typeof this.cachedResult && (now - this.lastCalled <= this.delay)) {
+        // Make sure we make one final call to the server to capture the final
+        // characters typed.
+        var self = this;
+        if ('undefined' != typeof this.finalCallback) {
+          clearTimeout(this.finalCallback);
+        }
+        this.finalCallback = setTimeout(function() {
+          self.transliterate(source, settings);
+        }, this.delay);
+
+        return this.cachedResult;
+      }
+
+      // Updated cached results with the latest from the server.
+      this.lastCalled = now;
+      this.cachedResult = $.get(drupalSettings.path.basePath + 'machine_name/transliterate', {
         text: source,
         langcode: drupalSettings.langcode,
         replace_pattern: settings.replace_pattern,
         replace: settings.replace,
         lowercase: true
       });
+
+      return this.cachedResult;
     }
-  };
+  });
+
+  Drupal.MachineName = MachineName;
 
 })(jQuery, Drupal, drupalSettings);
