Index: modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php	(date 1507118010000)
+++ modules/contrib/shs/src/Plugin/Field/FieldWidget/OptionsShsWidget.php	(revision )
@@ -2,11 +2,14 @@
 
 namespace Drupal\shs\Plugin\Field\FieldWidget;
 
+use Drupal;
 use Drupal\Component\Utility\Html;
+use Drupal\Core\Entity\FieldableEntityInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\BubbleableMetadata;
 use Drupal\Core\Url;
 
 /**
@@ -47,7 +50,6 @@
       '#title' => t('Allow creating new items'),
       '#default_value' => $this->getSetting('create_new_items'),
       '#description' => t('Allow users to create new items of the source bundle.'),
-      '#disabled' => TRUE,
     ];
     $element['create_new_levels'] = [
       '#type' => 'checkbox',
@@ -59,7 +61,6 @@
           ':input[name="fields[' . $field_name . '][settings_edit_form][settings][create_new_items]"]' => ['checked' => TRUE],
         ],
       ],
-      '#disabled' => TRUE,
     ];
     $element['force_deepest'] = [
       '#type' => 'checkbox',
@@ -103,6 +104,10 @@
    * {@inheritdoc}
    */
   public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+
+    // Don't cache because we get illegal choice errors if new items are created.
+    $form_state->disableCache();
+
     $element = parent::formElement($items, $delta, $element, $form, $form_state);
     if (isset($form_state->getBuildInfo()['base_form_id']) && ('field_config_form' === $form_state->getBuildInfo()['base_form_id'])) {
       // Do not display the shs widget in the field config.
@@ -122,6 +127,8 @@
       'anyLabel' => $this->getEmptyLabel() ?: t('- None -'),
       'anyValue' => '_none',
       'addNewLabel' => t('Add another item'),
+      'createValue' => '_create',
+      'createLabel' => $this->getCreateLabel() ?: t('Create...'),
     ];
 
     $bundle = reset($target_bundles);
@@ -139,10 +146,22 @@
       $parents = shs_term_get_parents($default_value, $settings_additional, $this->fieldDefinition->getItemDefinition()->getSetting('target_type'));
     }
 
+    // Generate a token for our ajax url.
+    // We need to run this through a render function because Drupal.url generates
+    // a placeholder token.
+    $urlBubbleable = Url::fromRoute('shs.create_term')->toString(TRUE);
+    $urlRender = array(
+      '#markup' => $urlBubbleable->getGeneratedUrl(),
+    );
+    BubbleableMetadata::createFromRenderArray($urlRender)
+      ->merge($urlBubbleable)->applyTo($urlRender);
+    $url = (string) Drupal::service('renderer')->renderPlain($urlRender);
+
     $settings_shs = [
       'settings' => $this->getSettings() + $settings_additional,
       'bundle' => $bundle,
       'baseUrl' => Url::fromUri('base:/shs-term-data')->toString(),
+      'createUrl' => $url,
       'cardinality' => $this->fieldDefinition->getFieldStorageDefinition()->getCardinality(),
       'parents' => $parents,
       'defaultValue' => $default_value,
@@ -153,7 +172,7 @@
       "shs_{$field_name}_js_settings",
     ];
     // Allow other modules to override the settings.
-    \Drupal::moduleHandler()->alter($hooks, $settings_shs, $bundle, $field_name);
+    Drupal::moduleHandler()->alter($hooks, $settings_shs, $bundle, $field_name);
 
     $element += [
       '#shs' => $settings_shs,
@@ -276,4 +295,32 @@
     return $options[$value];
   }
 
+  /**
+   * Returns the array of options for the widget.
+   *
+   * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
+   *   The entity for which to return options.
+   *
+   * @return array
+   *   The array of options for the widget.
+   */
+  protected function getOptions(FieldableEntityInterface $entity) {
+    if (!isset($this->options)) {
+      $options = parent::getOptions($entity);
+
+      // Add a create option if the widget needs one.
+      $new_label = $this->getCreateLabel();
+      if ($new_label) {
+        $options['_create'] = $new_label;
+      }
+
+      $this->options = $options;
+    }
+    return $this->options;
+  }
+
+  public function getCreateLabel() {
+    return (string) t('Create...');
+  }
+
 }
Index: modules/contrib/shs/src/Controller/ShsController.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- modules/contrib/shs/src/Controller/ShsController.php	(date 1507118010000)
+++ modules/contrib/shs/src/Controller/ShsController.php	(revision )
@@ -2,10 +2,16 @@
 
 namespace Drupal\shs\Controller;
 
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Cache\CacheableJsonResponse;
 use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\shs\Cache\ShsCacheableJsonResponse;
 use Drupal\shs\Cache\ShsTermCacheDependency;
+use Drupal\taxonomy\Entity\Vocabulary;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Controller for getting taxonomy terms.
@@ -80,4 +86,93 @@
     return $response;
   }
 
