diff --git a/js_example/css/jsweights.css b/js_example/css/jsweights.css
new file mode 100755
index 0000000..b454f01
--- /dev/null
+++ b/js_example/css/jsweights.css
@@ -0,0 +1,4 @@
+div#js-weights div {
+  font-size: 20px;
+  font-weight: bold;
+}
diff --git a/js_example/js/black.js b/js_example/js/black.js
new file mode 100755
index 0000000..1a3441e
--- /dev/null
+++ b/js_example/js/black.js
@@ -0,0 +1,13 @@
+(function ($, Drupal, drupalSettings) {
+    "use strict";
+    /**
+     * Attaches the JS test behavior to to weight div.
+     */
+    Drupal.behaviors.jsTestBlackWeight = {
+        attach: function(context, settings) {
+            var weight = drupalSettings.js_weights.black;
+            var newDiv = $('<div></div>').css('color', 'black').html('I have a weight of ' + weight);
+            $('#js-weights').append(newDiv);
+        }
+    };
+})(jQuery, Drupal, drupalSettings);
diff --git a/js_example/js/blue.js b/js_example/js/blue.js
new file mode 100755
index 0000000..f34b401
--- /dev/null
+++ b/js_example/js/blue.js
@@ -0,0 +1,13 @@
+(function ($, Drupal, drupalSettings) {
+    "use strict";
+    /**
+     * Attaches the JS test behavior to weight div.
+     */
+    Drupal.behaviors.jsTestBlueWeight = {
+        attach: function(context, settings) {
+            var weight = drupalSettings.js_weights.blue;
+            var newDiv = $('<div></div>').css('color', 'blue').html('I have a weight of ' + weight);
+            $('#js-weights').append(newDiv);
+        }
+    };
+})(jQuery, Drupal, drupalSettings);
diff --git a/js_example/js/brown.js b/js_example/js/brown.js
new file mode 100755
index 0000000..93533ee
--- /dev/null
+++ b/js_example/js/brown.js
@@ -0,0 +1,13 @@
+(function ($, Drupal, drupalSettings) {
+    "use strict";
+    /**
+     * Attaches the JS test behavior to weight div.
+     */
+    Drupal.behaviors.jsTestBrownWeight = {
+        attach: function(context, settings) {
+            var weight = drupalSettings.js_weights.brown;
+            var newDiv = $('<div></div>').css('color', 'brown').html('I have a weight of ' + weight);
+            $('#js-weights').append(newDiv);
+        }
+    };
+})(jQuery, Drupal, drupalSettings);
diff --git a/js_example/js/green.js b/js_example/js/green.js
new file mode 100755
index 0000000..950f109
--- /dev/null
+++ b/js_example/js/green.js
@@ -0,0 +1,13 @@
+(function ($, Drupal, drupalSettings) {
+    "use strict";
+    /**
+     * Attaches the JS test behavior to weight div.
+     */
+    Drupal.behaviors.jsTestGreenWeight = {
+        attach: function(context, settings) {
+            var weight = drupalSettings.js_weights.green;
+            var newDiv = $('<div></div>').css('color', 'green').html('I have a weight of ' + weight);
+            $('#js-weights').append(newDiv);
+        }
+    };
+})(jQuery, Drupal, drupalSettings);
diff --git a/js_example/js/purple.js b/js_example/js/purple.js
new file mode 100755
index 0000000..e237fad
--- /dev/null
+++ b/js_example/js/purple.js
@@ -0,0 +1,13 @@
+(function ($, Drupal, drupalSettings) {
+    "use strict";
+    /**
+     * Attaches the JS test behavior to weight div.
+     */
+    Drupal.behaviors.jsTestPurpleWeight = {
+        attach: function(context, settings) {
+            var weight = drupalSettings.js_weights.purple;
+            var newDiv = $('<div></div>').css('color', 'purple').html('I have a weight of ' + weight);
+            $('#js-weights').append(newDiv);
+        }
+    };
+})(jQuery, Drupal, drupalSettings);
diff --git a/js_example/js/red.js b/js_example/js/red.js
new file mode 100755
index 0000000..467aa14
--- /dev/null
+++ b/js_example/js/red.js
@@ -0,0 +1,13 @@
+(function ($, Drupal, drupalSettings) {
+    "use strict";
+    /**
+     * Attaches the JS test behavior to weight div.
+     */
+    Drupal.behaviors.jsTestRedWeight = {
+        attach: function(context, settings) {
+            var weight = drupalSettings.js_weights.red;
+            var newDiv = $('<div></div>').css('color', 'red').html('I have a weight of ' + weight);
+            $('#js-weights').append(newDiv);
+        }
+    };
+})(jQuery, Drupal, drupalSettings);
diff --git a/js_example/js_example.info.yml b/js_example/js_example.info.yml
new file mode 100755
index 0000000..1561660
--- /dev/null
+++ b/js_example/js_example.info.yml
@@ -0,0 +1,5 @@
+name: 'JavaScript Example'
+description: 'An example module showing how to use some of the new JavaScript features in Drupal 8'
+type: module
+package: 'Example modules'
+core: 8.x
diff --git a/js_example/js_example.module b/js_example/js_example.module
new file mode 100755
index 0000000..8968d83
--- /dev/null
+++ b/js_example/js_example.module
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Examples showing how to use some of the new JavaScript features in Drupal 8.
+ */
+
+/**
+ * @defgroup js_example Example: JavaScript
+ * @ingroup examples
+ * @{
+ * Examples using Drupal 8's built-in JavaScript.
+ */
+
+/**
+ * Implements hook_theme().
+ */
+function js_example_theme() {
+  return array(
+    'my_accordion' => array(
+      'template' => 'accordion',
+      'variables' => array('title' => NULL),
+    ),
+  );
+}
+
+/**
+ * Implements hook_menu().
+ */
+function js_example_menu() {
+  $items = array();
+  $items['examples/js_example'] = array(
+    'title' => 'JavaScript Example',
+    'route_name' => 'js_example.info',
+    'expanded' => TRUE,
+  );
+  $items['examples/js_example/weights'] = array(
+    'title' => 'JS weighting in action',
+    'route_name' => 'js_example.weights',
+    'expanded' => TRUE,
+  );
+  $items['examples/js_example/accordion'] = array(
+    'title' => 'jQuery UI accordion',
+    'route_name' => 'js_example.accordion',
+    'expanded' => TRUE,
+  );
+  return $items;
+}
+
+/**
+ * @} End of "defgroup js_example".
+ */
diff --git a/js_example/js_example.routing.yml b/js_example/js_example.routing.yml
new file mode 100755
index 0000000..3735ed0
--- /dev/null
+++ b/js_example/js_example.routing.yml
@@ -0,0 +1,23 @@
+js_example.info:
+  path: '/examples/js_example'
+  defaults:
+    _title: 'JavaScript Example Information'
+    _content: '\Drupal\js_example\Controller\JsExampleController::info'
+  requirements:
+    _access: 'TRUE'
+
+js_example.weights:
+  path: '/examples/js_example/weights'
+  defaults:
+    _title: 'JS Example: see weighting in action'
+    _content: '\Drupal\js_example\Controller\JsExampleController::getJsWeightImplementation'
+  requirements:
+    _access: 'TRUE'
+
+js_example.accordion:
+  path: '/examples/js_example/accordion'
+  defaults:
+    _title: 'JS Example: jQuery UI accordion'
+    _content: '\Drupal\js_example\Controller\JsExampleController::getJsAccordionImplementation'
+  requirements:
+    _access: 'TRUE'
diff --git a/js_example/lib/Drupal/js_example/Controller/JsExampleController.php b/js_example/lib/Drupal/js_example/Controller/JsExampleController.php
new file mode 100755
index 0000000..a3e3a4c
--- /dev/null
+++ b/js_example/lib/Drupal/js_example/Controller/JsExampleController.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\js_example\Controller\JsExampleController.
+ */
+
+namespace Drupal\js_example\Controller;
+
+/**
+ * Controller for js_example pages.
+ *
+ * @ingroup js_example
+ */
+class JsExampleController {
+
+  /**
+   * js_example info page.
+   */
+  public function info() {
+    $build ['content'] = array(
+      '#markup' =>
+'<p>Drupal includes jQuery and jQuery UI.</p>
+<p>We have two examples of using these:</p>
+<ol>
+<li>An accordion-style section reveal effect. This demonstrates calling a jQuery UI function using Drupal&#39;s rendering system.</li>
+<li>Sorting according to numeric &#39;weight.&#39; This demonstrates attaching your own JavaScript code to individual page elements using Drupal&#39;s rendering system.</li>
+</ol>',
+    );
+    return $build;
+  }
+
+  /**
+   * Weights implementation.
+   */
+  public function getJsWeightImplementation() {
+    // Create an array of items with random-ish weight values.
+    $weights = array(
+      'red' => 100,
+      'blue' => 23,
+      'green' => 3,
+      'brown' => 45,
+      'black' => 5,
+      'purple' => 60
+    );
+
+    // Start building the content.
+    $build = array();
+    // Main container DIV.
+    $build['content'] = array(
+      '#markup' => '<div id="js-weights"></div>'
+    );
+    // Attach a CSS file to show which line is output by which script
+    $build['#attached']['css'] = array(drupal_get_path('module', 'js_example') .
+      '/css/jsweights.css');
+    // Attach some javascript files.
+    $build['#attached']['js'] = array(
+      array(
+        'data' => drupal_get_path('module', 'js_example') . '/js/red.js',
+        'weight' => $weights['red']
+      ),
+      array(
+        'data' => drupal_get_path('module', 'js_example') . '/js/blue.js',
+        'weight' => $weights['blue']
+      ),
+      array(
+        'data' => drupal_get_path('module', 'js_example') . '/js/green.js',
+        'weight' => $weights['green']
+      ),
+      array(
+        'data' => drupal_get_path('module', 'js_example') . '/js/brown.js',
+        'weight' => $weights['brown']
+      ),
+      array(
+        'data' => drupal_get_path('module', 'js_example') . '/js/black.js',
+        'weight' => $weights['black']
+      ),
+      array(
+        'data' => drupal_get_path('module', 'js_example') . '/js/purple.js',
+        'weight' => $weights['purple']
+      ),
+    );
+    // Attach the weighted array to our JavaScript settings.
+    $build['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('js_weights' => $weights),
+    );
+
+    return $build;
+  }
+
+  /**
+   * Accordion page implementation.
+   *
+   * We're allowing a twig template to define our content in this case,
+   * which isn't normally how things work, but it's easier to demonstrate
+   * the JavaScript this way.
+   */
+  function getJsAccordionImplementation() {
+    $title = t('Click sections to expand or collapse:');
+    $build['myelement'] = array(
+      '#theme' => 'my_accordion',
+      '#title' => $title,
+    );
+    $build['myelement']['#attached']['library'][] = array(
+      'system',
+      'jquery.ui.accordion',
+    );
+    $build['myelement']['#attached']['js'][] = array(
+      'data' => '(function($){$(function() { $("#accordion").accordion(); })})(jQuery);',
+      'type' => 'inline',
+    );
+    return $build;
+  }
+
+}
diff --git a/js_example/lib/Drupal/js_example/Tests/JsExampleTest.php b/js_example/lib/Drupal/js_example/Tests/JsExampleTest.php
new file mode 100644
index 0000000..5fc72ba
--- /dev/null
+++ b/js_example/lib/Drupal/js_example/Tests/JsExampleTest.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * SimpleTests for js_example module.
+ */
+
+namespace Drupal\js_example\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Minimal test case for the js_example module.
+ *
+ * @ingroup js_example
+ */
+class JsExampleTest extends WebTestBase {
+
+  /**
+   * Modules to install.
+   *
+   * @var array
+   */
+  public static $modules = array('js_example');
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'name' => 'JavaScript Examples Tests',
+      'description' => 'Functional tests for the js_example module',
+      'group' => 'Examples',
+    );
+  }
+
+  /**
+   * Test all the paths defined by our module.
+   */
+  public function testJsExample() {
+    $paths = array(
+      'examples/js_example',
+      'examples/js_example/weights',
+      'examples/js_example/accordion',
+    );
+    foreach($paths as $path) {
+      $this->drupalGet($path);
+      $this->assertResponse(200, 'Visited ' . $path);
+    }
+  }
+
+}
diff --git a/js_example/templates/accordion.html.twig b/js_example/templates/accordion.html.twig
new file mode 100755
index 0000000..6c54e95
--- /dev/null
+++ b/js_example/templates/accordion.html.twig
@@ -0,0 +1,60 @@
+{#
+
+/**
+ * @file
+ * Template file for js_example module.
+ */
+#}
+
+<div class="demo">
+<h2>{{  title }}</h2>
+<div id="accordion">
+  <h3><a href="#">Section 1</a></h3>
+  <div>
+    <p>
+    Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam. Integer
+    ut neque. Vivamus nisi metus, molestie vel, gravida in, condimentum sit
+    amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi. Proin viverra leo ut
+    odio. Curabitur malesuada. Vestibulum a velit eu ante scelerisque vulputate.
+    </p>
+  </div>
+  <h3><a href="#">Section 2</a></h3>
+  <div>
+    <p>
+    Sed non urna. Donec et ante. Phasellus eu ligula. Vestibulum sit amet
+    purus. Vivamus hendrerit, dolor at aliquet laoreet, mauris turpis porttitor
+    velit, faucibus interdum tellus libero ac justo. Vivamus non quam. In
+    suscipit faucibus urna.
+    </p>
+  </div>
+  <h3><a href="#">Section 3</a></h3>
+  <div>
+    <p>
+    Nam enim risus, molestie et, porta ac, aliquam ac, risus. Quisque lobortis.
+    Phasellus pellentesque purus in massa. Aenean in pede. Phasellus ac libero
+    ac tellus pellentesque semper. Sed ac felis. Sed commodo, magna quis
+    lacinia ornare, quam ante aliquam nisi, eu iaculis leo purus venenatis dui.
+    </p>
+    <ul>
+      <li>List item one</li>
+      <li>List item two</li>
+      <li>List item three</li>
+    </ul>
+  </div>
+  <h3><a href="#">Section 4</a></h3>
+  <div>
+    <p>
+    Cras dictum. Pellentesque habitant morbi tristique senectus et netus
+    et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in
+    faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia
+    mauris vel est.
+    </p>
+    <p>
+    Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus.
+    Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
+    inceptos himenaeos.
+    </p>
+  </div>
+</div>
+
+</div><!-- End demo -->
