diff --git a/index.html b/index.html
index e79e5760a8..75d7a2eea9 100644
--- a/index.html
+++ b/index.html
@@ -260,7 +260,7 @@
Compare these to a non-framework implementation
Vanilla ES6
- jQuery
+ jQuery
diff --git a/updates/jquery/.gitignore b/updates/jquery/.gitignore
new file mode 100644
index 0000000000..03e05e4c07
--- /dev/null
+++ b/updates/jquery/.gitignore
@@ -0,0 +1,2 @@
+.DS_Store
+/node_modules
diff --git a/updates/jquery/README.md b/updates/jquery/README.md
new file mode 100644
index 0000000000..a42ecb9187
--- /dev/null
+++ b/updates/jquery/README.md
@@ -0,0 +1,41 @@
+# TodoMVC: jQuery
+## Description
+
+This application uses jQuery (3.6.3) to implement a todo application.
+
+jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript.
+
+[jQuery.com](https://jquery.com/)
+
+## Implementation details
+
+In contrast to mv(*) patterns, this implementation keeps display, state and app logic all within one file.
+Many apps that utilize jQuery tend to keep most or all aspects within a single file for simplicity.
+
+## Build Steps
+
+A simple build script copies all necessary files to a `dist` folder.
+It does not rely on compilers or transpilers and serves raw html, css and js files to the user.
+
+```
+npm run build
+```
+
+## Requirements
+
+The only requirement is an installation of Node, to be able to install dependencies and run scripts to serve a local server.
+
+```
+* Node (min version: 18.13.0)
+* NPM (min version: 8.19.3)
+```
+
+## Local preview
+
+```
+terminal:
+1. npm install
+2. npm run dev
+browser:
+1. http://localhost:7001/
+```
diff --git a/updates/jquery/dist/app.css b/updates/jquery/dist/app.css
new file mode 100644
index 0000000000..21a72cb1c1
--- /dev/null
+++ b/updates/jquery/dist/app.css
@@ -0,0 +1,4 @@
+#main,
+#footer {
+ display: none;
+}
diff --git a/updates/jquery/dist/app.js b/updates/jquery/dist/app.js
new file mode 100644
index 0000000000..d310b9adca
--- /dev/null
+++ b/updates/jquery/dist/app.js
@@ -0,0 +1,196 @@
+/*global jQuery, Handlebars, Router */
+jQuery(function ($) {
+ 'use strict';
+
+ Handlebars.registerHelper('eq', function (a, b, options) {
+ return a === b ? options.fn(this) : options.inverse(this);
+ });
+
+ var util = {
+ uuid: function () {
+ /*jshint bitwise:false */
+ var i, random;
+ var uuid = '';
+
+ for (i = 0; i < 32; i++) {
+ random = Math.random() * 16 | 0;
+ if (i === 8 || i === 12 || i === 16 || i === 20) {
+ uuid += '-';
+ }
+ uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16);
+ }
+
+ return uuid;
+ },
+ pluralize: function (count, word) {
+ return count === 1 ? word : word + 's';
+ },
+ store: function (namespace, data) {
+ return [];
+ }
+ };
+
+ var App = {
+ ENTER_KEY: 13,
+ ESCAPE_KEY: 27,
+ init: function () {
+ this.todos = util.store('todos-jquery');
+ this.todoTemplate = Handlebars.compile($('#todo-template').html());
+ this.footerTemplate = Handlebars.compile($('#footer-template').html());
+ this.bindEvents();
+
+ new Router({
+ '/:filter': function (filter) {
+ this.filter = filter;
+ this.render();
+ }.bind(this)
+ }).init('/all');
+
+ var dummyNodeToNotifyAppIsReady = document.createElement('div');
+ dummyNodeToNotifyAppIsReady.id = 'appIsReady';
+ document.body.appendChild(dummyNodeToNotifyAppIsReady);
+ },
+ bindEvents: function () {
+ $('#new-todo').on('keyup', this.create.bind(this));
+ $('#toggle-all').on('change', this.toggleAll.bind(this));
+ $('#footer').on('click', '.clear-completed', this.destroyCompleted.bind(this));
+ $('#todo-list')
+ .on('change', '.toggle', this.toggle.bind(this))
+ .on('dblclick', 'label', this.edit.bind(this))
+ .on('keyup', '.edit', this.editKeyup.bind(this))
+ .on('focusout', '.edit', this.update.bind(this))
+ .on('click', '.destroy', this.destroy.bind(this));
+ },
+ render: function () {
+ var todos = this.getFilteredTodos();
+ $('#todo-list').html(this.todoTemplate(todos));
+ $('#main').toggle(todos.length > 0);
+ $('#toggle-all').prop('checked', this.getActiveTodos().length === 0);
+ this.renderFooter();
+ $('#new-todo').focus();
+ util.store('todos-jquery', this.todos);
+ },
+ renderFooter: function () {
+ var todoCount = this.todos.length;
+ var activeTodoCount = this.getActiveTodos().length;
+ var template = this.footerTemplate({
+ activeTodoCount: activeTodoCount,
+ activeTodoWord: util.pluralize(activeTodoCount, 'item'),
+ completedTodos: todoCount - activeTodoCount,
+ filter: this.filter
+ });
+
+ $('#footer').toggle(todoCount > 0).html(template);
+ },
+ toggleAll: function (e) {
+ var isChecked = $(e.target).prop('checked');
+
+ this.todos.forEach(function (todo) {
+ todo.completed = isChecked;
+ });
+
+ this.render();
+ },
+ getActiveTodos: function () {
+ return this.todos.filter(function (todo) {
+ return !todo.completed;
+ });
+ },
+ getCompletedTodos: function () {
+ return this.todos.filter(function (todo) {
+ return todo.completed;
+ });
+ },
+ getFilteredTodos: function () {
+ if (this.filter === 'active') {
+ return this.getActiveTodos();
+ }
+
+ if (this.filter === 'completed') {
+ return this.getCompletedTodos();
+ }
+
+ return this.todos;
+ },
+ destroyCompleted: function () {
+ this.todos = this.getActiveTodos();
+ this.filter = 'all';
+ this.render();
+ },
+ // accepts an element from inside the `.item` div and
+ // returns the corresponding index in the `todos` array
+ indexFromEl: function (el) {
+ var id = $(el).closest('li').data('id');
+ var todos = this.todos;
+ var i = todos.length;
+
+ while (i--) {
+ if (todos[i].id === id) {
+ return i;
+ }
+ }
+ },
+ create: function (e) {
+ var $input = $(e.target);
+ var val = $.trim($input.val());
+
+ if (e.which !== this.ENTER_KEY || !val) {
+ return;
+ }
+
+ this.todos.push({
+ id: util.uuid(),
+ title: val,
+ completed: false
+ });
+
+ $input.val('');
+
+ this.render();
+ },
+ toggle: function (e) {
+ var i = this.indexFromEl(e.target);
+ this.todos[i].completed = !this.todos[i].completed;
+ this.render();
+ },
+ edit: function (e) {
+ var $input = $(e.target).closest('li').addClass('editing').find('.edit');
+ const title = $(e.target).text();
+ $input.trigger("focus").val("").val(title);
+ },
+ editKeyup: function (e) {
+ if (e.which === this.ENTER_KEY) {
+ e.target.blur();
+ }
+
+ if (e.which === this.ESCAPE_KEY) {
+ $(e.target).data('abort', true).blur();
+ }
+ },
+ update: function (e) {
+ var el = e.target;
+ var $el = $(el);
+ var val = $el.val().trim();
+
+ if (!val) {
+ this.destroy(e);
+ return;
+ }
+
+ if ($el.data('abort')) {
+ $el.data('abort', false);
+ } else {
+ this.todos[this.indexFromEl(el)].title = val;
+ }
+
+ this.render();
+ },
+ destroy: function (e) {
+ this.todos.splice(this.indexFromEl(e.target), 1);
+ this.render();
+ }
+ };
+
+ window.app = App;
+ window.app.init();
+});
diff --git a/updates/jquery/dist/base.css b/updates/jquery/dist/base.css
new file mode 100644
index 0000000000..da65968a73
--- /dev/null
+++ b/updates/jquery/dist/base.css
@@ -0,0 +1,141 @@
+hr {
+ margin: 20px 0;
+ border: 0;
+ border-top: 1px dashed #c5c5c5;
+ border-bottom: 1px dashed #f7f7f7;
+}
+
+.learn a {
+ font-weight: normal;
+ text-decoration: none;
+ color: #b83f45;
+}
+
+.learn a:hover {
+ text-decoration: underline;
+ color: #787e7e;
+}
+
+.learn h3,
+.learn h4,
+.learn h5 {
+ margin: 10px 0;
+ font-weight: 500;
+ line-height: 1.2;
+ color: #000;
+}
+
+.learn h3 {
+ font-size: 24px;
+}
+
+.learn h4 {
+ font-size: 18px;
+}
+
+.learn h5 {
+ margin-bottom: 0;
+ font-size: 14px;
+}
+
+.learn ul {
+ padding: 0;
+ margin: 0 0 30px 25px;
+}
+
+.learn li {
+ line-height: 20px;
+}
+
+.learn p {
+ font-size: 15px;
+ font-weight: 300;
+ line-height: 1.3;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+#issue-count {
+ display: none;
+}
+
+.quote {
+ border: none;
+ margin: 20px 0 60px 0;
+}
+
+.quote p {
+ font-style: italic;
+}
+
+.quote p:before {
+ content: '“';
+ font-size: 50px;
+ opacity: .15;
+ position: absolute;
+ top: -20px;
+ left: 3px;
+}
+
+.quote p:after {
+ content: '”';
+ font-size: 50px;
+ opacity: .15;
+ position: absolute;
+ bottom: -42px;
+ right: 3px;
+}
+
+.quote footer {
+ position: absolute;
+ bottom: -40px;
+ right: 0;
+}
+
+.quote footer img {
+ border-radius: 3px;
+}
+
+.quote footer a {
+ margin-left: 5px;
+ vertical-align: middle;
+}
+
+.speech-bubble {
+ position: relative;
+ padding: 10px;
+ background: rgba(0, 0, 0, .04);
+ border-radius: 5px;
+}
+
+.speech-bubble:after {
+ content: '';
+ position: absolute;
+ top: 100%;
+ right: 30px;
+ border: 13px solid transparent;
+ border-top-color: rgba(0, 0, 0, .04);
+}
+
+.learn-bar > .learn {
+ position: absolute;
+ width: 272px;
+ top: 8px;
+ left: -300px;
+ padding: 10px;
+ border-radius: 5px;
+ background-color: rgba(255, 255, 255, .6);
+ transition-property: left;
+ transition-duration: 500ms;
+}
+
+@media (min-width: 899px) {
+ .learn-bar {
+ width: auto;
+ padding-left: 300px;
+ }
+
+ .learn-bar > .learn {
+ left: 8px;
+ }
+}
diff --git a/updates/jquery/dist/director.min.js b/updates/jquery/dist/director.min.js
new file mode 100644
index 0000000000..55a8e64989
--- /dev/null
+++ b/updates/jquery/dist/director.min.js
@@ -0,0 +1,7 @@
+
+
+//
+// Generated on Fri Dec 27 2013 12:02:11 GMT-0500 (EST) by Nodejitsu, Inc (Using Codesurgeon).
+// Version 1.2.2
+//
+(function(a){function k(a,b,c,d){var e=0,f=0,g=0,c=(c||"(").toString(),d=(d||")").toString(),h;for(h=0;hi.indexOf(d,e)||~i.indexOf(c,e)&&!~i.indexOf(d,e)||!~i.indexOf(c,e)&&~i.indexOf(d,e)){f=i.indexOf(c,e),g=i.indexOf(d,e);if(~f&&!~g||!~f&&~g){var j=a.slice(0,(h||1)+1).join(b);a=[j].concat(a.slice((h||1)+1))}e=(g>f?g:f)+1,h=0}else e=0}return a}function j(a,b){var c,d=0,e="";while(c=a.substr(d).match(/[^\w\d\- %@&]*\*[^\w\d\- %@&]*/))d=c.index+c[0].length,c[0]=c[0].replace(/^\*/,"([_.()!\\ %@&a-zA-Z0-9-]+)"),e+=a.substr(0,c.index)+c[0];a=e+=a.substr(d);var f=a.match(/:([^\/]+)/ig),g,h;if(f){h=f.length;for(var j=0;j7))this.history===!0?setTimeout(function(){window.onpopstate=d},500):window.onhashchange=d,this.mode="modern";else{var f=document.createElement("iframe");f.id="state-frame",f.style.display="none",document.body.appendChild(f),this.writeFrame(""),"onpropertychange"in document&&"attachEvent"in document&&document.attachEvent("onpropertychange",function(){event.propertyName==="location"&&c.check()}),window.setInterval(function(){c.check()},50),this.onHashChanged=d,this.mode="legacy"}e.listeners.push(a);return this.mode},destroy:function(a){if(!!e&&!!e.listeners){var b=e.listeners;for(var c=b.length-1;c>=0;c--)b[c]===a&&b.splice(c,1)}},setHash:function(a){this.mode==="legacy"&&this.writeFrame(a),this.history===!0?(window.history.pushState({},document.title,a),this.fire()):b.hash=a[0]==="/"?a:"/"+a;return this},writeFrame:function(a){var b=document.getElementById("state-frame"),c=b.contentDocument||b.contentWindow.document;c.open(),c.write("
+
+
+
+
+
+
+