+  /**
+   * Create term data.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *
+   * @return JsonResponse
+   *   Json response.
+   */
+  public function createTerm(Request $request) {
+
+    $result = NULL;
+
+    // Obtain the data from the json.
+    $data = json_decode($request->getContent());
+    $value = $data->arguments->value;
+    $bundle = $data->arguments->bundle;
+    $entity_id = $data->arguments->entity_id;
+    $langcode = $data->arguments->langcode;
+
+    if (!$langcode) {
+      $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
+    }
+
+    $entity_manager = \Drupal::getContainer()->get('entity.manager');
+    $storage = $entity_manager->getStorage('taxonomy_term');
+
+    // Try to find the term.
+    $found = null;
+    $terms = $storage->loadTree($bundle, $entity_id, 1, TRUE);
+    foreach ($terms as $term) {
+      if ($term->hasTranslation($langcode)) {
+        $term = $term->getTranslation($langcode);
+      }
+      else {
+        $langcode = $term->default_langcode;
+      }
+
+      if (strcasecmp($term->getName(), $value) === 0) {
+        $found = $term;
+        break;
+      }
+    }
+
+    if (!$found) {
+      $term = $storage->create([
+        'vid' => $bundle,
+        'langcode' => $langcode,
+        'name' => $value,
+        'parent' => array($entity_id),
+      ]);
+      $term->save();
+    }
+    else {
+      $term = $found;
+    }
+
+    $result = (object) [
+      'tid' => $term->id(),
+      'name' => $term->getName(),
+      'description__value' => $term->getDescription(),
+      'langcode' => $langcode,
+      'hasChildren' => shs_term_has_children($term->id()),
+    ];
+
+    $response = new JsonResponse();
+    $response->setData($result);
+
+    return $response;
+  }
+
+  /**
+   * Checks access for a specific request.
+   *
+   * @param \Drupal\Core\Session\AccountInterface $account
+   *   Run access checks for this account.
+   *
+   * @return bool
+   */
+  public function createTermAccess(AccountInterface $account) {
+    $request = \Drupal::request();
+    $data = json_decode($request->getContent());
+    $bundle = $data->arguments->bundle;
+
+    return AccessResult::allowedIfHasPermissions($account, [
+      "edit terms in {$bundle}",
+      'administer taxonomy'
+    ], 'OR');
+  }
+
 }
Index: modules/contrib/shs/js/models/WidgetModel.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- modules/contrib/shs/js/models/WidgetModel.js	(date 1507118010000)
+++ modules/contrib/shs/js/models/WidgetModel.js	(revision )
@@ -31,6 +31,11 @@
        */
       defaultValue: '_none',
 
