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
Eugene Shen
todomvc
Commits
e4786809
Commit
e4786809
authored
Apr 18, 2012
by
Stephen McKamey
Committed by
Sindre Sorhus
Apr 18, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Closes #136: DUEL app
parent
8990986b
Changes
21
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
2752 additions
and
0 deletions
+2752
-0
architecture-examples/duel/.gitignore
architecture-examples/duel/.gitignore
+1
-0
architecture-examples/duel/README.md
architecture-examples/duel/README.md
+37
-0
architecture-examples/duel/pom.xml
architecture-examples/duel/pom.xml
+155
-0
architecture-examples/duel/src/main/resources/views/HomePage.duel
...ture-examples/duel/src/main/resources/views/HomePage.duel
+21
-0
architecture-examples/duel/src/main/resources/views/Stats.duel
...tecture-examples/duel/src/main/resources/views/Stats.duel
+23
-0
architecture-examples/duel/src/main/resources/views/Task.duel
...itecture-examples/duel/src/main/resources/views/Task.duel
+20
-0
architecture-examples/duel/src/main/resources/views/Tasks.duel
...tecture-examples/duel/src/main/resources/views/Tasks.duel
+16
-0
architecture-examples/duel/src/main/resources/views/TodoApp.duel
...cture-examples/duel/src/main/resources/views/TodoApp.duel
+15
-0
architecture-examples/duel/src/main/webapp/WEB-INF/web.xml
architecture-examples/duel/src/main/webapp/WEB-INF/web.xml
+24
-0
architecture-examples/duel/src/main/webapp/css/base.css
architecture-examples/duel/src/main/webapp/css/base.css
+389
-0
architecture-examples/duel/src/main/webapp/css/bg.png
architecture-examples/duel/src/main/webapp/css/bg.png
+0
-0
architecture-examples/duel/src/main/webapp/css/styles.merge
architecture-examples/duel/src/main/webapp/css/styles.merge
+5
-0
architecture-examples/duel/src/main/webapp/js/lib/duel.js
architecture-examples/duel/src/main/webapp/js/lib/duel.js
+1654
-0
architecture-examples/duel/src/main/webapp/js/scripts.merge
architecture-examples/duel/src/main/webapp/js/scripts.merge
+14
-0
architecture-examples/duel/src/main/webapp/js/todos/controller.js
...ture-examples/duel/src/main/webapp/js/todos/controller.js
+169
-0
architecture-examples/duel/src/main/webapp/js/todos/model.js
architecture-examples/duel/src/main/webapp/js/todos/model.js
+137
-0
architecture-examples/duel/staticapp.json
architecture-examples/duel/staticapp.json
+21
-0
architecture-examples/duel/www/cdn/0c975f0bb536597038b63a8cb0d85cff2222b0c9.png
...duel/www/cdn/0c975f0bb536597038b63a8cb0d85cff2222b0c9.png
+0
-0
architecture-examples/duel/www/cdn/1de7392f10ea2465d68b839144090d158ba7730f.js
.../duel/www/cdn/1de7392f10ea2465d68b839144090d158ba7730f.js
+28
-0
architecture-examples/duel/www/cdn/502117dcda6b1a71004e818c348c9de5fc80966a.css
...duel/www/cdn/502117dcda6b1a71004e818c348c9de5fc80966a.css
+1
-0
architecture-examples/duel/www/index.html
architecture-examples/duel/www/index.html
+22
-0
No files found.
architecture-examples/duel/.gitignore
0 → 100644
View file @
e4786809
target/
architecture-examples/duel/README.md
0 → 100644
View file @
e4786809
TodoMVC implemented in DUEL
===========================
Prerequisites
-------------
This example requires
[
Apache Maven 3
](
http://maven.apache.org/download.html
)
to build.
About DUEL
----------
[
DUEL
](
http://duelengine.org
)
is a duel-sided template engine. Views written as markup get precompiled into both
JavaScript (client-side templates) and Java (server-side templates).
The client-side templates are executed as functions directly from JavaScript. The result
can be rendered as either text markup or as DOM objects. This example generates DOM objects for views.
This particular example only uses the server-side templates for debugging. They have been generated into
the
`target/generated-sources/duel/`
directory.
How to build
------------
Run a standard Maven build command in the directory that contains the
`pom.xml`
:
mvn clean package
Maven will download any dependencies, clean out any previously built files, and generate a new static app in the
`www/`
directory.
How to run debug version
------------------------
To run a debug-able version using Tomcat 7 as the web server, use this Maven command:
mvn tomcat7:run
Then navigate your browser to: http://127.0.0.1:8080/
architecture-examples/duel/pom.xml
0 → 100644
View file @
e4786809
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
com.example.todos
</groupId>
<artifactId>
todomvc
</artifactId>
<version>
0.1.0
</version>
<packaging>
war
</packaging>
<name>
TodoMVC
</name>
<description>
TodoMVC example written in DUEL
</description>
<properties>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<resourcesDir>
${project.basedir}/src/main/resources
</resourcesDir>
<staticapps.version>
0.8.5
</staticapps.version>
<merge.version>
0.5.2
</merge.version>
<duel.version>
0.8.2
</duel.version>
<slf4j.version>
1.6.4
</slf4j.version>
<javac.version>
1.6
</javac.version>
<duel.clientPrefix>
todos.views
</duel.clientPrefix>
<duel.serverPrefix>
com.example.todos.views
</duel.serverPrefix>
<duel.sourceDir>
${resourcesDir}/views/
</duel.sourceDir>
<duel.clientPath>
/js/
</duel.clientPath>
<merge.cdnMapFile>
/cdn.properties
</merge.cdnMapFile>
<merge.cdnRoot>
/cdn/
</merge.cdnRoot>
<merge.cdnFiles>
.ico .png .jpg .gif .eot .woff .ttf .svg .svgz
</merge.cdnFiles>
<staticapps.config>
${project.basedir}/staticapp.json
</staticapps.config>
</properties>
<dependencies>
<!-- DUEL runtime -->
<dependency>
<groupId>
org.duelengine
</groupId>
<artifactId>
duel-runtime
</artifactId>
<version>
${duel.version}
</version>
</dependency>
<!-- DUEL staticapps -->
<dependency>
<groupId>
org.duelengine
</groupId>
<artifactId>
duel-staticapps
</artifactId>
<version>
${staticapps.version}
</version>
</dependency>
<!-- SLF4J runtime -->
<dependency>
<groupId>
org.slf4j
</groupId>
<artifactId>
slf4j-jdk14
</artifactId>
<version>
${slf4j.version}
</version>
</dependency>
</dependencies>
<build>
<finalName>
${project.artifactId}
</finalName>
<resources>
<resource>
<directory>
${resourcesDir}
</directory>
<excludes>
<!-- exclude DUEL sources from target output -->
<exclude>
**/*.duel
</exclude>
</excludes>
</resource>
</resources>
<plugins>
<!-- Tomcat 7 config -->
<plugin>
<groupId>
org.apache.tomcat.maven
</groupId>
<artifactId>
tomcat7-maven-plugin
</artifactId>
<version>
2.0-beta-1
</version>
<configuration>
<path>
/
</path>
<port>
8080
</port>
<warSourceDirectory>
${project.build.directory}/${project.build.finalName}/
</warSourceDirectory>
</configuration>
</plugin>
<!-- DUEL Compiler -->
<plugin>
<groupId>
org.duelengine
</groupId>
<artifactId>
duel-maven-plugin
</artifactId>
<version>
${duel.version}
</version>
<executions>
<execution>
<goals>
<goal>
generate
</goal>
</goals>
<configuration>
<clientPrefix>
${duel.clientPrefix}
</clientPrefix>
<serverPrefix>
${duel.serverPrefix}
</serverPrefix>
<inputDir>
${duel.sourceDir}
</inputDir>
<outputClientPath>
${duel.clientPath}
</outputClientPath>
</configuration>
</execution>
</executions>
</plugin>
<!-- Merge Builder -->
<plugin>
<groupId>
org.duelengine
</groupId>
<artifactId>
merge-maven-plugin
</artifactId>
<version>
${merge.version}
</version>
<executions>
<execution>
<goals>
<goal>
merge
</goal>
</goals>
<configuration>
<cdnMapFile>
${merge.cdnMapFile}
</cdnMapFile>
<cdnRoot>
${merge.cdnRoot}
</cdnRoot>
<cdnFiles>
${merge.cdnFiles}
</cdnFiles>
</configuration>
</execution>
</executions>
</plugin>
<!-- Static App Builder -->
<plugin>
<groupId>
org.duelengine
</groupId>
<artifactId>
duel-staticapps-maven-plugin
</artifactId>
<version>
${staticapps.version}
</version>
<executions>
<execution>
<goals>
<goal>
generate
</goal>
</goals>
<configuration>
<configPath>
${staticapps.config}
</configPath>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!-- Java compiler -->
<plugin>
<artifactId>
maven-compiler-plugin
</artifactId>
<configuration>
<source>
${javac.version}
</source>
<target>
${javac.version}
</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
architecture-examples/duel/src/main/resources/views/HomePage.duel
0 → 100755
View file @
e4786809
<view
name=
"HomePage"
>
<!doctype html>
<html
lang=
"en"
>
<head>
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
>
<title>
DUEL
•
TodoMVC
</title>
<link
rel=
"stylesheet"
href=
"/css/styles.merge"
>
<!--[if lt IE 9]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
</head>
<body>
<footer
id=
"info"
>
<p>
Double-click to edit a todo
</p>
<p>
Template by
<a
href=
"http://sindresorhus.com"
>
Sindre Sorhus
</a></p>
<p>
Ported to
<a
href=
"http://duelengine.org"
>
DUEL
</a>
by
<a
href=
"http://mck.me"
>
Stephen McKamey
</a></p>
</footer>
<script
src=
"/js/scripts.merge"
></script>
</body>
</html>
architecture-examples/duel/src/main/resources/views/Stats.duel
0 → 100644
View file @
e4786809
<view name="Stats">
<%-- this footer should hidden by default and shown when there are todos --%>
<footer id="footer" if="<%= data.total %>">
<span id="todo-count"><strong><%= data.active %></strong> <%= (data.active === 1) ? 'item' : 'items' %> left</span>
<%-- TODO: implement routing
<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>
--%>
<button id="clear-completed"
if="<%= data.completed %>"
onclick="<%= todos.actions.clear_click %>">Clear completed (<%= data.completed %>)</button>
</footer>
architecture-examples/duel/src/main/resources/views/Task.duel
0 → 100644
View file @
e4786809
<view name="Task">
<%-- could have embedded in 'tasks' for-loop, but this allows us to add single tasks --%>
<li class="<%= data.completed ? 'complete' : '' %>"
ondblclick="<%= todos.actions.content_dblclick(data.id) %>">
<div class="view">
<input class="toggle" type="checkbox" checked="<%= data.completed %>"
onchange="<%= todos.actions.completed_change(data.id) %>">
<label><%= data.title %></label>
<button class="destroy" onclick="<%= todos.actions.remove_click(data.id) %>"></button>
</div>
<input class="edit" type="text" value="<%= data.title %>"
onblur="<%= todos.actions.edit_blur(data.id) %>"
onkeypress="<%= todos.actions.edit_keypress(data.id) %>">
</li>
architecture-examples/duel/src/main/resources/views/Tasks.duel
0 → 100644
View file @
e4786809
<view name="Tasks">
<%-- this section should hidden by default and shown when there are todos --%>
<section id="main" if="<%= data.tasks.length %>">
<input id="toggle-all" type="checkbox" checked="<%= !data.stats.active %>"
onchange="<%= todos.actions.toggle_change %>">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
<for each="<%= data.tasks %>">
<call view="Task">
</for>
</ul>
</section>
architecture-examples/duel/src/main/resources/views/TodoApp.duel
0 → 100644
View file @
e4786809
<view name="TodoApp">
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<input id="new-todo"
placeholder="What needs to be done?"
autofocus
onblur="<%= todos.actions.add_blur %>"
onkeypress="<%= todos.actions.add_keypress %>">
</header>
<call view="Tasks" data="data" />
<call view="Stats" data="data.stats" />
</section>
architecture-examples/duel/src/main/webapp/WEB-INF/web.xml
0 → 100644
View file @
e4786809
<?xml version="1.0" encoding="UTF-8"?>
<web-app
version=
"2.5"
xmlns=
"http://java.sun.com/xml/ns/javaee"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
>
<servlet>
<servlet-name>
routing-servlet
</servlet-name>
<servlet-class>
org.duelengine.duel.staticapps.RoutingServlet
</servlet-class>
<init-param>
<param-name>
config-path
</param-name>
<param-value>
staticapp.json
</param-value>
</init-param>
<init-param>
<param-name>
dev-mode-override
</param-name>
<param-value>
true
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>
routing-servlet
</servlet-name>
<url-pattern>
/
</url-pattern>
</servlet-mapping>
</web-app>
architecture-examples/duel/src/main/webapp/css/base.css
0 → 100644
View file @
e4786809
html
,
body
{
margin
:
0
;
padding
:
0
;
}
button
{
margin
:
0
;
padding
:
0
;
border
:
0
;
background
:
none
;
font-size
:
100%
;
vertical-align
:
baseline
;
font-family
:
inherit
;
color
:
inherit
;
-webkit-appearance
:
none
;
/*-moz-appearance: none;*/
-ms-appearance
:
none
;
-o-appearance
:
none
;
appearance
:
none
;
}
body
{
font
:
14px
'Helvetica Neue'
,
Helvetica
,
Arial
,
sans-serif
;
line-height
:
1.4em
;
background
:
#eeeeee
url('bg.png')
;
color
:
#4d4d4d
;
width
:
550px
;
margin
:
0
auto
;
-webkit-font-smoothing
:
antialiased
;
-moz-font-smoothing
:
antialiased
;
-ms-font-smoothing
:
antialiased
;
-o-font-smoothing
:
antialiased
;
font-smoothing
:
antialiased
;
}
#todoapp
{
background
:
#fff
;
background
:
rgba
(
255
,
255
,
255
,
0.9
);
margin
:
130px
0
40px
0
;
border
:
1px
solid
#ccc
;
position
:
relative
;
border-top-left-radius
:
2px
;
border-top-right-radius
:
2px
;
box-shadow
:
0
2px
6px
0
rgba
(
0
,
0
,
0
,
0.2
),
0
25px
50px
0
rgba
(
0
,
0
,
0
,
0.15
);
}
#todoapp
:before
{
content
:
''
;
border-left
:
1px
solid
#f5d6d6
;
border-right
:
1px
solid
#f5d6d6
;
width
:
2px
;
position
:
absolute
;
top
:
0
;
left
:
40px
;
height
:
100%
;
}
#todoapp
h1
{
position
:
absolute
;
top
:
-120px
;
width
:
100%
;
font-size
:
70px
;
font-weight
:
bold
;
text-align
:
center
;
color
:
#b3b3b3
;
color
:
rgba
(
255
,
255
,
255
,
0.3
);
text-shadow
:
-1px
-1px
rgba
(
0
,
0
,
0
,
0.2
);
-webkit-text-rendering
:
optimizeLegibility
;
-moz-text-rendering
:
optimizeLegibility
;
-ms-text-rendering
:
optimizeLegibility
;
-o-text-rendering
:
optimizeLegibility
;
text-rendering
:
optimizeLegibility
;
}
#header
{
padding-top
:
15px
;
border-radius
:
inherit
;
}
#todoapp
header
:before
{
content
:
''
;
position
:
absolute
;
top
:
0
;
right
:
0
;
left
:
0
;
height
:
15px
;
z-index
:
2
;
border-bottom
:
1px
solid
#6c615c
;
background
:
#8d7d77
;
background
:
-webkit-gradient
(
linear
,
left
top
,
left
bottom
,
from
(
rgba
(
132
,
110
,
100
,
0.8
)),
to
(
rgba
(
101
,
84
,
76
,
0.8
)));
background
:
-webkit-linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
background
:
-moz-linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
background
:
-o-linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
background
:
-ms-linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
background
:
linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
filter
:
progid
:
DXImageTransform
.
Microsoft
.
gradient
(
GradientType
=
0
,
StartColorStr
=
'#9d8b83'
,
EndColorStr
=
'#847670'
);
border-radius
:
inherit
;
}
#todoapp
input
::-webkit-input-placeholder
{
font-style
:
italic
;
}
#todoapp
input
:-moz-placeholder
{
font-style
:
italic
;
color
:
#a9a9a9
;
}
#new-todo
,
.edit
{
margin
:
0
;
width
:
100%
;
font-size
:
24px
;
font-family
:
inherit
;
line-height
:
1.4em
;
border
:
0
;
outline
:
none
;
color
:
inherit
;
padding
:
6px
;
border
:
1px
solid
#999
;
box-shadow
:
inset
0
-1px
5px
0
rgba
(
0
,
0
,
0
,
0.2
);
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
-ms-box-sizing
:
border-box
;
-o-box-sizing
:
border-box
;
box-sizing
:
border-box
;
-webkit-font-smoothing
:
antialiased
;
-moz-font-smoothing
:
antialiased
;
-ms-font-smoothing
:
antialiased
;
-o-font-smoothing
:
antialiased
;
font-smoothing
:
antialiased
;
}
#new-todo
{
padding
:
16px
16px
16px
60px
;
border
:
none
;
background
:
rgba
(
0
,
0
,
0
,
0.02
);
position
:
relative
;
z-index
:
2
;
box-shadow
:
none
;
}
#main
{
position
:
relative
;
z-index
:
2
;
border-top
:
1px
dotted
#adadad
;
}
label
[
for
=
'toggle-all'
]
{
display
:
none
;
}
#toggle-all
{
position
:
absolute
;
top
:
-42px
;
left
:
12px
;
text-align
:
center
;
-webkit-appearance
:
none
;
/*-moz-appearance: none;*/
-ms-appearance
:
none
;
-o-appearance
:
none
;
appearance
:
none
;
-webkit-transform
:
rotate
(
90deg
);
/*-moz-transform: rotate(90deg);*/
-ms-transform
:
rotate
(
90deg
);
/*-o-transform: rotate(90deg);*/
transform
:
rotate
(
90deg
);
}
#toggle-all
:before
{
content
:
'»'
;
font-size
:
28px
;
color
:
#d9d9d9
;
padding
:
0
25px
7px
;
}
#toggle-all
:checked:before
{
color
:
#737373
;
}
/* Need this ugly hack, since only
WebKit supports styling of inputs */
@media
screen
and
(
-webkit-min-device-pixel-ratio
:
0
)
{
#toggle-all
{
top
:
-52px
;
left
:
-11px
;
}
}
#todo-list
{
margin
:
0
;
padding
:
0
;
list-style
:
none
;
}
#todo-list
li
{
position
:
relative
;
font-size
:
24px
;
border-bottom
:
1px
dotted
#ccc
;
}
#todo-list
li
:last-child
{
border-bottom
:
none
;
}
#todo-list
li
.editing
{
border-bottom
:
none
;
padding
:
0
;
}
#todo-list
li
.editing
.edit
{
display
:
block
;
width
:
506px
;
padding
:
13px
17px
12px
17px
;
margin
:
0
0
0
43px
;
}
#todo-list
li
.editing
.view
{
display
:
none
;
}
#todo-list
li
.toggle
{
text-align
:
center
;
width
:
35px
;
-webkit-appearance
:
none
;
/*-moz-appearance: none;*/
-ms-appearance
:
none
;
-o-appearance
:
none
;
appearance
:
none
;
}
#todo-list
li
.toggle
:after
{
font-size
:
18px
;
content
:
'✔'
;
line-height
:
40px
;
font-size
:
20px
;
color
:
#d9d9d9
;
text-shadow
:
0
-1px
0
#bfbfbf
;
}
#todo-list
li
.toggle
:checked:after
{
color
:
#85ada7
;
text-shadow
:
0
1px
0
#669991
;
bottom
:
1px
;
position
:
relative
;
}
#todo-list
li
label
{
word-break
:
break-word
;
margin
:
20px
15px
;
display
:
inline-block
;
-webkit-transition
:
color
0.4s
;
-moz-transition
:
color
0.4s
;
-ms-transition
:
color
0.4s
;
-o-transition
:
color
0.4s
;
transition
:
color
0.4s
;
}
#todo-list
li
.complete
label
{
color
:
#a9a9a9
;
text-decoration
:
line-through
;
}
#todo-list
li
.destroy
{
display
:
none
;
position
:
absolute
;
top
:
10px
;
right
:
10px
;
width
:
40px
;
height
:
40px
;
font-size
:
22px
;
color
:
#a88a8a
;
-webkit-transition
:
all
0.2s
;
-moz-transition
:
all
0.2s
;
-ms-transition
:
all
0.2s
;
-o-transition
:
all
0.2s
;
transition
:
all
0.2s
;
}
#todo-list
li
.destroy
:hover
{
text-shadow
:
0
0
1px
#000
,
0
0
10px
rgba
(
199
,
107
,
107
,
0.8
);
-webkit-transform
:
scale
(
1.3
);
-moz-transform
:
scale
(
1.3
);
-ms-transform
:
scale
(
1.3
);
-o-transform
:
scale
(
1.3
);
transform
:
scale
(
1.3
);
}
#todo-list
li
.destroy
:after
{
content
:
'✖'
;
}
#todo-list
li
:hover
.destroy
{
display
:
block
;
}
#todo-list
li
.edit
{
display
:
none
;
}
#todo-list
li
.editing
:last-child
{
margin-bottom
:
-1px
;
}
#footer
{
color
:
#777
;
padding
:
0
15px
;
position
:
absolute
;
right
:
0
;
bottom
:
-31px
;
left
:
0
;
z-index
:
1
;
text-align
:
center
;
}
#footer
:before
{
content
:
''
;
position
:
absolute
;
right
:
0
;
bottom
:
31px
;
left
:
0
;
height
:
100px
;
z-index
:
-1
;
box-shadow
:
0
1px
1px
rgba
(
0
,
0
,
0
,
0.3
),
0
6px
0
-3px
rgba
(
255
,
255
,
255
,
0.8
),
0
7px
1px
-3px
rgba
(
0
,
0
,
0
,
0.3
),
0
42px
0
-6px
rgba
(
255
,
255
,
255
,
0.8
),
0
43px
2px
-6px
rgba
(
0
,
0
,
0
,
0.2
);
}
#todo-count
{
float
:
left
;
text-align
:
left
;
}
#filters
{
margin
:
0
;
padding
:
0
;
list-style
:
none
;
position
:
absolute
;
right
:
0
;
left
:
0
;
}
#filters
li
{
display
:
inline
;
}
#filters
li
a
{
color
:
#83756f
;
margin
:
2px
;
text-decoration
:
none
;
}
#filters
li
a
.selected
{
font-weight
:
bold
;
}
#clear-completed
{
float
:
right
;
line-height
:
20px
;
text-decoration
:
none
;
background
:
rgba
(
0
,
0
,
0
,
0.1
);
font-size
:
11px
;
padding
:
0
10px
;
position
:
relative
;
border-radius
:
3px
;
box-shadow
:
0
-1px
0
0
rgba
(
0
,
0
,
0
,
0.2
);
}
#clear-completed
:hover
{
background
:
rgba
(
0
,
0
,
0
,
0.15
);
box-shadow
:
0
-1px
0
0
rgba
(
0
,
0
,
0
,
0.3
);
}
#info
{
margin
:
65px
auto
0
;
color
:
#a6a6a6
;
font-size
:
12px
;
text-shadow
:
0
1px
0
rgba
(
255
,
255
,
255
,
0.7
);
text-align
:
center
;
}
#info
a
{
color
:
inherit
;
}
\ No newline at end of file
architecture-examples/duel/src/main/webapp/css/bg.png
0 → 100644
View file @
e4786809
2.08 KB
architecture-examples/duel/src/main/webapp/css/styles.merge
0 → 100644
View file @
e4786809
# template styles
/css/base.css
# app overrides (not used)
#/css/app.css
\ No newline at end of file
architecture-examples/duel/src/main/webapp/js/lib/duel.js
0 → 100644
View file @
e4786809
This diff is collapsed.
Click to expand it.
architecture-examples/duel/src/main/webapp/js/scripts.merge
0 → 100644
View file @
e4786809
# libraries
/js/lib/duel.js
# model
/js/todos/model.js
# views
/js/todos/views/Stats.js
/js/todos/views/Task.js
/js/todos/views/Tasks.js
/js/todos/views/TodoApp.js
# controller
/js/todos/controller.js
architecture-examples/duel/src/main/webapp/js/todos/controller.js
0 → 100755
View file @
e4786809
var
todos
=
todos
||
{};
(
function
(
todos
,
document
)
{
/*-- private members -------------------------------*/
var
ENTER_KEY
=
13
,
STATS_ID
=
'
footer
'
,
TODOAPP_ID
=
'
todoapp
'
,
TASKS_ID
=
'
main
'
,
LIST_ID
=
'
todo-list
'
,
EDITING_CSS
=
'
editing
'
;
function
getById
(
id
)
{
return
document
.
getElementById
(
id
);
}
function
refreshStats
(
stats
)
{
// get the data
var
data
=
stats
||
todos
.
model
.
stats
();
// build the view
var
view
=
todos
.
views
.
Stats
(
data
).
toDOM
();
// replace old stats
var
old
=
getById
(
STATS_ID
);
if
(
old
)
{
old
.
parentNode
.
replaceChild
(
view
,
old
);
}
else
{
getById
(
TODOAPP_ID
).
appendChild
(
view
);
}
}
function
refreshAll
()
{
// get the data
var
data
=
{
tasks
:
todos
.
model
.
tasks
(),
stats
:
todos
.
model
.
stats
()
};
// build the view
var
view
=
todos
.
views
.
Tasks
(
data
).
toDOM
();
// replace old task list
var
old
=
getById
(
TASKS_ID
);
if
(
old
)
{
old
.
parentNode
.
replaceChild
(
view
,
old
);
}
else
{
getById
(
TODOAPP_ID
).
appendChild
(
view
);
}
refreshStats
(
data
.
stats
);
}
function
add
(
input
)
{
var
title
=
(
input
.
value
||
''
).
trim
();
input
.
value
=
''
;
if
(
!
title
)
{
return
;
}
var
task
=
todos
.
model
.
add
(
title
);
var
list
=
getById
(
LIST_ID
);
if
(
list
)
{
// add new at the top
list
.
appendChild
(
todos
.
views
.
Task
(
task
).
toDOM
()
);
refreshStats
();
}
else
{
refreshAll
();
}
}
function
edit
(
input
,
id
)
{
var
title
=
(
input
.
value
||
''
).
trim
();
input
.
value
=
title
;
if
(
title
)
{
todos
.
model
.
edit
(
id
,
title
);
}
else
{
todos
.
model
.
remove
(
id
);
}
refreshAll
();
}
/*-- export public interface -------------------------------*/
// event handlers
todos
.
actions
=
{
add_blur
:
function
(
e
)
{
add
(
this
);
},
add_keypress
:
function
(
e
)
{
if
(
e
.
keyCode
===
ENTER_KEY
)
{
add
(
this
);
}
},
edit_blur
:
function
(
id
)
{
// create a closure around the ID
return
function
(
e
)
{
edit
(
this
,
id
);
};
},
edit_keypress
:
function
(
id
)
{
// create a closure around the ID
return
function
(
e
)
{
if
(
e
.
keyCode
===
ENTER_KEY
)
{
// just blur so doesn't get triggered twice
this
.
blur
();
}
};
},
remove_click
:
function
(
id
)
{
// create a closure around the ID
return
function
(
e
)
{
todos
.
model
.
remove
(
id
);
refreshAll
();
};
},
clear_click
:
function
()
{
todos
.
model
.
expunge
();
refreshAll
();
},
content_dblclick
:
function
(
id
)
{
// create a closure around the ID
return
function
(
e
)
{
var
li
=
this
;
li
.
className
=
EDITING_CSS
;
li
.
getElementsByTagName
(
'
input
'
)[
1
].
focus
();
};
},
completed_change
:
function
(
id
)
{
// create a closure around the ID
return
function
(
e
)
{
var
checkbox
=
this
;
todos
.
model
.
toggle
(
id
,
checkbox
.
checked
);
refreshAll
();
};
},
toggle_change
:
function
(
e
)
{
var
checkbox
=
this
;
todos
.
model
.
toggleAll
(
checkbox
.
checked
);
refreshAll
();
}
};
/*-- init task list -------------------------------*/
(
function
(
body
)
{
// build out task list
var
view
=
todos
.
views
.
TodoApp
({
tasks
:
todos
.
model
.
tasks
(),
stats
:
todos
.
model
.
stats
()
}).
toDOM
();
// insert at top
body
.
insertBefore
(
view
,
body
.
firstChild
);
})(
document
.
body
);
})(
todos
,
document
);
architecture-examples/duel/src/main/webapp/js/todos/model.js
0 → 100755
View file @
e4786809
var
todos
=
todos
||
{};
(
function
(
todos
,
localStorage
,
KEY
)
{
/*-- private members -------------------------------*/
var
tasks
;
// model uses localStorage as the underlying data store
// this creates a poor man's localStorage polyfill
localStorage
=
localStorage
||
(
function
()
{
var
storage
=
{};
return
{
getItem
:
function
(
key
)
{
return
storage
[
key
];
},
setItem
:
function
(
key
,
value
)
{
storage
[
key
]
=
value
;
}
};
})();
function
create
(
title
,
completed
)
{
return
{
// fast, compact, non-repeating, unique ID: e.g., 'c2wwu0vz.pz4zpvi'
id
:
(
new
Date
().
getTime
()
+
Math
.
random
()).
toString
(
36
),
title
:
title
,
completed
:
!!
completed
};
}
function
save
()
{
// if doesn't support JSON then will be directly stored in polyfill
var
value
=
typeof
JSON
!==
'
undefined
'
?
JSON
.
stringify
(
tasks
)
:
tasks
;
localStorage
.
setItem
(
KEY
,
value
);
}
// initialize storage
var
value
=
localStorage
.
getItem
(
KEY
);
if
(
value
)
{
// if doesn't support JSON then will be directly stored in polyfill
tasks
=
typeof
JSON
!==
'
undefined
'
?
JSON
.
parse
(
value
)
:
value
;
}
else
{
tasks
=
[];
}
/*-- export public interface -------------------------------*/
todos
.
model
=
{
tasks
:
function
()
{
return
tasks
;
},
stats
:
function
()
{
var
stats
=
{
total
:
tasks
.
length
,
active
:
tasks
.
length
,
completed
:
0
};
var
i
=
tasks
.
length
;
while
(
i
--
)
{
if
(
tasks
[
i
].
completed
)
{
stats
.
completed
++
;
}
}
stats
.
active
-=
stats
.
completed
;
return
stats
;
},
add
:
function
(
title
)
{
var
task
=
create
(
title
,
false
);
tasks
.
push
(
task
);
save
();
return
task
;
},
edit
:
function
(
id
,
title
)
{
var
i
=
tasks
.
length
;
while
(
i
--
)
{
if
(
tasks
[
i
].
id
===
id
)
{
tasks
[
i
].
title
=
title
;
save
();
return
;
}
}
},
// toggle completion of task
toggle
:
function
(
id
,
completed
)
{
var
i
=
tasks
.
length
;
while
(
i
--
)
{
if
(
tasks
[
i
].
id
===
id
)
{
tasks
[
i
].
completed
=
completed
;
save
();
return
;
}
}
},
// toggle completion of all tasks
toggleAll
:
function
(
completed
)
{
var
i
=
tasks
.
length
;
while
(
i
--
)
{
tasks
[
i
].
completed
=
completed
;
}
save
();
},
remove
:
function
(
id
)
{
var
i
=
tasks
.
length
;
while
(
i
--
)
{
if
(
tasks
[
i
].
id
===
id
)
{
tasks
.
splice
(
i
,
1
);
save
();
return
;
}
}
},
expunge
:
function
()
{
var
i
=
tasks
.
length
;
while
(
i
--
)
{
if
(
tasks
[
i
].
completed
)
{
tasks
.
splice
(
i
,
1
);
}
}
save
();
}
};
})(
todos
,
window
.
localStorage
,
'
todos-duel
'
);
architecture-examples/duel/staticapp.json
0 → 100644
View file @
e4786809
{
"targetDir"
:
"www/"
,
"sourceDir"
:
"target/todomvc/"
,
"serverPrefix"
:
"com.example.todos.views"
,
"cdnMap"
:
"cdn"
,
"cdnLinksMap"
:
"cdnLinks"
,
"cdnHost"
:
"./"
,
"isDevMode"
:
false
,
"views"
:
{
"index.html"
:
{
"view"
:
"HomePage"
,
"data"
:
{},
"extras"
:
{}
}
},
"files"
:
[
"robots.txt"
,
"favicon.ico"
]
}
architecture-examples/duel/www/cdn/0c975f0bb536597038b63a8cb0d85cff2222b0c9.png
0 → 100644
View file @
e4786809
2.08 KB
architecture-examples/duel/www/cdn/1de7392f10ea2465d68b839144090d158ba7730f.js
0 → 100644
View file @
e4786809
This diff is collapsed.
Click to expand it.
architecture-examples/duel/www/cdn/502117dcda6b1a71004e818c348c9de5fc80966a.css
0 → 100644
View file @
e4786809
html
,
body
{
margin
:
0
;
padding
:
0
;}
button
{
margin
:
0
;
padding
:
0
;
border
:
0
;
background
:
none
;
font-size
:
100%
;
vertical-align
:
baseline
;
font-family
:
inherit
;
color
:
inherit
;
-webkit-appearance
:
none
;
-ms-appearance
:
none
;
-o-appearance
:
none
;
appearance
:
none
;}
body
{
font
:
14px
'Helvetica Neue'
,
Helvetica
,
Arial
,
sans-serif
;
line-height
:
1.4em
;
background
:
#EEE
url("0c975f0bb536597038b63a8cb0d85cff2222b0c9.png")
;
color
:
#4d4d4d
;
width
:
550px
;
margin
:
0
auto
;
-webkit-font-smoothing
:
antialiased
;
-moz-font-smoothing
:
antialiased
;
-ms-font-smoothing
:
antialiased
;
-o-font-smoothing
:
antialiased
;
font-smoothing
:
antialiased
;}
#todoapp
{
background
:
#fff
;
background
:
rgba
(
255
,
255
,
255
,
0.9
);
margin
:
130px
0
40px
0
;
border
:
1px
solid
#ccc
;
position
:
relative
;
border-top-left-radius
:
2px
;
border-top-right-radius
:
2px
;
box-shadow
:
0
2px
6px
0
rgba
(
0
,
0
,
0
,
0.2
),
0
25px
50px
0
rgba
(
0
,
0
,
0
,
0.15
);}
#todoapp
:before
{
content
:
''
;
border-left
:
1px
solid
#f5d6d6
;
border-right
:
1px
solid
#f5d6d6
;
width
:
2px
;
position
:
absolute
;
top
:
0
;
left
:
40px
;
height
:
100%
;}
#todoapp
h1
{
position
:
absolute
;
top
:
-120px
;
width
:
100%
;
font-size
:
70px
;
font-weight
:
bold
;
text-align
:
center
;
color
:
#b3b3b3
;
color
:
rgba
(
255
,
255
,
255
,
0.3
);
text-shadow
:
-1px
-1px
rgba
(
0
,
0
,
0
,
0.2
);
-webkit-text-rendering
:
optimizeLegibility
;
-moz-text-rendering
:
optimizeLegibility
;
-ms-text-rendering
:
optimizeLegibility
;
-o-text-rendering
:
optimizeLegibility
;
text-rendering
:
optimizeLegibility
;}
#header
{
padding-top
:
15px
;
border-radius
:
inherit
;}
#todoapp
header
:before
{
content
:
''
;
position
:
absolute
;
top
:
0
;
right
:
0
;
left
:
0
;
height
:
15px
;
z-index
:
2
;
border-bottom
:
1px
solid
#6c615c
;
background
:
#8d7d77
;
background
:
-webkit-gradient
(
linear
,
left
top
,
left
bottom
,
from
(
rgba
(
132
,
110
,
100
,
0.8
)),
to
(
rgba
(
101
,
84
,
76
,
0.8
)));
background
:
-webkit-linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
background
:
-moz-linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
background
:
-o-linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
background
:
-ms-linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
background
:
linear-gradient
(
top
,
rgba
(
132
,
110
,
100
,
0.8
),
rgba
(
101
,
84
,
76
,
0.8
));
filter
:
progid
:
DXImageTransform
.
Microsoft
.
gradient
(
GradientType
=
0
,
StartColorStr
=
'#9d8b83'
,
EndColorStr
=
'#847670'
);
border-radius
:
inherit
;}
#todoapp
input
::-webkit-input-placeholder
{
font-style
:
italic
;}
#todoapp
input
:-moz-placeholder
{
font-style
:
italic
;
color
:
#a9a9a9
;}
#new-todo
,
.edit
{
margin
:
0
;
width
:
100%
;
font-size
:
24px
;
font-family
:
inherit
;
line-height
:
1.4em
;
border
:
0
;
outline
:
none
;
color
:
inherit
;
padding
:
6px
;
border
:
1px
solid
#999
;
box-shadow
:
inset
0
-1px
5px
0
rgba
(
0
,
0
,
0
,
0.2
);
-webkit-box-sizing
:
border-box
;
-moz-box-sizing
:
border-box
;
-ms-box-sizing
:
border-box
;
-o-box-sizing
:
border-box
;
box-sizing
:
border-box
;
-webkit-font-smoothing
:
antialiased
;
-moz-font-smoothing
:
antialiased
;
-ms-font-smoothing
:
antialiased
;
-o-font-smoothing
:
antialiased
;
font-smoothing
:
antialiased
;}
#new-todo
{
padding
:
16px
16px
16px
60px
;
border
:
none
;
background
:
rgba
(
0
,
0
,
0
,
0.02
);
position
:
relative
;
z-index
:
2
;
box-shadow
:
none
;}
#main
{
position
:
relative
;
z-index
:
2
;
border-top
:
1px
dotted
#adadad
;}
label
[
for
=
'toggle-all'
]
{
display
:
none
;}
#toggle-all
{
position
:
absolute
;
top
:
-42px
;
left
:
12px
;
text-align
:
center
;
-webkit-appearance
:
none
;
-ms-appearance
:
none
;
-o-appearance
:
none
;
appearance
:
none
;
-webkit-transform
:
rotate
(
90deg
);
-ms-transform
:
rotate
(
90deg
);
transform
:
rotate
(
90deg
);}
#toggle-all
:before
{
content
:
'»'
;
font-size
:
28px
;
color
:
#d9d9d9
;
padding
:
0
25px
7px
;}
#toggle-all
:checked:before
{
color
:
#737373
;}
@media
screen
and
(
-webkit-min-device-pixel-ratio
:
0
){
#toggle-all
{
top
:
-52px
;
left
:
-11px
;}}
#todo-list
{
margin
:
0
;
padding
:
0
;
list-style
:
none
;}
#todo-list
li
{
position
:
relative
;
font-size
:
24px
;
border-bottom
:
1px
dotted
#ccc
;}
#todo-list
li
:last-child
{
border-bottom
:
none
;}
#todo-list
li
.editing
{
border-bottom
:
none
;
padding
:
0
;}
#todo-list
li
.editing
.edit
{
display
:
block
;
width
:
506px
;
padding
:
13px
17px
12px
17px
;
margin
:
0
0
0
43px
;}
#todo-list
li
.editing
.view
{
display
:
none
;}
#todo-list
li
.toggle
{
text-align
:
center
;
width
:
35px
;
-webkit-appearance
:
none
;
-ms-appearance
:
none
;
-o-appearance
:
none
;
appearance
:
none
;}
#todo-list
li
.toggle
:after
{
font-size
:
18px
;
content
:
'✔'
;
line-height
:
40px
;
font-size
:
20px
;
color
:
#d9d9d9
;
text-shadow
:
0
-1px
0
#bfbfbf
;}
#todo-list
li
.toggle
:checked:after
{
color
:
#85ada7
;
text-shadow
:
0
1px
0
#669991
;
bottom
:
1px
;
position
:
relative
;}
#todo-list
li
label
{
word-break
:
break-word
;
margin
:
20px
15px
;
display
:
inline-block
;
-webkit-transition
:
color
0.4s
;
-moz-transition
:
color
0.4s
;
-ms-transition
:
color
0.4s
;
-o-transition
:
color
0.4s
;
transition
:
color
0.4s
;}
#todo-list
li
.complete
label
{
color
:
#a9a9a9
;
text-decoration
:
line-through
;}
#todo-list
li
.destroy
{
display
:
none
;
position
:
absolute
;
top
:
10px
;
right
:
10px
;
width
:
40px
;
height
:
40px
;
font-size
:
22px
;
color
:
#a88a8a
;
-webkit-transition
:
all
0.2s
;
-moz-transition
:
all
0.2s
;
-ms-transition
:
all
0.2s
;
-o-transition
:
all
0.2s
;
transition
:
all
0.2s
;}
#todo-list
li
.destroy
:hover
{
text-shadow
:
0
0
1px
#000
,
0
0
10px
rgba
(
199
,
107
,
107
,
0.8
);
-webkit-transform
:
scale
(
1.3
);
-moz-transform
:
scale
(
1.3
);
-ms-transform
:
scale
(
1.3
);
-o-transform
:
scale
(
1.3
);
transform
:
scale
(
1.3
);}
#todo-list
li
.destroy
:after
{
content
:
'✖'
;}
#todo-list
li
:hover
.destroy
{
display
:
block
;}
#todo-list
li
.edit
{
display
:
none
;}
#todo-list
li
.editing
:last-child
{
margin-bottom
:
-1px
;}
#footer
{
color
:
#777
;
padding
:
0
15px
;
position
:
absolute
;
right
:
0
;
bottom
:
-31px
;
left
:
0
;
z-index
:
1
;
text-align
:
center
;}
#footer
:before
{
content
:
''
;
position
:
absolute
;
right
:
0
;
bottom
:
31px
;
left
:
0
;
height
:
100px
;
z-index
:
-1
;
box-shadow
:
0
1px
1px
rgba
(
0
,
0
,
0
,
0.3
),
0
6px
0
-3px
rgba
(
255
,
255
,
255
,
0.8
),
0
7px
1px
-3px
rgba
(
0
,
0
,
0
,
0.3
),
0
42px
0
-6px
rgba
(
255
,
255
,
255
,
0.8
),
0
43px
2px
-6px
rgba
(
0
,
0
,
0
,
0.2
);}
#todo-count
{
float
:
left
;
text-align
:
left
;}
#filters
{
margin
:
0
;
padding
:
0
;
list-style
:
none
;
position
:
absolute
;
right
:
0
;
left
:
0
;}
#filters
li
{
display
:
inline
;}
#filters
li
a
{
color
:
#83756f
;
margin
:
2px
;
text-decoration
:
none
;}
#filters
li
a
.selected
{
font-weight
:
bold
;}
#clear-completed
{
float
:
right
;
line-height
:
20px
;
text-decoration
:
none
;
background
:
rgba
(
0
,
0
,
0
,
0.1
);
font-size
:
11px
;
padding
:
0
10px
;
position
:
relative
;
border-radius
:
3px
;
box-shadow
:
0
-1px
0
0
rgba
(
0
,
0
,
0
,
0.2
);}
#clear-completed
:hover
{
background
:
rgba
(
0
,
0
,
0
,
0.15
);
box-shadow
:
0
-1px
0
0
rgba
(
0
,
0
,
0
,
0.3
);}
#info
{
margin
:
65px
auto
0
;
color
:
#a6a6a6
;
font-size
:
12px
;
text-shadow
:
0
1px
0
rgba
(
255
,
255
,
255
,
0.7
);
text-align
:
center
;}
#info
a
{
color
:
inherit
;}
\ No newline at end of file
architecture-examples/duel/www/index.html
0 → 100644
View file @
e4786809
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"utf-8"
/>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
/>
<title>
DUEL
•
TodoMVC
</title>
<link
rel=
"stylesheet"
href=
"./cdn/502117dcda6b1a71004e818c348c9de5fc80966a.css"
/>
<!--[if lt IE 9]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
</head>
<body>
<footer
id=
"info"
>
<p>
Double-click to edit a todo
</p>
<p>
Template by
<a
href=
"http://sindresorhus.com"
>
Sindre Sorhus
</a></p>
<p>
Ported to
<a
href=
"http://duelengine.org"
>
DUEL
</a>
by
<a
href=
"http://mck.me"
>
Stephen McKamey
</a></p>
</footer>
<script
src=
"./cdn/1de7392f10ea2465d68b839144090d158ba7730f.js"
></script>
</body>
</html>
\ No newline at end of file
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