Commit 07274e75 authored by Colin Eberhardt's avatar Colin Eberhardt

Further whitespace tidyup

Fixed whitespace issues

Added routing
Fixed bug, CSS class 'done' applied to cells should have been 'completed'
parent 48e183af
#todo-count span.word {
font-weight: normal;
/* The CSS that is common to all TodoMVC implementations, base.css, styles the selected routing filter using the
following selector:
#filters li a.selected
In the GWT implementation, a Hyperlink widget is used for the routing filters. This widget allows you to
specify a history - and will handle the clicks accordingly. The HTML for this widget is as follows:
<div><a ...></a></div>
Where the 'div' element represents the hyperlink GWT widget. This results in the following GWT
specific style. */
#filters li div.selected a {
font-weight: bold;
}
/* The GWT TodoMVC uses a CellList - a framework widget for rendering a list of cells - to
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
function gwttodo(){var M='',dc='\n-',ub='" for "gwt:onLoadErrorFn"',sb='" for "gwt:onPropertyErrorFn"',Sb='"<script src=\\"',fb='"><\/script>',W='#',cc=');',Wb='-\n',ec='-><\/scr',Tb='.cache.js\\"><\/scr" + "ipt>"',Y='/',ib='//',Jb='2598AEA8366C96B57FECAE2C9CF852C2',Kb='290DF5E2344EE252BFA83EE54A18660C',Lb='46BBAD516CEA92A1558EB6AC364EDBDD',Mb='510BCB5AECF42013A6248A2D3FC4B7AE',Nb='8F467762443B9109859B7EBDAA5DDC2A',Pb=':',mb='::',Ub='<scr',eb='<script id="',pb='=',X='?',rb='Bad handler "',Gb='Cross-site hosted mode not yet implemented. See issue ',Ob='DE8E639EC5E34893D46F03386463AC34',Qb='DOMContentLoaded',gb='SCRIPT',db='__gwt_marker_gwttodo',hb='base',_='baseUrl',Q='begin',P='bootstrap',$='clear.cache.gif',ob='content',bc='document.write(',V='end',Zb='evtGroup: "loadExternalRefs", millis:(new Date()).getTime(),',_b='evtGroup: "moduleStartup", millis:(new Date()).getTime(),',Db='gecko',Eb='gecko1_8',R='gwt.codesvr=',S='gwt.hosted=',T='gwt.hybrid',tb='gwt:onLoadErrorFn',qb='gwt:onPropertyErrorFn',nb='gwt:property',N='gwttodo',bb='gwttodo.nocache.js',lb='gwttodo::',Hb='http://code.google.com/p/google-web-toolkit/issues/detail?id=2079',Cb='ie6',Bb='ie8',Ab='ie9',Z='img',fc='ipt>',Vb='ipt><!-',Rb='loadExternalRefs',jb='meta',Yb='moduleName:"gwttodo", sessionId:window.__gwtStatsSessionId, subSystem:"startup",',U='moduleStartup',zb='msie',kb='name',wb='opera',yb='safari',ab='script',Ib='selectingPermutation',O='startup',$b='type: "end"});',ac='type: "moduleRequested"});',cb='undefined',Fb='unknown',vb='user.agent',xb='webkit',Xb='window.__gwtStatsEvent && window.__gwtStatsEvent({';var m=window,n=document,o=m.__gwtStatsEvent?function(a){return m.__gwtStatsEvent(a)}:null,p=m.__gwtStatsSessionId?m.__gwtStatsSessionId:null,q,r,s=M,t={},u=[],v=[],w=[],x=0,y,z;o&&o({moduleName:N,sessionId:p,subSystem:O,evtGroup:P,millis:(new Date).getTime(),type:Q});if(!m.__gwt_stylesLoaded){m.__gwt_stylesLoaded={}}if(!m.__gwt_scriptsLoaded){m.__gwt_scriptsLoaded={}}function A(){var b=false;try{var c=m.location.search;return (c.indexOf(R)!=-1||(c.indexOf(S)!=-1||m.external&&m.external.gwtOnLoad))&&c.indexOf(T)==-1}catch(a){}A=function(){return b};return b}
function gwttodo(){var M='',dc='\n-',ub='" for "gwt:onLoadErrorFn"',sb='" for "gwt:onPropertyErrorFn"',Sb='"<script src=\\"',fb='"><\/script>',W='#',cc=');',Wb='-\n',ec='-><\/scr',Tb='.cache.js\\"><\/scr" + "ipt>"',Y='/',ib='//',Jb='11269AA57F495539D3888C07B9EB3B17',Kb='11502D2DBBE27FDC3BF44BACE45F84B6',Lb='28574D07C51C1139889498637093E3B0',Mb='2AC272A01A9C4D209D21D674CB52AB0C',Nb='5C490F07F777E65FD19DF9ECC16C17FB',Pb=':',mb='::',Ub='<scr',eb='<script id="',pb='=',X='?',rb='Bad handler "',Gb='Cross-site hosted mode not yet implemented. See issue ',Qb='DOMContentLoaded',Ob='F07E0067CA72074137C8A4F29F19B2C3',gb='SCRIPT',db='__gwt_marker_gwttodo',hb='base',_='baseUrl',Q='begin',P='bootstrap',$='clear.cache.gif',ob='content',bc='document.write(',V='end',Zb='evtGroup: "loadExternalRefs", millis:(new Date()).getTime(),',_b='evtGroup: "moduleStartup", millis:(new Date()).getTime(),',Db='gecko',Eb='gecko1_8',R='gwt.codesvr=',S='gwt.hosted=',T='gwt.hybrid',tb='gwt:onLoadErrorFn',qb='gwt:onPropertyErrorFn',nb='gwt:property',N='gwttodo',bb='gwttodo.nocache.js',lb='gwttodo::',Hb='http://code.google.com/p/google-web-toolkit/issues/detail?id=2079',Cb='ie6',Bb='ie8',Ab='ie9',Z='img',fc='ipt>',Vb='ipt><!-',Rb='loadExternalRefs',jb='meta',Yb='moduleName:"gwttodo", sessionId:window.__gwtStatsSessionId, subSystem:"startup",',U='moduleStartup',zb='msie',kb='name',wb='opera',yb='safari',ab='script',Ib='selectingPermutation',O='startup',$b='type: "end"});',ac='type: "moduleRequested"});',cb='undefined',Fb='unknown',vb='user.agent',xb='webkit',Xb='window.__gwtStatsEvent && window.__gwtStatsEvent({';var m=window,n=document,o=m.__gwtStatsEvent?function(a){return m.__gwtStatsEvent(a)}:null,p=m.__gwtStatsSessionId?m.__gwtStatsSessionId:null,q,r,s=M,t={},u=[],v=[],w=[],x=0,y,z;o&&o({moduleName:N,sessionId:p,subSystem:O,evtGroup:P,millis:(new Date).getTime(),type:Q});if(!m.__gwt_stylesLoaded){m.__gwt_stylesLoaded={}}if(!m.__gwt_scriptsLoaded){m.__gwt_scriptsLoaded={}}function A(){var b=false;try{var c=m.location.search;return (c.indexOf(R)!=-1||(c.indexOf(S)!=-1||m.external&&m.external.gwtOnLoad))&&c.indexOf(T)==-1}catch(a){}A=function(){return b};return b}
function B(){if(q&&r){q(y,N,s,x);o&&o({moduleName:N,sessionId:p,subSystem:O,evtGroup:U,millis:(new Date).getTime(),type:V})}}
function C(){function e(a){var b=a.lastIndexOf(W);if(b==-1){b=a.length}var c=a.indexOf(X);if(c==-1){c=a.length}var d=a.lastIndexOf(Y,Math.min(c,b));return d>=0?a.substring(0,d+1):M}
function f(a){if(a.match(/^\w+:\/\//)){}else{var b=n.createElement(Z);b.src=a+$;a=e(b.src)}return a}
......@@ -12,6 +12,6 @@ function D(){var b=document.getElementsByTagName(jb);for(var c=0,d=b.length;c<d;
function E(a){var b=t[a];return b==null?null:b}
function F(a,b){var c=w;for(var d=0,e=a.length-1;d<e;++d){c=c[a[d]]||(c[a[d]]=[])}c[a[e]]=b}
function G(a){var b=v[a](),c=u[a];if(b in c){return b}var d=[];for(var e in c){d[c[e]]=e}if(z){z(a,d,b)}throw null}
v[vb]=function(){var b=navigator.userAgent.toLowerCase();var c=function(a){return parseInt(a[1])*1000+parseInt(a[2])};if(function(){return b.indexOf(wb)!=-1}())return wb;if(function(){return b.indexOf(xb)!=-1}())return yb;if(function(){return b.indexOf(zb)!=-1&&n.documentMode>=9}())return Ab;if(function(){return b.indexOf(zb)!=-1&&n.documentMode>=8}())return Bb;if(function(){var a=/msie ([0-9]+)\.([0-9]+)/.exec(b);if(a&&a.length==3)return c(a)>=6000}())return Cb;if(function(){return b.indexOf(Db)!=-1}())return Eb;return Fb};u[vb]={gecko1_8:0,ie6:1,ie8:2,ie9:3,opera:4,safari:5};gwttodo.onScriptLoad=function(a){gwttodo.onScriptLoad=null;q=a;B()};if(A()){alert(Gb+Hb);return}D();C();o&&o({moduleName:N,sessionId:p,subSystem:O,evtGroup:P,millis:(new Date).getTime(),type:Ib});var H;try{F([Cb],Jb);F([yb],Kb);F([wb],Lb);F([Bb],Mb);F([Ab],Nb);F([Eb],Ob);H=w[G(vb)];var I=H.indexOf(Pb);if(I!=-1){x=Number(H.substring(I+1));H=H.substring(0,I)}}catch(a){return}var J;function K(){if(!r){r=true;B();if(n.removeEventListener){n.removeEventListener(Qb,K,false)}if(J){clearInterval(J)}}}
v[vb]=function(){var b=navigator.userAgent.toLowerCase();var c=function(a){return parseInt(a[1])*1000+parseInt(a[2])};if(function(){return b.indexOf(wb)!=-1}())return wb;if(function(){return b.indexOf(xb)!=-1}())return yb;if(function(){return b.indexOf(zb)!=-1&&n.documentMode>=9}())return Ab;if(function(){return b.indexOf(zb)!=-1&&n.documentMode>=8}())return Bb;if(function(){var a=/msie ([0-9]+)\.([0-9]+)/.exec(b);if(a&&a.length==3)return c(a)>=6000}())return Cb;if(function(){return b.indexOf(Db)!=-1}())return Eb;return Fb};u[vb]={gecko1_8:0,ie6:1,ie8:2,ie9:3,opera:4,safari:5};gwttodo.onScriptLoad=function(a){gwttodo.onScriptLoad=null;q=a;B()};if(A()){alert(Gb+Hb);return}D();C();o&&o({moduleName:N,sessionId:p,subSystem:O,evtGroup:P,millis:(new Date).getTime(),type:Ib});var H;try{F([Bb],Jb);F([yb],Kb);F([wb],Lb);F([Eb],Mb);F([Cb],Nb);F([Ab],Ob);H=w[G(vb)];var I=H.indexOf(Pb);if(I!=-1){x=Number(H.substring(I+1));H=H.substring(0,I)}}catch(a){return}var J;function K(){if(!r){r=true;B();if(n.removeEventListener){n.removeEventListener(Qb,K,false)}if(J){clearInterval(J)}}}
if(n.addEventListener){n.addEventListener(Qb,function(){K()},false)}var J=setInterval(function(){if(/loaded|complete/.test(n.readyState)){K()}},50);o&&o({moduleName:N,sessionId:p,subSystem:O,evtGroup:P,millis:(new Date).getTime(),type:V});o&&o({moduleName:N,sessionId:p,subSystem:O,evtGroup:Rb,millis:(new Date).getTime(),type:Q});var L=Sb+s+H+Tb;n.write(Ub+Vb+Wb+Xb+Yb+Zb+$b+Xb+Yb+_b+ac+bc+L+cc+dc+ec+fc)}
gwttodo();
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='gwttodo'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.json.JSON'/>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User' />
<inherits name='com.google.gwt.json.JSON' />
<!-- Don't inherit any GWT styles - they're ugly! -->
<!-- <inherits name='com.google.gwt.user.theme.clean.Clean'/>-->
<!-- Don't inherit any GWT styles - they're ugly! -->
<!-- <inherits name='com.google.gwt.user.theme.clean.Clean'/> -->
<!-- Other module inherits -->
<!-- Other module inherits -->
<!-- Specify the app entry point class. -->
<entry-point class='com.todo.client.GwtToDo'/>
<!-- Specify the app entry point class. -->
<entry-point class='com.todo.client.GwtToDo' />
<!-- Specify the paths for translatable code -->
<source path='client'/>
<!-- Specify the paths for translatable code -->
<source path='client' />
<add-linker name="xs" />
<add-linker name="xs" />
</module>
......@@ -82,7 +82,7 @@ public class ToDoCell extends AbstractCell<ToDoItem> {
} else {
SafeHtml rendered =
templates.view(value.isDone() ? templates.inputChecked() : templates.inputClear(),
SafeHtmlUtils.fromString(value.getTitle()), value.isDone() ? "listItem view done"
SafeHtmlUtils.fromString(value.getTitle()), value.isDone() ? "listItem view completed"
: "listItem view",
// NOTE: The addition of a timestamp here is a bit of a HACK! The problem
// is that the CellList uses a HasDataPresenter for rendering. This class
......@@ -158,9 +158,9 @@ public class ToDoCell extends AbstractCell<ToDoItem> {
// update the 'row' style
if (input.isChecked()) {
getViewRootElement(parent).addClassName("done");
getViewRootElement(parent).addClassName("completed");
} else {
getViewRootElement(parent).removeClassName("done");
getViewRootElement(parent).removeClassName("completed");
}
} else if (tagName.equals("BUTTON")) {
......
......@@ -4,12 +4,15 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONBoolean;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.storage.client.Storage;
import com.google.gwt.user.client.History;
import com.google.gwt.view.client.AbstractDataProvider;
import com.google.gwt.view.client.ListDataProvider;
......@@ -53,6 +56,11 @@ public class ToDoPresenter {
* Adds the handler to the events raised by the view.
*/
void addhandler(ViewEventHandler handler);
/**
* Informs the view of the current routing state.
*/
void setRouting(ToDoRouting routing);
}
/**
......@@ -96,30 +104,79 @@ public class ToDoPresenter {
}
};
private final ListDataProvider<ToDoItem> todos = new ListDataProvider<ToDoItem>();
private final List<ToDoItem> todos = new ArrayList<ToDoItem>();
private final ListDataProvider<ToDoItem> filteredTodos = new ListDataProvider<ToDoItem>();
private final View view;
private ToDoRouting routing = ToDoRouting.ALL;
private boolean suppressStateChanged = false;
public ToDoPresenter(View view) {
this.view = view;
loadState();
String initialToken = History.getToken();
routing = parseRoutingToken(initialToken);
view.addhandler(viewHandler);
view.setDataProvider(todos);
view.setDataProvider(filteredTodos);
view.setRouting(routing);
updateTaskStatistics();
setupHistoryHandler();
}
/**
* Set up a the history changed handler, which provides routing.
*/
private void setupHistoryHandler() {
History.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
routing = parseRoutingToken(historyToken);
view.setRouting(routing);
updateFilteredList();
}
});
}
/**
* Converts the string routing token into the equivalent enum value
*/
private ToDoRouting parseRoutingToken(String token ) {
if (token.equals("/active")) {
return ToDoRouting.ACTIVE;
} else if (token.equals("/completed")) {
return ToDoRouting.COMPLETED;
} else {
return ToDoRouting.ALL;
}
}
/**
* Updates the filtered list, which is rendered in the UI.
*/
private void updateFilteredList() {
filteredTodos.getList().clear();
for (ToDoItem task : todos) {
if (routing.getRoutingFunction().matches(task)) {
filteredTodos.getList().add(task);
}
}
}
/**
* Computes the tasks statistics and updates the view.
*/
private void updateTaskStatistics() {
int totalTasks = todos.getList().size();
int totalTasks = todos.size();
int completeTask = 0;
for (ToDoItem task : todos.getList()) {
for (ToDoItem task : todos) {
if (task.isDone()) {
completeTask++;
}
......@@ -132,9 +189,8 @@ public class ToDoPresenter {
* Deletes the given task and updates statistics.
*/
protected void deleteTask(ToDoItem toDoItem) {
todos.getList().remove(toDoItem);
updateTaskStatistics();
saveState();
todos.remove(toDoItem);
taskStateChanged();
}
/**
......@@ -148,9 +204,17 @@ public class ToDoPresenter {
// if the item has become empty, remove it
if (toDoItem.getTitle().trim().equals("")) {
todos.getList().remove(toDoItem);
todos.remove(toDoItem);
}
taskStateChanged();
}
/**
* When the task state has changed, this method will update the UI and persist
*/
private void taskStateChanged() {
updateFilteredList();
updateTaskStatistics();
saveState();
}
......@@ -162,18 +226,12 @@ public class ToDoPresenter {
// update the completed state of each item
suppressStateChanged = true;
for (ToDoItem task : todos.getList()) {
for (ToDoItem task : todos) {
task.setDone(completed);
}
suppressStateChanged = false;
// cause the view to refresh the whole list - yes, this is a bit ugly!
List<ToDoItem> items = new ArrayList<ToDoItem>(todos.getList());
todos.getList().clear();
todos.getList().addAll(items);
updateTaskStatistics();
saveState();
taskStateChanged();
}
/**
......@@ -188,24 +246,24 @@ public class ToDoPresenter {
ToDoItem toDoItem = new ToDoItem(taskTitle, this);
view.clearTaskText();
todos.getList().add(toDoItem);
updateTaskStatistics();
saveState();
todos.add(toDoItem);
taskStateChanged();
}
/**
* Clears completed tasks and updates the view.
*/
private void clearCompletedTasks() {
Iterator<ToDoItem> iterator = todos.getList().iterator();
Iterator<ToDoItem> iterator = todos.iterator();
while (iterator.hasNext()) {
ToDoItem item = iterator.next();
if (item.isDone()) {
iterator.remove();
}
}
updateTaskStatistics();
saveState();
taskStateChanged();
}
/**
......@@ -217,8 +275,8 @@ public class ToDoPresenter {
// JSON encode the items
JSONArray todoItems = new JSONArray();
for (int i = 0; i < todos.getList().size(); i++) {
ToDoItem toDoItem = todos.getList().get(i);
for (int i = 0; i < todos.size(); i++) {
ToDoItem toDoItem = todos.get(i);
JSONObject jsonObject = new JSONObject();
jsonObject.put("task", new JSONString(toDoItem.getTitle()));
jsonObject.put("complete", JSONBoolean.getInstance(toDoItem.isDone()));
......@@ -245,12 +303,14 @@ public class ToDoPresenter {
String task = jsonObject.get("task").isString().stringValue();
boolean completed = jsonObject.get("complete").isBoolean().booleanValue();
// add a new item to our list
todos.getList().add(new ToDoItem(task, completed, this));
todos.add(new ToDoItem(task, completed, this));
}
} catch (Exception e) {
}
}
updateFilteredList();
}
}
package com.todo.client;
public enum ToDoRouting {
/**
* Displays all todo items
*/
ALL(new ToDoRoutingAll()),
/**
* Displays active todo items - i.e. those that have not been done
*/
ACTIVE(new ToDoRoutingActive()),
/**
* Displays completed todo items - i.e. those that have been done
*/
COMPLETED(new ToDoRoutingCompleted());
private final ToDoRoutingFunction routingFunction;
private ToDoRouting(ToDoRoutingFunction routingFunction) {
this.routingFunction = routingFunction;
}
public ToDoRoutingFunction getRoutingFunction() {
return routingFunction;
}
}
package com.todo.client;
/**
* A routing function that matches active todo items.
*/
public class ToDoRoutingActive implements ToDoRoutingFunction {
@Override
public boolean matches(ToDoItem item) {
return !item.isDone();
}
}
package com.todo.client;
/**
* A routing function that matches all todo items.
*/
public class ToDoRoutingAll implements ToDoRoutingFunction {
@Override
public boolean matches(ToDoItem item) {
return true;
}
}
package com.todo.client;
/**
* A routing function that matches completed todo items.
*/
public class ToDoRoutingCompleted implements ToDoRoutingFunction {
@Override
public boolean matches(ToDoItem item) {
return item.isDone();
}
}
package com.todo.client;
/**
* A routing function filters todo items, based on some criteria
*/
public interface ToDoRoutingFunction {
/**
* Determines whether the given todo item matches this routing function.
*/
boolean matches(ToDoItem item);
}
......@@ -18,6 +18,7 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AbstractDataProvider;
import com.todo.client.ToDoPresenter.ViewEventHandler;
......@@ -33,6 +34,15 @@ public class ToDoView extends Composite implements ToDoPresenter.View {
interface ToDoViewUiBinder extends UiBinder<Widget, ToDoView> {
}
@UiField
Hyperlink routingAll;
@UiField
Hyperlink routingActive;
@UiField
Hyperlink routingCompleted;
@UiField
TextBoxWithPlaceholder taskText;
......@@ -143,6 +153,22 @@ public class ToDoView extends Composite implements ToDoPresenter.View {
toggleAll.setChecked(totalTasks == completedTasks);
}
@Override
public void setRouting(ToDoRouting routing) {
selectRoutingHyperlink(routingAll, ToDoRouting.ALL, routing);
selectRoutingHyperlink(routingActive, ToDoRouting.ACTIVE, routing);
selectRoutingHyperlink(routingCompleted, ToDoRouting.COMPLETED, routing);
}
private void selectRoutingHyperlink(Hyperlink hyperlink, ToDoRouting currentRoutingState,
ToDoRouting routingStateToMatch) {
if (currentRoutingState == routingStateToMatch) {
hyperlink.getElement().addClassName("selected");
} else {
hyperlink.getElement().removeClassName("selected");
}
}
private void hideElement(Element element, boolean hide) {
if (hide) {
element.setAttribute("style", "display:none;");
......
......@@ -2,6 +2,9 @@
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:cv="urn:import:com.google.gwt.user.cellview.client"
xmlns:todo="urn:import:com.todo.client">
<ui:style>
.inline { display:inline; }
</ui:style>
<g:HTMLPanel>
<section id="todoapp">
<header id="header">
......@@ -25,6 +28,17 @@
<span class="word" ui:field="remainingTasksLabel"></span>
left
</span>
<ul id="filters">
<li>
<g:Hyperlink targetHistoryToken="/" styleName="{style.inline}" ui:field="routingAll">All</g:Hyperlink>
</li>
<li>
<g:Hyperlink targetHistoryToken="/active" styleName="{style.inline}" ui:field="routingActive">Active</g:Hyperlink>
</li>
<li>
<g:Hyperlink targetHistoryToken="/completed" styleName="{style.inline}" ui:field="routingCompleted">Completed</g:Hyperlink>
</li>
</ul>
<g:Button ui:field="clearCompleted">
Clear completed (<span class="number-done" ui:field="clearTasksCount"></span>)
</g:Button>
......
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