+      /**
+       * The new item that was created.
+       */
+      createValue: null,
+      
       /**
        * Position of widget in app.
        *
Index: modules/contrib/shs/js/views/AppView.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- modules/contrib/shs/js/views/AppView.js	(date 1507118010000)
+++ modules/contrib/shs/js/views/AppView.js	(revision )
@@ -65,9 +65,6 @@
           parents: parents
         }));
       });
-//      $.each(app.getConfig('parents'), function (index, item) {
-//        // Add WidgetModel for each parent.
-//      });
 
       app.collection.trigger('initialize:shs');
 
@@ -127,6 +124,19 @@
           // Use value of parent widget (which is the id of the model ;)).
           value = widgetModel.get('id');
         }
+        else if (widgetModel.get('createValue')) {
+          // Add the created item to the original select item.
+          var options = $("option", app.$el).map(function () {
+            return $(this).val();
+          }).get();
+          if ($.inArray(value, options) === -1) {
+            var item = widgetModel.get('createValue');
+            app.$el.append($("<option/>").val(item.tid).text(item.name));
+            // We can now reset our widget model to the new tid.
+            widgetModel.set('createValue', null);
+            widgetModel.set('defaultValue', item.tid);
+          }
+        }
       }
       // Set the updated value.
       app.$el.val(value).trigger({
Index: modules/contrib/shs/shs.module
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- modules/contrib/shs/shs.module	(date 1507118010000)
+++ modules/contrib/shs/shs.module	(revision )
@@ -79,7 +79,7 @@
       $storage = Drupal::entityTypeManager()->getStorage($target_type);
       $parent_terms = array_reverse(array_keys($storage->loadAllParents($value)));
       $keys = array_merge([0], $parent_terms);
-      $values = array_merge($parent_terms, [$value]);
+      $values = array_merge($parent_terms, [$settings['anyValue']]);
       $parents[$delta] = [];
       foreach ($keys as $index => $key) {
         $parents[$delta][] = [
Index: modules/contrib/shs/js/views/WidgetView.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- modules/contrib/shs/js/views/WidgetView.js	(date 1507118010000)
+++ modules/contrib/shs/js/views/WidgetView.js	(revision )
@@ -40,7 +40,7 @@
       if (!this.model.get('dataLoaded')) {
         // Create new item collection.
         this.model.itemCollection = new Drupal.shs.WidgetItemCollection({
-          url: this.container.app.getConfig('baseUrl') + '/' + this.container.app.getConfig('fieldName') + '/' + this.container.app.getConfig('bundle') + '/' + this.model.get('id')
+          url: Drupal.url.toAbsolute(this.container.app.getConfig('baseUrl') + '/' + this.container.app.getConfig('fieldName') + '/' + this.container.app.getConfig('bundle') + '/' + this.model.get('id'))
         });
       }
 
@@ -91,6 +91,11 @@
       // Add "any" option.
       widget.$el.append($('<option>').text(widget.container.app.getSetting('anyLabel')).val(widget.container.app.getSetting('anyValue')));
 
+      // Add "create" option.
+      if (widget.container.app.getSetting('create_new_items')) {
+        widget.$el.append($('<option>').text(widget.container.app.getSetting('createLabel')).val(widget.container.app.getSetting('createValue')));
+      }
+
       // Create options from collection.
       widget.model.itemCollection.each(function (item) {
         if (!item.get('tid')) {
@@ -138,6 +143,67 @@
         $container.append(widget.$el.fadeIn(widget.container.app.getConfig('display.animationSpeed')));
       }
 
+      var createValue = widget.container.app.getSetting('createValue');
+      if (widget.$el.val() == createValue) {
+        var create_item_input_id = 'shs-widget-create-new-item-' + widget.container.app.getConfig('fieldName');
+        $container.append($('<input>')
+            .on('keyup', function(e) {
+              if (e.keyCode == 13) {
+                // Do something
+                $('#' + create_item_input_id + '_button').trigger('click');
+                e.preventDefault();
+                return false;
+              }
+            })
+            .attr('type', 'text')
+            .attr('id', create_item_input_id)
+            .attr('name', 'create_new_item')
+        ).append($('<button>')
+            .attr('id', create_item_input_id + '_button')
+            .html('Create')
+            .on('click', function(e) {
+                var value = $('#' + create_item_input_id).val();
+
+                // Get the langcode value if present.
+                var $language = $('select[name="langcode[0][value]"]');
+                var langcode = 'und';
+                if ($language) {
+                  langcode = $language.val();
+                }
+
+                $.ajax({
+                  url: Drupal.url.toAbsolute(widget.container.app.getConfig('createUrl')),
+                  type: 'POST',
+                  dataType: 'json',
+                  async: false,
+                  contentType: 'application/json',
+                  Accept: 'application/json',
+                  data: JSON.stringify({
+                    arguments: {
+                      value: value,
+                      bundle: widget.container.app.getConfig('bundle'),
+                      entity_id: widget.model.get('id'),
+                      langcode: langcode
+                    }
+                  })
+                }).then(function(data) {
+                  if (data !== 'null') {
+                    // Force a reload.
+                    widget.model.set('dataLoaded', false);
+
+                    // Update create value of attached model.
+                    widget.model.set('createValue', data);
+
+                    // Fire events.
+                    widget.container.collection.trigger('update:selection', widget.model, widget.model.get('defaultValue'), widget);
+                  }
+                });
+
+                e.preventDefault();
+                return false;
+            })
+        );
+      }
       widget.model.set('dataLoaded', true);
       // Return self for chaining.
       return widget;
Index: modules/contrib/shs/shs.routing.yml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- modules/contrib/shs/shs.routing.yml	(date 1507118010000)
+++ modules/contrib/shs/shs.routing.yml	(revision )
@@ -6,3 +6,11 @@
     entity_id: null
   requirements:
     _permission: 'access content'
+
+shs.create_term:
+  path: '/shs-create-term'
+  defaults:
+    _controller: '\Drupal\shs\Controller\ShsController::createTerm'
+  requirements:
+    _csrf_token: 'TRUE'
+    _custom_access:  '\Drupal\shs\Controller\ShsController::createTermAccess'
Index: modules/contrib/shs/js/views/ContainerView.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- modules/contrib/shs/js/views/ContainerView.js	(date 1507118010000)
+++ modules/contrib/shs/js/views/ContainerView.js	(revision )
@@ -42,7 +42,7 @@
       }
 
       this.collection = new Drupal.shs.WidgetCollection({
-        url: this.app.getConfig('baseUrl') + '/' + this.app.getConfig('fieldName') + '/' + this.app.getConfig('bundle')
+        url: Drupal.url.toAbsolute(this.app.getConfig('baseUrl') + '/' + this.app.getConfig('fieldName') + '/' + this.app.getConfig('bundle'))
       });
       this.collection.reset();
 
@@ -119,7 +119,14 @@
       container.collection.remove(models);
 
       var anyValue = container.app.getSetting('anyValue');
-      if (value !== anyValue) {
+      var createValue = container.app.getSetting('createValue');
+
+      if (value === createValue && widgetModel.get('createValue')) {
+        var item = widgetModel.get('createValue');
+        value = item.tid;
+      }
+
+      if ((value !== anyValue) && (value !== createValue)) {
         // Add new model with current selection.
         container.collection.add(new Drupal.shs.classes[container.app.getConfig('fieldName')].models.widget({
           id: value,
@@ -130,7 +137,7 @@
         // Use value of parent widget (which is the id of the model ;)).
         value = widgetModel.get('id');
       }
-
+      
       // Update parents.
       var parents = [];
       var previousParent = 0;
