Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
todomvc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Sven Franck
todomvc
Commits
133d5cca
Commit
133d5cca
authored
Oct 27, 2013
by
Paul Miller
Committed by
Pascal Hartig
Oct 28, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add exoskeleton todomvc.
parent
6a64e8c6
Changes
17
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
3482 additions
and
0 deletions
+3482
-0
labs/architecture-examples/exoskeleton/.gitignore
labs/architecture-examples/exoskeleton/.gitignore
+0
-0
labs/architecture-examples/exoskeleton/bower.json
labs/architecture-examples/exoskeleton/bower.json
+10
-0
labs/architecture-examples/exoskeleton/bower_components/backbone.localStorage/backbone.localStorage.js
...components/backbone.localStorage/backbone.localStorage.js
+244
-0
labs/architecture-examples/exoskeleton/bower_components/exoskeleton/exoskeleton.js
...s/exoskeleton/bower_components/exoskeleton/exoskeleton.js
+1855
-0
labs/architecture-examples/exoskeleton/bower_components/microtemplates/index.js
...ples/exoskeleton/bower_components/microtemplates/index.js
+122
-0
labs/architecture-examples/exoskeleton/bower_components/todomvc-common/base.css
...ples/exoskeleton/bower_components/todomvc-common/base.css
+555
-0
labs/architecture-examples/exoskeleton/bower_components/todomvc-common/base.js
...mples/exoskeleton/bower_components/todomvc-common/base.js
+209
-0
labs/architecture-examples/exoskeleton/bower_components/todomvc-common/bg.png
...amples/exoskeleton/bower_components/todomvc-common/bg.png
+0
-0
labs/architecture-examples/exoskeleton/index.html
labs/architecture-examples/exoskeleton/index.html
+63
-0
labs/architecture-examples/exoskeleton/js/app.js
labs/architecture-examples/exoskeleton/js/app.js
+12
-0
labs/architecture-examples/exoskeleton/js/collections/todos.js
...architecture-examples/exoskeleton/js/collections/todos.js
+50
-0
labs/architecture-examples/exoskeleton/js/models/todo.js
labs/architecture-examples/exoskeleton/js/models/todo.js
+26
-0
labs/architecture-examples/exoskeleton/js/routers/router.js
labs/architecture-examples/exoskeleton/js/routers/router.js
+26
-0
labs/architecture-examples/exoskeleton/js/views/app-view.js
labs/architecture-examples/exoskeleton/js/views/app-view.js
+143
-0
labs/architecture-examples/exoskeleton/js/views/todo-view.js
labs/architecture-examples/exoskeleton/js/views/todo-view.js
+103
-0
labs/architecture-examples/exoskeleton/readme.md
labs/architecture-examples/exoskeleton/readme.md
+33
-0
learn.json
learn.json
+31
-0
No files found.
labs/architecture-examples/exoskeleton/.gitignore
0 → 100644
View file @
133d5cca
labs/architecture-examples/exoskeleton/bower.json
0 → 100644
View file @
133d5cca
{
"name"
:
"todomvc-exoskeleton"
,
"version"
:
"0.0.0"
,
"dependencies"
:
{
"exoskeleton"
:
"~0.3.0"
,
"microtemplates"
:
"~0.1.0"
,
"todomvc-common"
:
"~0.1.4"
,
"backbone.localStorage"
:
"git://github.com/paulmillr/Backbone.localStorage.git#9c225b37bdea4ac21d4b2445fa8962fe74e3175b"
}
}
labs/architecture-examples/exoskeleton/bower_components/backbone.localStorage/backbone.localStorage.js
0 → 100644
View file @
133d5cca
/**
* Backbone localStorage Adapter
* Version 1.1.7
*
* https://github.com/jeromegn/Backbone.localStorage
*/
(
function
(
root
,
factory
)
{
if
(
typeof
exports
===
'
object
'
&&
typeof
require
===
'
function
'
)
{
module
.
exports
=
factory
(
require
(
"
backbone
"
));
}
else
if
(
typeof
define
===
"
function
"
&&
define
.
amd
)
{
// AMD. Register as an anonymous module.
define
([
"
backbone
"
],
function
(
Backbone
)
{
// Use global variables if the locals are undefined.
return
factory
(
Backbone
||
root
.
Backbone
);
});
}
else
{
// RequireJS isn't being used. Assume underscore and backbone are loaded in <script> tags
factory
(
Backbone
);
}
}(
this
,
function
(
Backbone
)
{
// A simple module to replace `Backbone.sync` with *localStorage*-based
// persistence. Models are given GUIDS, and saved into a JSON object. Simple
// as that.
// Hold reference to Underscore.js and Backbone.js in the closure in order
// to make things work even if they are removed from the global namespace
// Generate four random hex digits.
function
S4
()
{
return
(((
1
+
Math
.
random
())
*
0x10000
)
|
0
).
toString
(
16
).
substring
(
1
);
};
// Generate a pseudo-GUID by concatenating random hexadecimal.
function
guid
()
{
return
(
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
());
};
function
contains
(
array
,
item
)
{
var
i
=
array
.
length
;
while
(
i
--
)
if
(
array
[
i
]
===
obj
)
return
true
;
return
false
;
}
function
extend
(
obj
,
props
)
{
for
(
var
key
in
props
)
obj
[
key
]
=
props
[
key
]
return
obj
;
}
// Our Store is represented by a single JS object in *localStorage*. Create it
// with a meaningful name, like the name you'd give a table.
// window.Store is deprectated, use Backbone.LocalStorage instead
Backbone
.
LocalStorage
=
window
.
Store
=
function
(
name
)
{
if
(
!
this
.
localStorage
)
{
throw
"
Backbone.localStorage: Environment does not support localStorage.
"
}
this
.
name
=
name
;
var
store
=
this
.
localStorage
().
getItem
(
this
.
name
);
this
.
records
=
(
store
&&
store
.
split
(
"
,
"
))
||
[];
};
extend
(
Backbone
.
LocalStorage
.
prototype
,
{
// Save the current state of the **Store** to *localStorage*.
save
:
function
()
{
this
.
localStorage
().
setItem
(
this
.
name
,
this
.
records
.
join
(
"
,
"
));
},
// Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
// have an id of it's own.
create
:
function
(
model
)
{
if
(
!
model
.
id
)
{
model
.
id
=
guid
();
model
.
set
(
model
.
idAttribute
,
model
.
id
);
}
this
.
localStorage
().
setItem
(
this
.
name
+
"
-
"
+
model
.
id
,
JSON
.
stringify
(
model
));
this
.
records
.
push
(
model
.
id
.
toString
());
this
.
save
();
return
this
.
find
(
model
);
},
// Update a model by replacing its copy in `this.data`.
update
:
function
(
model
)
{
this
.
localStorage
().
setItem
(
this
.
name
+
"
-
"
+
model
.
id
,
JSON
.
stringify
(
model
));
var
modelId
=
model
.
id
.
toString
();
if
(
!
contains
(
this
.
records
,
modelId
))
{
this
.
records
.
push
(
modelId
);
this
.
save
();
}
return
this
.
find
(
model
);
},
// Retrieve a model from `this.data` by id.
find
:
function
(
model
)
{
return
this
.
jsonData
(
this
.
localStorage
().
getItem
(
this
.
name
+
"
-
"
+
model
.
id
));
},
// Return the array of all models currently in storage.
findAll
:
function
()
{
var
result
=
[];
for
(
var
i
=
0
,
id
,
data
;
i
<
this
.
records
.
length
;
i
++
)
{
id
=
this
.
records
[
i
];
data
=
this
.
jsonData
(
this
.
localStorage
().
getItem
(
this
.
name
+
"
-
"
+
id
));
if
(
data
!=
null
)
result
.
push
(
data
);
}
return
result
;
},
// Delete a model from `this.data`, returning it.
destroy
:
function
(
model
)
{
if
(
model
.
isNew
())
return
false
this
.
localStorage
().
removeItem
(
this
.
name
+
"
-
"
+
model
.
id
);
var
modelId
=
model
.
id
.
toString
();
for
(
var
i
=
0
,
id
;
i
<
this
.
records
.
length
;
i
++
)
{
if
(
this
.
records
[
i
]
===
modelId
)
{
this
.
records
.
splice
(
i
,
1
);
}
}
this
.
save
();
return
model
;
},
localStorage
:
function
()
{
return
localStorage
;
},
// fix for "illegal access" error on Android when JSON.parse is passed null
jsonData
:
function
(
data
)
{
return
data
&&
JSON
.
parse
(
data
);
},
// Clear localStorage for specific collection.
_clear
:
function
()
{
var
local
=
this
.
localStorage
(),
itemRe
=
new
RegExp
(
"
^
"
+
this
.
name
+
"
-
"
);
// Remove id-tracking item (e.g., "foo").
local
.
removeItem
(
this
.
name
);
// Match all data items (e.g., "foo-ID") and remove.
for
(
var
k
in
local
)
{
if
(
itemRe
.
test
(
k
))
{
local
.
removeItem
(
k
);
}
}
this
.
records
.
length
=
0
;
},
// Size of localStorage.
_storageSize
:
function
()
{
return
this
.
localStorage
().
length
;
}
});
// localSync delegate to the model or collection's
// *localStorage* property, which should be an instance of `Store`.
// window.Store.sync and Backbone.localSync is deprecated, use Backbone.LocalStorage.sync instead
Backbone
.
LocalStorage
.
sync
=
window
.
Store
.
sync
=
Backbone
.
localSync
=
function
(
method
,
model
,
options
)
{
var
store
=
model
.
localStorage
||
model
.
collection
.
localStorage
;
var
resp
,
errorMessage
;
//If $ is having Deferred - use it.
var
syncDfd
=
Backbone
.
$
?
(
Backbone
.
$
.
Deferred
&&
Backbone
.
$
.
Deferred
())
:
(
Backbone
.
Deferred
&&
Backbone
.
Deferred
());
try
{
switch
(
method
)
{
case
"
read
"
:
resp
=
model
.
id
!=
undefined
?
store
.
find
(
model
)
:
store
.
findAll
();
break
;
case
"
create
"
:
resp
=
store
.
create
(
model
);
break
;
case
"
update
"
:
resp
=
store
.
update
(
model
);
break
;
case
"
delete
"
:
resp
=
store
.
destroy
(
model
);
break
;
}
}
catch
(
error
)
{
if
(
error
.
code
===
22
&&
store
.
_storageSize
()
===
0
)
errorMessage
=
"
Private browsing is unsupported
"
;
else
errorMessage
=
error
.
message
;
}
if
(
resp
)
{
if
(
options
&&
options
.
success
)
{
if
(
Backbone
.
VERSION
===
"
0.9.10
"
)
{
options
.
success
(
model
,
resp
,
options
);
}
else
{
options
.
success
(
resp
);
}
}
if
(
syncDfd
)
{
syncDfd
.
resolve
(
resp
);
}
}
else
{
errorMessage
=
errorMessage
?
errorMessage
:
"
Record Not Found
"
;
if
(
options
&&
options
.
error
)
if
(
Backbone
.
VERSION
===
"
0.9.10
"
)
{
options
.
error
(
model
,
errorMessage
,
options
);
}
else
{
options
.
error
(
errorMessage
);
}
if
(
syncDfd
)
syncDfd
.
reject
(
errorMessage
);
}
// add compatibility with $.ajax
// always execute callback for success and error
if
(
options
&&
options
.
complete
)
options
.
complete
(
resp
);
return
syncDfd
&&
syncDfd
.
promise
();
};
Backbone
.
ajaxSync
=
Backbone
.
sync
;
Backbone
.
getSyncMethod
=
function
(
model
)
{
if
(
model
.
localStorage
||
(
model
.
collection
&&
model
.
collection
.
localStorage
))
{
return
Backbone
.
localSync
;
}
return
Backbone
.
ajaxSync
;
};
// Override 'Backbone.sync' to default to localSync,
// the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
Backbone
.
sync
=
function
(
method
,
model
,
options
)
{
return
Backbone
.
getSyncMethod
(
model
).
apply
(
this
,
[
method
,
model
,
options
]);
};
return
Backbone
.
LocalStorage
;
}));
labs/architecture-examples/exoskeleton/bower_components/exoskeleton/exoskeleton.js
0 → 100644
View file @
133d5cca
This diff is collapsed.
Click to expand it.
labs/architecture-examples/exoskeleton/bower_components/microtemplates/index.js
0 → 100644
View file @
133d5cca
// Simple JavaScript Templating
// Paul Miller (http://paulmillr.com)
// http://underscorejs.org
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
(
function
(
globals
)
{
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
var
settings
=
{
evaluate
:
/<%
([\s\S]
+
?)
%>/g
,
interpolate
:
/<%=
([\s\S]
+
?)
%>/g
,
escape
:
/<%-
([\s\S]
+
?)
%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var
noMatch
=
/
(
.
)
^/
;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var
escapes
=
{
"
'
"
:
"
'
"
,
'
\\
'
:
'
\\
'
,
'
\r
'
:
'
r
'
,
'
\n
'
:
'
n
'
,
'
\t
'
:
'
t
'
,
'
\
u2028
'
:
'
u2028
'
,
'
\
u2029
'
:
'
u2029
'
};
var
escaper
=
/
\\
|'|
\r
|
\n
|
\t
|
\u
2028|
\u
2029/g
;
// List of HTML entities for escaping.
var
htmlEntities
=
{
'
&
'
:
'
&
'
,
'
<
'
:
'
<
'
,
'
>
'
:
'
>
'
,
'
"
'
:
'
"
'
,
"
'
"
:
'
'
'
};
var
entityRe
=
new
RegExp
(
'
[&<>"
\'
]
'
,
'
g
'
);
var
escapeExpr
=
function
(
string
)
{
if
(
string
==
null
)
return
''
;
return
(
''
+
string
).
replace
(
entityRe
,
function
(
match
)
{
return
htmlEntities
[
match
];
});
};
var
counter
=
0
;
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
var
tmpl
=
function
(
text
,
data
)
{
var
render
;
// Combine delimiters into one regular expression via alternation.
var
matcher
=
new
RegExp
([
(
settings
.
escape
||
noMatch
).
source
,
(
settings
.
interpolate
||
noMatch
).
source
,
(
settings
.
evaluate
||
noMatch
).
source
].
join
(
'
|
'
)
+
'
|$
'
,
'
g
'
);
// Compile the template source, escaping string literals appropriately.
var
index
=
0
;
var
source
=
"
__p+='
"
;
text
.
replace
(
matcher
,
function
(
match
,
escape
,
interpolate
,
evaluate
,
offset
)
{
source
+=
text
.
slice
(
index
,
offset
)
.
replace
(
escaper
,
function
(
match
)
{
return
'
\\
'
+
escapes
[
match
];
});
if
(
escape
)
{
source
+=
"
'+
\n
((__t=(
"
+
escape
+
"
))==null?'':escapeExpr(__t))+
\n
'
"
;
}
if
(
interpolate
)
{
source
+=
"
'+
\n
((__t=(
"
+
interpolate
+
"
))==null?'':__t)+
\n
'
"
;
}
if
(
evaluate
)
{
source
+=
"
';
\n
"
+
evaluate
+
"
\n
__p+='
"
;
}
index
=
offset
+
match
.
length
;
return
match
;
});
source
+=
"
';
\n
"
;
// If a variable is not specified, place data values in local scope.
if
(
!
settings
.
variable
)
source
=
'
with(obj||{}){
\n
'
+
source
+
'
}
\n
'
;
source
=
"
var __t,__p='',__j=Array.prototype.join,
"
+
"
print=function(){__p+=__j.call(arguments,'');};
\n
"
+
source
+
"
return __p;
\n
//# sourceURL=/microtemplates/source[
"
+
counter
++
+
"
]
"
;
try
{
render
=
new
Function
(
settings
.
variable
||
'
obj
'
,
'
escapeExpr
'
,
source
);
}
catch
(
e
)
{
e
.
source
=
source
;
throw
e
;
}
if
(
data
)
return
render
(
data
,
escapeExpr
);
var
template
=
function
(
data
)
{
return
render
.
call
(
this
,
data
,
escapeExpr
);
};
// Provide the compiled function source as a convenience for precompilation.
template
.
source
=
'
function(
'
+
(
settings
.
variable
||
'
obj
'
)
+
'
){
\n
'
+
source
+
'
}
'
;
return
template
;
};
tmpl
.
settings
=
settings
;
if
(
typeof
define
!==
'
undefined
'
&&
define
.
amd
)
{
define
([],
function
()
{
return
tmpl
;
});
// RequireJS
}
else
if
(
typeof
module
!==
'
undefined
'
&&
module
.
exports
)
{
module
.
exports
=
tmpl
;
// CommonJS
}
else
{
globals
.
microtemplate
=
tmpl
;
// <script>
}
})(
this
);
labs/architecture-examples/exoskeleton/bower_components/todomvc-common/base.css
0 → 100644
View file @
133d5cca
This diff is collapsed.
Click to expand it.
labs/architecture-examples/exoskeleton/bower_components/todomvc-common/base.js
0 → 100644
View file @
133d5cca
(
function
()
{
'
use strict
'
;
// Underscore's Template Module
// Courtesy of underscorejs.org
var
_
=
(
function
(
_
)
{
_
.
defaults
=
function
(
object
)
{
if
(
!
object
)
{
return
object
;
}
for
(
var
argsIndex
=
1
,
argsLength
=
arguments
.
length
;
argsIndex
<
argsLength
;
argsIndex
++
)
{
var
iterable
=
arguments
[
argsIndex
];
if
(
iterable
)
{
for
(
var
key
in
iterable
)
{
if
(
object
[
key
]
==
null
)
{
object
[
key
]
=
iterable
[
key
];
}
}
}
}
return
object
;
}
// By default, Underscore uses ERB-style template delimiters, change the
// following template settings to use alternative delimiters.
_
.
templateSettings
=
{
evaluate
:
/<%
([\s\S]
+
?)
%>/g
,
interpolate
:
/<%=
([\s\S]
+
?)
%>/g
,
escape
:
/<%-
([\s\S]
+
?)
%>/g
};
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
var
noMatch
=
/
(
.
)
^/
;
// Certain characters need to be escaped so that they can be put into a
// string literal.
var
escapes
=
{
"
'
"
:
"
'
"
,
'
\\
'
:
'
\\
'
,
'
\r
'
:
'
r
'
,
'
\n
'
:
'
n
'
,
'
\t
'
:
'
t
'
,
'
\
u2028
'
:
'
u2028
'
,
'
\
u2029
'
:
'
u2029
'
};
var
escaper
=
/
\\
|'|
\r
|
\n
|
\t
|
\u
2028|
\u
2029/g
;
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
_
.
template
=
function
(
text
,
data
,
settings
)
{
var
render
;
settings
=
_
.
defaults
({},
settings
,
_
.
templateSettings
);
// Combine delimiters into one regular expression via alternation.
var
matcher
=
new
RegExp
([
(
settings
.
escape
||
noMatch
).
source
,
(
settings
.
interpolate
||
noMatch
).
source
,
(
settings
.
evaluate
||
noMatch
).
source
].
join
(
'
|
'
)
+
'
|$
'
,
'
g
'
);
// Compile the template source, escaping string literals appropriately.
var
index
=
0
;
var
source
=
"
__p+='
"
;
text
.
replace
(
matcher
,
function
(
match
,
escape
,
interpolate
,
evaluate
,
offset
)
{
source
+=
text
.
slice
(
index
,
offset
)
.
replace
(
escaper
,
function
(
match
)
{
return
'
\\
'
+
escapes
[
match
];
});
if
(
escape
)
{
source
+=
"
'+
\n
((__t=(
"
+
escape
+
"
))==null?'':_.escape(__t))+
\n
'
"
;
}
if
(
interpolate
)
{
source
+=
"
'+
\n
((__t=(
"
+
interpolate
+
"
))==null?'':__t)+
\n
'
"
;
}
if
(
evaluate
)
{
source
+=
"
';
\n
"
+
evaluate
+
"
\n
__p+='
"
;
}
index
=
offset
+
match
.
length
;
return
match
;
});
source
+=
"
';
\n
"
;
// If a variable is not specified, place data values in local scope.
if
(
!
settings
.
variable
)
source
=
'
with(obj||{}){
\n
'
+
source
+
'
}
\n
'
;
source
=
"
var __t,__p='',__j=Array.prototype.join,
"
+
"
print=function(){__p+=__j.call(arguments,'');};
\n
"
+
source
+
"
return __p;
\n
"
;
try
{
render
=
new
Function
(
settings
.
variable
||
'
obj
'
,
'
_
'
,
source
);
}
catch
(
e
)
{
e
.
source
=
source
;
throw
e
;
}
if
(
data
)
return
render
(
data
,
_
);
var
template
=
function
(
data
)
{
return
render
.
call
(
this
,
data
,
_
);
};
// Provide the compiled function source as a convenience for precompilation.
template
.
source
=
'
function(
'
+
(
settings
.
variable
||
'
obj
'
)
+
'
){
\n
'
+
source
+
'
}
'
;
return
template
;
};
return
_
;
})({});
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
redirect
()
{
if
(
location
.
hostname
===
'
tastejs.github.io
'
)
{
location
.
href
=
location
.
href
.
replace
(
'
tastejs.github.io/todomvc
'
,
'
todomvc.com
'
);
}
}
function
findRoot
()
{
var
base
;
[
/labs/
,
/
\w
*-examples/
].
forEach
(
function
(
href
)
{
var
match
=
location
.
href
.
match
(
href
);
if
(
!
base
&&
match
)
{
base
=
location
.
href
.
indexOf
(
match
);
}
});
return
location
.
href
.
substr
(
0
,
base
);
}
function
getFile
(
file
,
callback
)
{
if
(
!
location
.
host
)
{
return
console
.
info
(
'
Miss the info bar? Run TodoMVC from a server to avoid a cross-origin error.
'
);
}
var
xhr
=
new
XMLHttpRequest
();
xhr
.
open
(
'
GET
'
,
findRoot
()
+
file
,
true
);
xhr
.
send
();
xhr
.
onload
=
function
()
{
if
(
xhr
.
status
===
200
&&
callback
)
{
callback
(
xhr
.
responseText
);
}
};
}
function
Learn
(
learnJSON
,
config
)
{
if
(
!
(
this
instanceof
Learn
))
{
return
new
Learn
(
learnJSON
,
config
);
}
var
template
,
framework
;
if
(
typeof
learnJSON
!==
'
object
'
)
{
try
{
learnJSON
=
JSON
.
parse
(
learnJSON
);
}
catch
(
e
)
{
return
;
}
}
if
(
config
)
{
template
=
config
.
template
;
framework
=
config
.
framework
;
}
if
(
!
template
&&
learnJSON
.
templates
)
{
template
=
learnJSON
.
templates
.
todomvc
;
}
if
(
!
framework
&&
document
.
querySelector
(
'
[data-framework]
'
))
{
framework
=
document
.
querySelector
(
'
[data-framework]
'
).
getAttribute
(
'
data-framework
'
);
}
if
(
template
&&
learnJSON
[
framework
])
{
this
.
frameworkJSON
=
learnJSON
[
framework
];
this
.
template
=
template
;
this
.
append
();
}
}
Learn
.
prototype
.
append
=
function
()
{
var
aside
=
document
.
createElement
(
'
aside
'
);
aside
.
innerHTML
=
_
.
template
(
this
.
template
,
this
.
frameworkJSON
);
aside
.
className
=
'
learn
'
;
// Localize demo links
var
demoLinks
=
aside
.
querySelectorAll
(
'
.demo-link
'
);
Array
.
prototype
.
forEach
.
call
(
demoLinks
,
function
(
demoLink
)
{
demoLink
.
setAttribute
(
'
href
'
,
findRoot
()
+
demoLink
.
getAttribute
(
'
href
'
));
});
document
.
body
.
className
=
(
document
.
body
.
className
+
'
learn-bar
'
).
trim
();
document
.
body
.
insertAdjacentHTML
(
'
afterBegin
'
,
aside
.
outerHTML
);
};
redirect
();
getFile
(
'
learn.json
'
,
Learn
);
})();
labs/architecture-examples/exoskeleton/bower_components/todomvc-common/bg.png
0 → 100644
View file @
133d5cca
2.08 KB
labs/architecture-examples/exoskeleton/index.html
0 → 100644
View file @
133d5cca
<!doctype html>
<html
lang=
"en"
data-framework=
"exoskeleton"
>
<head>
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
<title>
Exoskeleton.js • TodoMVC
</title>
<link
rel=
"stylesheet"
href=
"bower_components/todomvc-common/base.css"
>
</head>
<body>
<section
id=
"todoapp"
>
<header
id=
"header"
>
<h1>
todos
</h1>
<input
id=
"new-todo"
placeholder=
"What needs to be done?"
autofocus
>
</header>
<section
id=
"main"
>
<input
id=
"toggle-all"
type=
"checkbox"
>
<label
for=
"toggle-all"
>
Mark all as complete
</label>
<ul
id=
"todo-list"
></ul>
</section>
<footer
id=
"footer"
></footer>
</section>
<footer
id=
"info"
>
<p>
Double-click to edit a todo
</p>
<p>
Written by
<a
href=
"https://paulmillr.com"
>
Paul Miller
</a></p>
<p>
Part of
<a
href=
"http://todomvc.com"
>
TodoMVC
</a></p>
</footer>
<script
type=
"text/template"
id=
"item-template"
>
<
div
class
=
"
view
"
>
<
input
class
=
"
toggle
"
type
=
"
checkbox
"
<%=
completed
?
'
checked
'
:
''
%>>
<
label
><%-
title
%><
/label
>
<
button
class
=
"
destroy
"
><
/button
>
<
/div
>
<
input
class
=
"
edit
"
value
=
"
<%- title %>
"
>
</script>
<script
type=
"text/template"
id=
"stats-template"
>
<
span
id
=
"
todo-count
"
><
strong
><%=
remaining
%><
/strong> <%= remaining === 1
?
'item' : 'items' %> left</
span
>
<
ul
id
=
"
filters
"
>
<
li
>
<
a
class
=
"
selected
"
href
=
"
#/
"
>
All
<
/a
>
<
/li
>
<
li
>
<
a
href
=
"
#/active
"
>
Active
<
/a
>
<
/li
>
<
li
>
<
a
href
=
"
#/completed
"
>
Completed
<
/a
>
<
/li
>
<
/ul
>
<%
if
(
completed
)
{
%>
<
button
id
=
"
clear-completed
"
>
Clear
completed
(
<%=
completed
%>
)
<
/button
>
<%
}
%>
</script>
<script
src=
"bower_components/todomvc-common/base.js"
></script>
<script
src=
"bower_components/exoskeleton/exoskeleton.js"
></script>
<script
src=
"bower_components/microtemplates/index.js"
></script>
<script
src=
"bower_components/backbone.localStorage/backbone.localStorage.js"
></script>
<script
src=
"js/models/todo.js"
></script>
<script
src=
"js/collections/todos.js"
></script>
<script
src=
"js/views/todo-view.js"
></script>
<script
src=
"js/views/app-view.js"
></script>
<script
src=
"js/routers/router.js"
></script>
<script
src=
"js/app.js"
></script>
</body>
</html>
labs/architecture-examples/exoskeleton/js/app.js
0 → 100644
View file @
133d5cca
/*global $ */
/*jshint unused:false */
var
app
=
app
||
{};
var
ENTER_KEY
=
13
;
var
ESCAPE_KEY
=
27
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
function
()
{
'
use strict
'
;
// kick things off by creating the `App`
new
app
.
AppView
();
},
false
);
labs/architecture-examples/exoskeleton/js/collections/todos.js
0 → 100644
View file @
133d5cca
/*global Backbone */
var
app
=
app
||
{};
(
function
()
{
'
use strict
'
;
// Todo Collection
// ---------------
// The collection of todos is backed by *localStorage* instead of a remote
// server.
var
Todos
=
Backbone
.
Collection
.
extend
({
// Reference to this collection's model.
model
:
app
.
Todo
,
// Save all of the todo items under the `"todos"` namespace.
localStorage
:
new
Backbone
.
LocalStorage
(
'
todos-exoskeleton
'
),
// Filter down the list of all todo items that are finished.
completed
:
function
()
{
return
this
.
filter
(
function
(
todo
)
{
return
todo
.
get
(
'
completed
'
);
});
},
// Filter down the list to only todo items that are still not finished.
remaining
:
function
()
{
return
this
.
filter
(
function
(
todo
)
{
return
!
todo
.
get
(
'
completed
'
);
});
},
// We keep the Todos in sequential order, despite being saved by unordered
// GUID in the database. This generates the next order number for new items.
nextOrder
:
function
()
{
if
(
!
this
.
length
)
{
return
1
;
}
return
this
.
at
(
this
.
length
-
1
).
get
(
'
order
'
)
+
1
;
},
// Todos are sorted by their original insertion order.
comparator
:
function
(
todo
)
{
return
todo
.
get
(
'
order
'
);
}
});
// Create our global collection of **Todos**.
app
.
todos
=
new
Todos
();
})();
labs/architecture-examples/exoskeleton/js/models/todo.js
0 → 100644
View file @
133d5cca
/*global Backbone */
var
app
=
app
||
{};
(
function
()
{
'
use strict
'
;
// Todo Model
// ----------
// Our basic **Todo** model has `title`, `order`, and `completed` attributes.
app
.
Todo
=
Backbone
.
Model
.
extend
({
// Default attributes for the todo
// and ensure that each todo created has `title` and `completed` keys.
defaults
:
{
title
:
''
,
completed
:
false
},
// Toggle the `completed` state of this todo item.
toggle
:
function
()
{
this
.
save
({
completed
:
!
this
.
get
(
'
completed
'
)
});
}
});
})();
labs/architecture-examples/exoskeleton/js/routers/router.js
0 → 100644
View file @
133d5cca
/*global Backbone */
var
app
=
app
||
{};
(
function
()
{
'
use strict
'
;
// Todo Router
// ----------
var
TodoRouter
=
Backbone
.
Router
.
extend
({
routes
:
{
'
*filter
'
:
'
setFilter
'
},
setFilter
:
function
(
param
)
{
// Set the current filter to be used
app
.
TodoFilter
=
param
||
''
;
// Trigger a collection filter event, causing hiding/unhiding
// of Todo view items
app
.
todos
.
trigger
(
'
filter
'
);
}
});
app
.
TodoRouter
=
new
TodoRouter
();
Backbone
.
history
.
start
();
})();
labs/architecture-examples/exoskeleton/js/views/app-view.js
0 → 100644
View file @
133d5cca
/*global Backbone, microtemplate, ENTER_KEY */
var
app
=
app
||
{};
(
function
()
{
'
use strict
'
;
var
toggleEl
=
function
(
el
,
toggle
)
{
el
.
style
.
display
=
toggle
?
''
:
'
none
'
;
};
// The Application
// ---------------
// Our overall **AppView** is the top-level piece of UI.
app
.
AppView
=
Backbone
.
View
.
extend
({
// Instead of generating a new element, bind to the existing skeleton of
// the App already present in the HTML.
el
:
'
#todoapp
'
,
// Our template for the line of statistics at the bottom of the app.
statsTemplate
:
microtemplate
(
document
.
querySelector
(
'
#stats-template
'
).
innerHTML
),
// Delegated events for creating new items, and clearing completed ones.
events
:
{
'
keypress #new-todo
'
:
'
createOnEnter
'
,
'
click #clear-completed
'
:
'
clearCompleted
'
,
'
click #toggle-all
'
:
'
toggleAllComplete
'
},
// At initialization we bind to the relevant events on the `Todos`
// collection, when items are added or changed. Kick things off by
// loading any preexisting todos that might be saved in *localStorage*.
initialize
:
function
()
{
this
.
allCheckbox
=
this
.
find
(
'
#toggle-all
'
);
this
.
input
=
this
.
find
(
'
#new-todo
'
);
this
.
footer
=
this
.
find
(
'
#footer
'
);
this
.
main
=
this
.
find
(
'
#main
'
);
this
.
listenTo
(
app
.
todos
,
'
add
'
,
this
.
addOne
);
this
.
listenTo
(
app
.
todos
,
'
reset
'
,
this
.
addAll
);
this
.
listenTo
(
app
.
todos
,
'
change:completed
'
,
this
.
filterOne
);
this
.
listenTo
(
app
.
todos
,
'
filter
'
,
this
.
filterAll
);
this
.
listenTo
(
app
.
todos
,
'
all
'
,
this
.
render
);
// Suppresses 'add' events with {reset: true} and prevents the app view
// from being re-rendered for every model. Only renders when the 'reset'
// event is triggered at the end of the fetch.
app
.
todos
.
fetch
({
reset
:
true
});
},
// Re-rendering the App just means refreshing the statistics -- the rest
// of the app doesn't change.
render
:
function
()
{
var
completed
=
app
.
todos
.
completed
().
length
;
var
remaining
=
app
.
todos
.
remaining
().
length
;
var
selector
=
'
[href="#/
'
+
(
app
.
TodoFilter
||
''
)
+
'
"]
'
;
if
(
app
.
todos
.
length
)
{
// TODO
toggleEl
(
this
.
main
,
true
);
toggleEl
(
this
.
footer
,
true
);
this
.
footer
.
innerHTML
=
this
.
statsTemplate
({
completed
:
completed
,
remaining
:
remaining
});
this
.
findAll
(
'
#filters li a
'
).
forEach
(
function
(
el
)
{
el
.
classList
.
remove
(
'
selected
'
);
if
(
Backbone
.
utils
.
matchesSelector
(
el
,
selector
))
{
el
.
classList
.
add
(
'
selected
'
);
}
});
}
else
{
toggleEl
(
this
.
main
,
false
);
toggleEl
(
this
.
footer
,
false
);
}
this
.
allCheckbox
.
checked
=
!
remaining
;
},
// Add a single todo item to the list by creating a view for it, and
// appending its element to the `<ul>`.
addOne
:
function
(
todo
)
{
var
view
=
new
app
.
TodoView
({
model
:
todo
});
document
.
querySelector
(
'
#todo-list
'
).
appendChild
(
view
.
render
().
el
);
},
// Add all items in the **Todos** collection at once.
addAll
:
function
()
{
this
.
find
(
'
#todo-list
'
).
innerHTML
=
''
;
app
.
todos
.
forEach
(
this
.
addOne
,
this
);
},
filterOne
:
function
(
todo
)
{
todo
.
trigger
(
'
visible
'
);
},
filterAll
:
function
()
{
app
.
todos
.
forEach
(
this
.
filterOne
,
this
);
},
// Generate the attributes for a new Todo item.
newAttributes
:
function
()
{
return
{
title
:
this
.
input
.
value
.
trim
(),
order
:
app
.
todos
.
nextOrder
(),
completed
:
false
};
},
// If you hit return in the main input field, create new **Todo** model,
// persisting it to *localStorage*.
createOnEnter
:
function
(
e
)
{
if
(
e
.
which
!==
ENTER_KEY
||
!
this
.
input
.
value
.
trim
())
{
return
;
}
app
.
todos
.
create
(
this
.
newAttributes
());
this
.
input
.
value
=
''
;
},
// Clear all completed todo items, destroying their models.
clearCompleted
:
function
()
{
app
.
todos
.
completed
().
forEach
(
function
(
todo
)
{
todo
.
destroy
();
});
return
false
;
},
toggleAllComplete
:
function
()
{
var
completed
=
this
.
allCheckbox
.
checked
;
app
.
todos
.
forEach
(
function
(
todo
)
{
todo
.
save
({
'
completed
'
:
completed
});
});
}
});
})();
labs/architecture-examples/exoskeleton/js/views/todo-view.js
0 → 100644
View file @
133d5cca
/*global Backbone, microtemplate, ENTER_KEY, ESCAPE_KEY */
var
app
=
app
||
{};
(
function
()
{
'
use strict
'
;
// Todo Item View
// --------------
// The DOM element for a todo item...
app
.
TodoView
=
Backbone
.
View
.
extend
({
//... is a list tag.
tagName
:
'
li
'
,
// Cache the template function for a single item.
template
:
microtemplate
(
document
.
querySelector
(
'
#item-template
'
).
innerHTML
),
// The DOM events specific to an item.
events
:
{
'
click .toggle
'
:
'
toggleCompleted
'
,
'
dblclick label
'
:
'
edit
'
,
'
click .destroy
'
:
'
clear
'
,
// Not keypress since it doesn't work with escape.
'
keyup .edit
'
:
'
handleKey
'
,
// Not blur since it doesn't bubble up.
'
focusout .edit
'
:
'
close
'
},
// The TodoView listens for changes to its model, re-rendering. Since there's
// a one-to-one correspondence between a **Todo** and a **TodoView** in this
// app, we set a direct reference on the model for convenience.
initialize
:
function
()
{
this
.
listenTo
(
this
.
model
,
'
change
'
,
this
.
render
);
this
.
listenTo
(
this
.
model
,
'
destroy
'
,
this
.
remove
);
this
.
listenTo
(
this
.
model
,
'
visible
'
,
this
.
toggleVisible
);
},
// Re-render the titles of the todo item.
render
:
function
()
{
this
.
el
.
innerHTML
=
this
.
template
(
this
.
model
.
toJSON
());
var
method
=
this
.
model
.
get
(
'
completed
'
)
?
'
add
'
:
'
remove
'
;
this
.
el
.
classList
[
method
](
'
completed
'
);
this
.
toggleVisible
();
this
.
input
=
this
.
find
(
'
.edit
'
);
return
this
;
},
toggleVisible
:
function
()
{
this
.
el
.
classList
[
this
.
isHidden
()
?
'
add
'
:
'
remove
'
](
'
hidden
'
);
},
isHidden
:
function
()
{
var
isCompleted
=
this
.
model
.
get
(
'
completed
'
);
return
(
// hidden cases only
(
!
isCompleted
&&
app
.
TodoFilter
===
'
completed
'
)
||
(
isCompleted
&&
app
.
TodoFilter
===
'
active
'
)
);
},
// Toggle the `"completed"` state of the model.
toggleCompleted
:
function
()
{
this
.
model
.
toggle
();
},
// Switch this view into `"editing"` mode, displaying the input field.
edit
:
function
()
{
this
.
el
.
classList
.
add
(
'
editing
'
);
this
.
input
.
focus
();
// Set the selection to the last char.
this
.
input
.
value
=
this
.
input
.
value
;
},
// Close the `"editing"` mode, saving changes to the todo.
close
:
function
(
e
,
discard
)
{
var
value
=
discard
?
this
.
model
.
get
(
'
title
'
)
:
this
.
input
.
value
.
trim
();
this
.
input
.
value
=
value
;
if
(
value
)
{
this
.
model
.
save
({
title
:
value
});
}
else
{
this
.
clear
();
}
this
.
el
.
classList
.
remove
(
'
editing
'
);
},
// If you hit `enter`, we're through editing the item.
// If you hit `escape`, we're saving it with old value.
handleKey
:
function
(
e
)
{
if
(
e
.
which
===
ENTER_KEY
)
{
this
.
close
();
}
else
if
(
e
.
which
===
ESCAPE_KEY
)
{
this
.
close
(
null
,
true
);
}
},
// Remove the item, destroy the model from *localStorage* and delete its view.
clear
:
function
()
{
this
.
model
.
destroy
();
}
});
})();
labs/architecture-examples/exoskeleton/readme.md
0 → 100644
View file @
133d5cca
# Exoskeleton TodoMVC Example
> Exoskeleton is a faster and leaner Backbone for your HTML5 apps.
> It is a [Backbone](http://backbonejs.org) drop-in replacement
> with 100% optional dependencies, is faster, more developer-friendly with
> AMD / Bower / Component support and oriented towards modern browsers.
> _[Exoskeleton - exosjs.com](http://exosjs.com)_
## Learning Exoskeleton
Learning resources are work in progress. Since it is a drop-in replacement,
you can use Backbone docs and links:
The
[
Backbone.js website
](
http://backbonejs.org
)
is a great resource for getting started.
Articles and guides from the community:
*
[
Developing Backbone.js Applications
](
http://addyosmani.github.io/backbone-fundamentals
)
*
[
Collection of tutorials, blog posts, and example sites
](
https://github.com/documentcloud/backbone/wiki/Tutorials%2C-blog-posts-and-example-sites
)
Get help from other Backbone.js users:
*
[
Backbone.js on StackOverflow
](
http://stackoverflow.com/questions/tagged/backbone.js
)
*
[
Exoskeleton on Twitter
](
http://twitter.com/paulmillr
)
## Running
Simply open
`public/index.html`
in your browser to see it in action!
## Credit
This TodoMVC application was created by
[
@paulmillr
](
http://paulmillr.com
)
.
learn.json
View file @
133d5cca
...
...
@@ -873,6 +873,37 @@
}]
}]
},
"exoskeleton"
:
{
"name"
:
"Exoskeleton"
,
"description"
:
"A faster and leaner Backbone for your HTML5 apps."
,
"homepage"
:
"http://exosjs.com"
,
"source_path"
:
[{
"name"
:
"Architecture Example"
,
"url"
:
"labs/architecture-examples/exoskeleton"
}],
"link_groups"
:
[{
"heading"
:
"Official Resources"
,
"links"
:
[{
"name"
:
"Documentation"
,
"url"
:
"http://backbonejs.org"
},
{
"name"
:
"Exoskeleton on GitHub"
,
"url"
:
"https://github.com/paulmillr/exoskeleton"
}]
},
{
"heading"
:
"Community"
,
"links"
:
[{
"name"
:
"Exoskeleton on StackOverflow"
,
"url"
:
"http://stackoverflow.com/questions/tagged/exoskeleton"
},
{
"name"
:
"Backbone on StackOverflow"
,
"url"
:
"http://stackoverflow.com/questions/tagged/backbone.js"
},
{
"name"
:
"Exoskeleton's author on Twitter"
,
"url"
:
"http://twitter.com/paulmillr"
}]
}]
},
"extjs"
:
{
"name"
:
"Ext JS"
,
"description"
:
"Sencha Ext JS is the industry's most powerful desktop application development platform with unparalleled cross-browser compatibility, advanced MVC architecture, plugin-free charting, and modern UI widgets."
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment