Commit 07d0b47c authored by Artem Denysov's avatar Artem Denysov Committed by Sam Saccone

Update marionette.js to v3 (#1676)

* update marionette.js to v3

* update readme

* update name of Mn on main page

* fix code style
parent b3d4c2a8
...@@ -19,3 +19,6 @@ node_modules/backbone ...@@ -19,3 +19,6 @@ node_modules/backbone
node_modules/backbone.localstorage node_modules/backbone.localstorage
!node_modules/backbone.localstorage/backbone.localStorage.js !node_modules/backbone.localstorage/backbone.localStorage.js
node_modules/backbone.radio
!node_modules/backbone.radio/build/backbone.radio.js
...@@ -51,10 +51,10 @@ ...@@ -51,10 +51,10 @@
</div> </div>
<input class="edit" value="<%- title %>"> <input class="edit" value="<%- title %>">
</script> </script>
<script type="text/html" id="template-todoListCompositeView"> <script type="text/html" id="template-todoListView">
<input id="toggle-all" type="checkbox"> <input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label> <label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"></ul> <ul></ul>
</script> </script>
<!-- vendor libraries --> <!-- vendor libraries -->
<script src="node_modules/todomvc-common/base.js"></script> <script src="node_modules/todomvc-common/base.js"></script>
...@@ -62,8 +62,8 @@ ...@@ -62,8 +62,8 @@
<script src="node_modules/underscore/underscore.js"></script> <script src="node_modules/underscore/underscore.js"></script>
<script src="node_modules/backbone/backbone.js"></script> <script src="node_modules/backbone/backbone.js"></script>
<script src="node_modules/backbone.localstorage/backbone.localStorage.js"></script> <script src="node_modules/backbone.localstorage/backbone.localStorage.js"></script>
<script src="node_modules/backbone.marionette/lib/backbone.marionette.js"></script>
<script src="node_modules/backbone.radio/build/backbone.radio.js"></script> <script src="node_modules/backbone.radio/build/backbone.radio.js"></script>
<script src="node_modules/backbone.marionette/lib/backbone.marionette.js"></script>
<!-- application --> <!-- application -->
<script src="js/TodoMVC.Application.js"></script> <script src="js/TodoMVC.Application.js"></script>
<script src="js/TodoMVC.Todos.js"></script> <script src="js/TodoMVC.Todos.js"></script>
......
...@@ -5,7 +5,7 @@ var TodoMVC = TodoMVC || {}; ...@@ -5,7 +5,7 @@ var TodoMVC = TodoMVC || {};
(function () { (function () {
'use strict'; 'use strict';
var TodoApp = Backbone.Marionette.Application.extend({ var TodoApp = Mn.Application.extend({
setRootLayout: function () { setRootLayout: function () {
this.root = new TodoMVC.RootLayout(); this.root = new TodoMVC.RootLayout();
} }
......
...@@ -7,7 +7,7 @@ var TodoMVC = TodoMVC || {}; ...@@ -7,7 +7,7 @@ var TodoMVC = TodoMVC || {};
var filterChannel = Backbone.Radio.channel('filter'); var filterChannel = Backbone.Radio.channel('filter');
TodoMVC.RootLayout = Backbone.Marionette.LayoutView.extend({ TodoMVC.RootLayout = Mn.View.extend({
el: '#todoapp', el: '#todoapp',
...@@ -20,7 +20,7 @@ var TodoMVC = TodoMVC || {}; ...@@ -20,7 +20,7 @@ var TodoMVC = TodoMVC || {};
// Layout Header View // Layout Header View
// ------------------ // ------------------
TodoMVC.HeaderLayout = Backbone.Marionette.ItemView.extend({ TodoMVC.HeaderLayout = Mn.View.extend({
template: '#template-header', template: '#template-header',
...@@ -60,7 +60,7 @@ var TodoMVC = TodoMVC || {}; ...@@ -60,7 +60,7 @@ var TodoMVC = TodoMVC || {};
// Layout Footer View // Layout Footer View
// ------------------ // ------------------
TodoMVC.FooterLayout = Backbone.Marionette.ItemView.extend({ TodoMVC.FooterLayout = Mn.View.extend({
template: '#template-footer', template: '#template-footer',
// UI bindings create cached attributes that // UI bindings create cached attributes that
...@@ -82,7 +82,7 @@ var TodoMVC = TodoMVC || {}; ...@@ -82,7 +82,7 @@ var TodoMVC = TodoMVC || {};
all: 'render' all: 'render'
}, },
templateHelpers: { templateContext: {
activeCountLabel: function () { activeCountLabel: function () {
return (this.activeCount === 1 ? 'item' : 'items') + ' left'; return (this.activeCount === 1 ? 'item' : 'items') + ' left';
} }
......
...@@ -12,7 +12,7 @@ var TodoMVC = TodoMVC || {}; ...@@ -12,7 +12,7 @@ var TodoMVC = TodoMVC || {};
// //
// Handles a single dynamic route to show // Handles a single dynamic route to show
// the active vs complete todo items // the active vs complete todo items
TodoMVC.Router = Backbone.Marionette.AppRouter.extend({ TodoMVC.Router = Mn.AppRouter.extend({
appRoutes: { appRoutes: {
'*filter': 'filterItems' '*filter': 'filterItems'
} }
...@@ -23,7 +23,7 @@ var TodoMVC = TodoMVC || {}; ...@@ -23,7 +23,7 @@ var TodoMVC = TodoMVC || {};
// //
// Control the workflow and logic that exists at the application // Control the workflow and logic that exists at the application
// level, above the implementation detail of views and models // level, above the implementation detail of views and models
TodoMVC.Controller = Backbone.Marionette.Object.extend({ TodoMVC.Controller = Mn.Object.extend({
initialize: function () { initialize: function () {
this.todoList = new TodoMVC.TodoList(); this.todoList = new TodoMVC.TodoList();
......
...@@ -12,7 +12,7 @@ var TodoMVC = TodoMVC || {}; ...@@ -12,7 +12,7 @@ var TodoMVC = TodoMVC || {};
// //
// Display an individual todo item, and respond to changes // Display an individual todo item, and respond to changes
// that are made to the item, including marking completed. // that are made to the item, including marking completed.
TodoMVC.TodoView = Backbone.Marionette.ItemView.extend({ TodoMVC.TodoView = Mn.View.extend({
tagName: 'li', tagName: 'li',
...@@ -81,18 +81,38 @@ var TodoMVC = TodoMVC || {}; ...@@ -81,18 +81,38 @@ var TodoMVC = TodoMVC || {};
} }
}); });
// Item List View // Item List View Body
// -------------- // --------------
// //
// Controls the rendering of the list of items, including the // Controls the rendering of the list of items, including the
// filtering of activs vs completed items for display. // filtering of items for display.
TodoMVC.ListView = Backbone.Marionette.CompositeView.extend({ TodoMVC.ListViewBody = Mn.CollectionView.extend({
tagName: 'ul',
template: '#template-todoListCompositeView', id: 'todo-list',
childView: TodoMVC.TodoView, childView: TodoMVC.TodoView,
childViewContainer: '#todo-list', filter: function (child) {
var filteredOn = filterChannel.request('filterState').get('filter');
return child.matchesFilter(filteredOn);
}
});
// Item List View
// --------------
//
// Manages List View
TodoMVC.ListView = Mn.View.extend({
template: '#template-todoListView',
regions: {
listBody: {
el: 'ul',
replaceElement: true
}
},
ui: { ui: {
toggle: '#toggle-all' toggle: '#toggle-all'
...@@ -111,11 +131,6 @@ var TodoMVC = TodoMVC || {}; ...@@ -111,11 +131,6 @@ var TodoMVC = TodoMVC || {};
this.listenTo(filterChannel.request('filterState'), 'change:filter', this.render, this); this.listenTo(filterChannel.request('filterState'), 'change:filter', this.render, this);
}, },
filter: function (child) {
var filteredOn = filterChannel.request('filterState').get('filter');
return child.matchesFilter(filteredOn);
},
setCheckAllState: function () { setCheckAllState: function () {
function reduceCompleted(left, right) { function reduceCompleted(left, right) {
return left && right.get('completed'); return left && right.get('completed');
...@@ -132,6 +147,12 @@ var TodoMVC = TodoMVC || {}; ...@@ -132,6 +147,12 @@ var TodoMVC = TodoMVC || {};
this.collection.each(function (todo) { this.collection.each(function (todo) {
todo.save({ completed: isChecked }); todo.save({ completed: isChecked });
}); });
},
onRender: function () {
this.showChildView('listBody', new TodoMVC.ListViewBody({
collection: this.collection
}));
} }
}); });
})(); })();
// Backbone.Radio v1.0.2 // Backbone.Radio v2.0.0
(function (global, factory) { (function (global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory(require("underscore"), require("backbone")) : typeof define === "function" && define.amd ? define(["underscore", "backbone"], factory) : global.Backbone.Radio = factory(global._, global.Backbone); typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('underscore'), require('backbone')) :
})(this, function (_, Backbone) { typeof define === 'function' && define.amd ? define(['underscore', 'backbone'], factory) :
"use strict"; (global.Backbone = global.Backbone || {}, global.Backbone.Radio = factory(global._,global.Backbone));
}(this, function (_,Backbone) { 'use strict';
_ = 'default' in _ ? _['default'] : _;
Backbone = 'default' in Backbone ? Backbone['default'] : Backbone;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
};
var previousRadio = Backbone.Radio; var previousRadio = Backbone.Radio;
var Radio = Backbone.Radio = {}; var Radio = Backbone.Radio = {};
Radio.VERSION = "1.0.2"; Radio.VERSION = '2.0.0';
// This allows you to run multiple instances of Radio on the same // This allows you to run multiple instances of Radio on the same
// webapp. After loading the new version, call `noConflict()` to // webapp. After loading the new version, call `noConflict()` to
...@@ -25,7 +36,7 @@ ...@@ -25,7 +36,7 @@
// Format debug text. // Format debug text.
Radio._debugText = function (warning, eventName, channelName) { Radio._debugText = function (warning, eventName, channelName) {
return warning + (channelName ? " on the " + channelName + " channel" : "") + ": \"" + eventName + "\""; return warning + (channelName ? ' on the ' + channelName + ' channel' : '') + ': "' + eventName + '"';
}; };
// This is the method that's called when an unregistered event was called. // This is the method that's called when an unregistered event was called.
...@@ -52,7 +63,7 @@ ...@@ -52,7 +63,7 @@
var results = {}; var results = {};
// Handle event maps. // Handle event maps.
if (typeof name === "object") { if ((typeof name === 'undefined' ? 'undefined' : _typeof(name)) === 'object') {
for (var key in name) { for (var key in name) {
var result = obj[action].apply(obj, [key, name[key]].concat(rest)); var result = obj[action].apply(obj, [key, name[key]].concat(rest));
eventSplitter.test(key) ? _.extend(results, result) : results[key] = result; eventSplitter.test(key) ? _.extend(results, result) : results[key] = result;
...@@ -94,7 +105,7 @@ ...@@ -94,7 +105,7 @@
// A helper used by `off` methods to the handler from the store // A helper used by `off` methods to the handler from the store
function removeHandler(store, name, callback, context) { function removeHandler(store, name, callback, context) {
var event = store[name]; var event = store[name];
if ((!callback || (callback === event.callback || callback === event.callback._callback)) && (!context || context === event.context)) { if ((!callback || callback === event.callback || callback === event.callback._callback) && (!context || context === event.context)) {
delete store[name]; delete store[name];
return true; return true;
} }
...@@ -134,15 +145,18 @@ ...@@ -134,15 +145,18 @@
// This is to produce an identical function in both tuneIn and tuneOut, // This is to produce an identical function in both tuneIn and tuneOut,
// so that Backbone.Events unregisters it. // so that Backbone.Events unregisters it.
function _partial(channelName) { function _partial(channelName) {
return _logs[channelName] || (_logs[channelName] = _.partial(Radio.log, channelName)); return _logs[channelName] || (_logs[channelName] = _.bind(Radio.log, Radio, channelName));
} }
_.extend(Radio, { _.extend(Radio, {
// Log information about the channel and event // Log information about the channel and event
log: function log(channelName, eventName) { log: function log(channelName, eventName) {
var args = _.rest(arguments, 2); if (typeof console === 'undefined') {
console.log("[" + channelName + "] \"" + eventName + "\"", args); return;
}
var args = _.toArray(arguments).slice(2);
console.log('[' + channelName + '] "' + eventName + '"', args);
}, },
// Logs all events on this channel to the console. It sets an // Logs all events on this channel to the console. It sets an
...@@ -151,7 +165,7 @@ ...@@ -151,7 +165,7 @@
tuneIn: function tuneIn(channelName) { tuneIn: function tuneIn(channelName) {
var channel = Radio.channel(channelName); var channel = Radio.channel(channelName);
channel._tunedIn = true; channel._tunedIn = true;
channel.on("all", _partial(channelName)); channel.on('all', _partial(channelName));
return this; return this;
}, },
...@@ -159,7 +173,7 @@ ...@@ -159,7 +173,7 @@
tuneOut: function tuneOut(channelName) { tuneOut: function tuneOut(channelName) {
var channel = Radio.channel(channelName); var channel = Radio.channel(channelName);
channel._tunedIn = false; channel._tunedIn = false;
channel.off("all", _partial(channelName)); channel.off('all', _partial(channelName));
delete _logs[channelName]; delete _logs[channelName];
return this; return this;
} }
...@@ -182,8 +196,8 @@ ...@@ -182,8 +196,8 @@
// Make a request // Make a request
request: function request(name) { request: function request(name) {
var args = _.rest(arguments); var args = _.toArray(arguments).slice(1);
var results = Radio._eventsApi(this, "request", name, args); var results = Radio._eventsApi(this, 'request', name, args);
if (results) { if (results) {
return results; return results;
} }
...@@ -196,25 +210,25 @@ ...@@ -196,25 +210,25 @@
} }
// If the request isn't handled, log it in DEBUG mode and exit // If the request isn't handled, log it in DEBUG mode and exit
if (requests && (requests[name] || requests["default"])) { if (requests && (requests[name] || requests['default'])) {
var handler = requests[name] || requests["default"]; var handler = requests[name] || requests['default'];
args = requests[name] ? args : arguments; args = requests[name] ? args : arguments;
return Radio._callHandler(handler.callback, handler.context, args); return Radio._callHandler(handler.callback, handler.context, args);
} else { } else {
Radio.debugLog("An unhandled request was fired", name, channelName); Radio.debugLog('An unhandled request was fired', name, channelName);
} }
}, },
// Set up a handler for a request // Set up a handler for a request
reply: function reply(name, callback, context) { reply: function reply(name, callback, context) {
if (Radio._eventsApi(this, "reply", name, [callback, context])) { if (Radio._eventsApi(this, 'reply', name, [callback, context])) {
return this; return this;
} }
this._requests || (this._requests = {}); this._requests || (this._requests = {});
if (this._requests[name]) { if (this._requests[name]) {
Radio.debugLog("A request was overwritten", name, this.channelName); Radio.debugLog('A request was overwritten', name, this.channelName);
} }
this._requests[name] = { this._requests[name] = {
...@@ -227,7 +241,7 @@ ...@@ -227,7 +241,7 @@
// Set up a handler that can only be requested once // Set up a handler that can only be requested once
replyOnce: function replyOnce(name, callback, context) { replyOnce: function replyOnce(name, callback, context) {
if (Radio._eventsApi(this, "replyOnce", name, [callback, context])) { if (Radio._eventsApi(this, 'replyOnce', name, [callback, context])) {
return this; return this;
} }
...@@ -243,7 +257,7 @@ ...@@ -243,7 +257,7 @@
// Remove handler(s) // Remove handler(s)
stopReplying: function stopReplying(name, callback, context) { stopReplying: function stopReplying(name, callback, context) {
if (Radio._eventsApi(this, "stopReplying", name)) { if (Radio._eventsApi(this, 'stopReplying', name)) {
return this; return this;
} }
...@@ -251,7 +265,7 @@ ...@@ -251,7 +265,7 @@
if (!name && !callback && !context) { if (!name && !callback && !context) {
delete this._requests; delete this._requests;
} else if (!removeHandlers(this._requests, name, callback, context)) { } else if (!removeHandlers(this._requests, name, callback, context)) {
Radio.debugLog("Attempted to remove the unregistered request", name, this.channelName); Radio.debugLog('Attempted to remove the unregistered request', name, this.channelName);
} }
return this; return this;
...@@ -269,7 +283,7 @@ ...@@ -269,7 +283,7 @@
Radio.channel = function (channelName) { Radio.channel = function (channelName) {
if (!channelName) { if (!channelName) {
throw new Error("You must provide a name for the channel."); throw new Error('You must provide a name for the channel.');
} }
if (Radio._channels[channelName]) { if (Radio._channels[channelName]) {
...@@ -310,14 +324,13 @@ ...@@ -310,14 +324,13 @@
* *
*/ */
var channel, var channel;
args, var args;
systems = [Backbone.Events, Radio.Commands, Radio.Requests]; var systems = [Backbone.Events, Radio.Requests];
_.each(systems, function (system) { _.each(systems, function (system) {
_.each(system, function (method, methodName) { _.each(system, function (method, methodName) {
Radio[methodName] = function (channelName) { Radio[methodName] = function (channelName) {
args = _.rest(arguments); args = _.toArray(arguments).slice(1);
channel = this.channel(channelName); channel = this.channel(channelName);
return channel[methodName].apply(channel, args); return channel[methodName].apply(channel, args);
}; };
...@@ -326,11 +339,12 @@ ...@@ -326,11 +339,12 @@
Radio.reset = function (channelName) { Radio.reset = function (channelName) {
var channels = !channelName ? this._channels : [this._channels[channelName]]; var channels = !channelName ? this._channels : [this._channels[channelName]];
_.invoke(channels, "reset"); _.each(channels, function (channel) {
channel.reset();
});
}; };
var backbone_radio = Radio; return Radio;
return backbone_radio; }));
});
//# sourceMappingURL=./backbone.radio.js.map //# sourceMappingURL=./backbone.radio.js.map
\ No newline at end of file
...@@ -197,8 +197,8 @@ label[for='toggle-all'] { ...@@ -197,8 +197,8 @@ label[for='toggle-all'] {
} }
#todo-list li label { #todo-list li label {
white-space: pre-line; white-space: pre;
word-break: break-all; word-break: break-word;
padding: 15px 60px 15px 15px; padding: 15px 60px 15px 15px;
margin-left: 45px; margin-left: 45px;
display: block; display: block;
......
...@@ -114,7 +114,12 @@ ...@@ -114,7 +114,12 @@
})({}); })({});
if (location.hostname === 'todomvc.com') { if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-31081062-1', 'auto');
ga('send', 'pageview');
} }
/* jshint ignore:end */ /* jshint ignore:end */
...@@ -228,7 +233,7 @@ ...@@ -228,7 +233,7 @@
xhr.onload = function (e) { xhr.onload = function (e) {
var parsedResponse = JSON.parse(e.target.responseText); var parsedResponse = JSON.parse(e.target.responseText);
if (parsedResponse instanceof Array) { if (parsedResponse instanceof Array) {
var count = parsedResponse.length var count = parsedResponse.length;
if (count !== 0) { if (count !== 0) {
issueLink.innerHTML = 'This app has ' + count + ' open issues'; issueLink.innerHTML = 'This app has ' + count + ' open issues';
document.getElementById('issue-count').style.display = 'inline'; document.getElementById('issue-count').style.display = 'inline';
......
{ {
"private": true, "private": true,
"dependencies": { "dependencies": {
"backbone": "^1.1.2", "backbone": "^1.3.3",
"backbone.localstorage": "^1.1.6", "backbone.localstorage": "^1.1.6",
"backbone.marionette": "^2.4.1", "backbone.marionette": "^3.0.0",
"backbone.radio": "^1.0.1", "backbone.radio": "^2.0.0",
"jquery": "^1.11.2", "jquery": "^1.11.2",
"todomvc-app-css": "^1.0.1", "todomvc-app-css": "^1.0.1",
"todomvc-common": "^1.0.1", "todomvc-common": "^1.0.1",
......
...@@ -11,16 +11,16 @@ The [Backbone.Marionette website](http://marionettejs.com) is a great resource f ...@@ -11,16 +11,16 @@ The [Backbone.Marionette website](http://marionettejs.com) is a great resource f
Here are some links you may find helpful: Here are some links you may find helpful:
* [API Reference](https://github.com/marionettejs/backbone.marionette/tree/master/docs) * [API Reference](http://marionettejs.com/docs/current/)
* [Applications built with Backbone.Marionette](https://github.com/marionettejs/backbone.marionette/wiki/Projects-and-websites-using-marionette) * [Additional Marionette Resources](http://marionettejs.com/additional-resources/)
* [Introduction to Composite JavaScript Apps](https://github.com/marionettejs/backbone.marionette/wiki/Introduction-to-composite-javascript-apps)
* [FAQ](https://github.com/marionettejs/backbone.marionette/wiki#frequently-asked-questions)
* [Backbone.Marionette on GitHub](https://github.com/marionettejs/backbone.marionette) * [Backbone.Marionette on GitHub](https://github.com/marionettejs/backbone.marionette)
Articles and guides from the community: Articles and guides from the community:
* [A Thorough Introduction to Backbone.Marionette](http://coding.smashingmagazine.com/2013/02/11/introduction-backbone-marionette) * [A Thorough Introduction to Backbone.Marionette](http://coding.smashingmagazine.com/2013/02/11/introduction-backbone-marionette)
* [Backbone Marionette: Better Backbone Apps](http://www.joezimjs.com/javascript/backbone-marionette-better-backbone-apps) * [Backbone Marionette: Better Backbone Apps](http://www.joezimjs.com/javascript/backbone-marionette-better-backbone-apps)
* [Marionette Guides](https://www.gitbook.com/book/marionette/marionette-guides/details)
* [Marionette.js v3. Getting started with new version](http://blog.marionettejs.com/2016/08/23/marionette-v3/index.html)
Get help from other Backbone.Marionette users: Get help from other Backbone.Marionette users:
...@@ -32,4 +32,4 @@ _If you have other helpful links to share, or find any of the links above no lon ...@@ -32,4 +32,4 @@ _If you have other helpful links to share, or find any of the links above no lon
## Implementation ## Implementation
This implementation of the application uses Marionette's module system. Variations using RequireJS and a more classic approach to JavaScript modules [are also available here](https://github.com/marionettejs/backbone.marionette/wiki/Projects-and-websites-using-marionette). * [Simple setups with different build tools](https://github.com/marionettejs/marionette-integrations)
\ No newline at end of file
...@@ -121,7 +121,7 @@ ...@@ -121,7 +121,7 @@
<a href="examples/vue/" data-source="http://vuejs.org" data-content="Vue.js provides the benefits of MVVM data binding and a composable component system with an extremely simple and flexible API.">Vue.js</a> <a href="examples/vue/" data-source="http://vuejs.org" data-content="Vue.js provides the benefits of MVVM data binding and a composable component system with an extremely simple and flexible API.">Vue.js</a>
</li> </li>
<li class="routing"> <li class="routing">
<a href="examples/backbone_marionette/" data-source="http://marionettejs.com" data-content="Backbone.Marionette is a composite application library for Backbone.js that aims to simplify the construction of large scale JavaScript applications.">MarionetteJS</a> <a href="examples/backbone_marionette/" data-source="http://marionettejs.com" data-content="Backbone.Marionette is a composite application library for Backbone.js that aims to simplify the construction of large scale JavaScript applications.">Marionette.js</a>
</li> </li>
<li class="routing"> <li class="routing">
<a href="examples/troopjs_require/" data-source="https://github.com/troopjs/" data-content="TroopJS attempts to package popular front-end technologies and bind them with minimal effort for the developer. It includes jQuery for DOM manipulation, When.js for promises, RequireJS for modularity and Has.js for feature detection. On top, it includes Pub/Sub support, templating, weaving (widgets to DOM) and auto-wiring.">TroopJS + RequireJS</a> <a href="examples/troopjs_require/" data-source="https://github.com/troopjs/" data-content="TroopJS attempts to package popular front-end technologies and bind them with minimal effort for the developer. It includes jQuery for DOM manipulation, When.js for promises, RequireJS for modularity and Has.js for feature detection. On top, it includes Pub/Sub support, templating, weaving (widgets to DOM) and auto-wiring.">TroopJS + RequireJS</a>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment