Skip to content

Instantly share code, notes, and snippets.

@tvbarajas
Created February 28, 2014 05:53
Show Gist options
  • Select an option

  • Save tvbarajas/9266013 to your computer and use it in GitHub Desktop.

Select an option

Save tvbarajas/9266013 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>GluJS - Touch Example</title>
<link rel="stylesheet" href="http://cdn.sencha.com/touch/sencha-touch-2.3.1/resources/css/sencha-touch.css"/>
<script type="text/javascript" src="http://cdn.sencha.com/touch/sencha-touch-2.3.1/sencha-touch-all-debug.js"></script>
<script type="text/javascript" src="http://www.glujs.com/js/glu-touch-2.js"></script>
<script type="text/javascript" src="http://www.glujs.com/js/glu.js"></script>
</head>
<body>
</body>
</html>
Ext.setup({
onReady:function () {
glu.viewport('todo.main');
}
});
glu.defView('todo.main', {
centered:false,
border:false,
layout:{
type:'vbox'
},
items:[
{
docked:'top',
xtype:'titlebar',
items:[
{
xtype:'label',
html:'~~todo~~'
}
]
},
{
layout:'hbox',
height:50,
items:[
{
xtype:'checkboxfield',
checked:'@>{allVisibleItemsAreCompleted}',
disabled:'@{!completeAllIsDisabled}',
width:50,
height:40,
//handler : '@{batchComplete}'
listeners:{
checkedChanged:'@{batchComplete}'
}
},
{
xtype:'textfield',
value:'@{newItemText}',
cls:'todo-newItemText',
placeHolder:'~~newItemText~~',
enterKeyHandler:'@{addNewItem}',
width:300,
height:40
}
]
},
{ //list body
layout:'vbox',
flex:1,
scrollable:{
direction:'vertical',
directionLock:true
},
items:'@{todoList}'
},
{
xtype:'toolbar',
height:50,
// layout:'fit',
docked:'bottom',
items:[
{
xtype:'label',
html:'@{itemsLeftText}'
},
{
xtype:'spacer',
width:50
},
{
xtype:'container',
height:50,
items:[
{
xtype:'segmentedbutton',
centered:true,
floating:false,
allowMultiple: false,
activeButton:'@{filterMode}',
items:[
{
xtype:'button',
text:'~~all~~',
value:'all'
},
{
xtype:'button',
text:'~~active~~',
value:'active'
},
{
xtype:'button',
text:'~~completed~~',
value:'completed'
}
]
}
]
}
]
}
]
});
glu.defView('todo.todoitem', {
xtype:'container',
layout:'hbox',
isHovered:'@{focused}',
height:50,
hidden:'@{!isVisible}',
items:[
{
xtype:'checkboxfield',
checked:'@{completed}',
width:50,
height:40
},
{
xtype:'label',
width:250, //flex isn't working for some reason...
height:40,
disabledCls:'todo-item-completed',
disabled:'@{completed}',
html:'@{text}'
// html : {
// html:'@{text}',
// width:300,
// alignment : 'l-l?',
// field : {
// xtype: 'textfield'
// }
// }
},
{
xtype:'button',
iconCls:'delete',
iconMask:true,
handler:'@{remove}'
}
]
});
glu.defModel('todo.main', {
todoList:{ mtype:'list' },
newItemText:'',
filterMode:'all',
addNewItem:function () {
this.todoList.add(this.model({
mtype:'todoitem',
text:Ext.String.trim(this.newItemText)
}));
this.set('newItemText', '');
},
remove:function (item) { this.todoList.remove(item); },
notifyItemChanged:function () {
this.fireEvent('todolistchanged');
},
activeCount$: function(){
var l = this.todoList.length; //force for now!
return this.todoList.count(function(item){ return item.completed === false;});
},
visibleCount$: function(){
var l = this.todoList.length; //force for now!
return this.todoList.count(function(item){ return item.isVisible === true;});
},
itemsLeftText$:function () {
return this.localize('itemsLeft', {count:this.activeCount});
},
completedCount$:function () {
return this.todoList.length - this.activeCount;
},
clearCompleted:function () {
for (var i = this.todoList.length - 1; i > -1; i--) {
var item = this.todoList.getAt(i);
if (item.completed === true) {
this.remove(item);
}
}
},
clearCompletedText$:function () {
return this.localize('clearCompleted', {count:this.completedCount});
},
clearCompletedIsVisible$:function () {
return this.completedCount > 0;
},
completeAllIsDisabled$:function () {
return this.visibleCount > 0;
},
batchComplete:function (value) {
console.log (value ? "Completing all" : "Uncompleting all")
this.todoList.each(function (item) {
if (item.isVisible) item.set('completed', value)
});
},
allVisibleItemsAreCompleted$:function () {
switch (this.filterMode) {
case 'all' :
return this.activeCount == 0 && this.todoList.length > 0;
case 'active' :
return false;
case 'completed' :
return this.completedCount > 0;
}
}
});
glu.defModel('todo.todoitem', {
text:'',
completed:false,
focused:false,
remove:function () {
this.parentVM.remove(this);
},
removeIsVisible$:function () { return this.focused; },
isVisible$:function(){
var mode = this.parentVM.filterMode;
return mode == 'all' || (mode == 'active' && this.completed == false) || (mode=='completed' && this.completed == true);
},
//TODO: Figure out first-order-logic semantics to allow accumulators from outside
//e.g. in parent : this.todoList.count(function(){ this.completed == true;});
//and .count is recognized as 'live' accumulator that listens to any change on any child this.completed
//i.e. this.on ('todoList.*.completedchanged')
//meaning as items are added to list we start listening on them
when_completed_changes_notify_parent:{
on:['completedchanged','isvisiblechanged'],
action:function () {
this.parentVM.notifyItemChanged();
}
}
});
glu.namespace('todo').locale = {
todo: 'ToDo',
newItemText : 'What needs to be done?',
itemsLeft : '{count} items left',
all:'All',
active:'Active',
completed:'Completed',
clearCompleted:'Clear completed ({count})'
};
glu.namespace('todo.models').task = {
fields:[
{
name:'id',
type:'int'
},{
name:'description',
type:'string'
},{
name:'priority',
type:'string',
oneOf : ['high','medium','low']
},{
name:'lastUpdated',
type:'date'
}
]
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment