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
1c04c6b5
Commit
1c04c6b5
authored
Jul 06, 2012
by
Sindre Sorhus
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tabs
parent
21c9a3f9
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
384 additions
and
384 deletions
+384
-384
architecture-examples/yuilibrary/js/app.js
architecture-examples/yuilibrary/js/app.js
+384
-384
No files found.
architecture-examples/yuilibrary/js/app.js
View file @
1c04c6b5
...
@@ -10,23 +10,23 @@ var TodoAppView, TodoList, TodoModel, TodoView, localStorageName = 'todos-yuilib
...
@@ -10,23 +10,23 @@ var TodoAppView, TodoList, TodoModel, TodoView, localStorageName = 'todos-yuilib
// attributes and methods useful for todo items.
// attributes and methods useful for todo items.
TodoModel
=
Y
.
TodoModel
=
Y
.
Base
.
create
(
'
todoModel
'
,
Y
.
Model
,
[],
{
TodoModel
=
Y
.
TodoModel
=
Y
.
Base
.
create
(
'
todoModel
'
,
Y
.
Model
,
[],
{
// This tells the Model to use a localStorage sync provider (which we'll
// This tells the Model to use a localStorage sync provider (which we'll
// create below) to save and load information about a todo item.
// create below) to save and load information about a todo item.
sync
:
LocalStorageSync
(
localStorageName
),
sync
:
LocalStorageSync
(
localStorageName
),
// This method will toggle the `done` attribute from `true` to `false`, or
// This method will toggle the `done` attribute from `true` to `false`, or
// vice versa.
// vice versa.
toggleDone
:
function
()
{
toggleDone
:
function
()
{
this
.
set
(
'
done
'
,
!
this
.
get
(
'
done
'
)).
save
();
this
.
set
(
'
done
'
,
!
this
.
get
(
'
done
'
)).
save
();
}
}
},
{
},
{
ATTRS
:
{
ATTRS
:
{
// Indicates whether or not this todo item has been completed.
// Indicates whether or not this todo item has been completed.
done
:
{
value
:
false
},
done
:
{
value
:
false
},
// Contains the text of the todo item.
// Contains the text of the todo item.
text
:
{
value
:
''
}
text
:
{
value
:
''
}
}
}
});
});
// -- ModelList ----------------------------------------------------------------
// -- ModelList ----------------------------------------------------------------
...
@@ -36,28 +36,28 @@ TodoModel = Y.TodoModel = Y.Base.create('todoModel', Y.Model, [], {
...
@@ -36,28 +36,28 @@ TodoModel = Y.TodoModel = Y.Base.create('todoModel', Y.Model, [], {
// information about the todo items in the list.
// information about the todo items in the list.
TodoList
=
Y
.
TodoList
=
Y
.
Base
.
create
(
'
todoList
'
,
Y
.
ModelList
,
[],
{
TodoList
=
Y
.
TodoList
=
Y
.
Base
.
create
(
'
todoList
'
,
Y
.
ModelList
,
[],
{
// This tells the list that it will hold instances of the TodoModel class.
// This tells the list that it will hold instances of the TodoModel class.
model
:
TodoModel
,
model
:
TodoModel
,
// This tells the list to use a localStorage sync provider (which we'll
// This tells the list to use a localStorage sync provider (which we'll
// create below) to load the list of todo items.
// create below) to load the list of todo items.
sync
:
LocalStorageSync
(
localStorageName
),
sync
:
LocalStorageSync
(
localStorageName
),
// Returns an array of all models in this list with the `done` attribute
// Returns an array of all models in this list with the `done` attribute
// set to `true`.
// set to `true`.
done
:
function
()
{
done
:
function
()
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
model
.
get
(
'
done
'
);
return
model
.
get
(
'
done
'
);
});
});
},
},
// Returns an array of all models in this list with the `done` attribute
// Returns an array of all models in this list with the `done` attribute
// set to `false`.
// set to `false`.
remaining
:
function
()
{
remaining
:
function
()
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
Y
.
Array
.
filter
(
this
.
toArray
(),
function
(
model
)
{
return
!
model
.
get
(
'
done
'
);
return
!
model
.
get
(
'
done
'
);
});
});
}
}
});
});
// -- Todo App View ------------------------------------------------------------
// -- Todo App View ------------------------------------------------------------
...
@@ -71,165 +71,165 @@ TodoList = Y.TodoList = Y.Base.create('todoList', Y.ModelList, [], {
...
@@ -71,165 +71,165 @@ TodoList = Y.TodoList = Y.Base.create('todoList', Y.ModelList, [], {
// initially loaded or reset.
// initially loaded or reset.
TodoAppView
=
Y
.
TodoAppView
=
Y
.
Base
.
create
(
'
todoAppView
'
,
Y
.
View
,
[],
{
TodoAppView
=
Y
.
TodoAppView
=
Y
.
Base
.
create
(
'
todoAppView
'
,
Y
.
View
,
[],
{
// The container node is the wrapper for this view. All the view's events
// The container node is the wrapper for this view. All the view's events
// will be delegated from the container. In this case, the #todo-app
// will be delegated from the container. In this case, the #todo-app
// node already exists on the page, so we don't need to create it.
// node already exists on the page, so we don't need to create it.
container
:
Y
.
one
(
'
#todo-app
'
),
container
:
Y
.
one
(
'
#todo-app
'
),
// This is a custom property that we'll use to hold a reference to the
// This is a custom property that we'll use to hold a reference to the
// "new todo" input field.
// "new todo" input field.
inputNode
:
Y
.
one
(
'
#new-todo
'
),
inputNode
:
Y
.
one
(
'
#new-todo
'
),
// The `template` property is a convenience property for holding a template
// The `template` property is a convenience property for holding a template
// for this view. In this case, we'll use it to store the contents of the
// for this view. In this case, we'll use it to store the contents of the
// #todo-stats-template element, which will serve as the template for the
// #todo-stats-template element, which will serve as the template for the
// statistics displayed at the bottom of the list.
// statistics displayed at the bottom of the list.
template
:
Y
.
one
(
'
#todo-stats-template
'
).
getContent
(),
template
:
Y
.
one
(
'
#todo-stats-template
'
).
getContent
(),
// This is where we attach DOM events for the view. The `events` object is a
// This is where we attach DOM events for the view. The `events` object is a
// mapping of selectors to an object containing one or more events to attach
// mapping of selectors to an object containing one or more events to attach
// to the node(s) matching each selector.
// to the node(s) matching each selector.
events
:
{
events
:
{
// Handle <enter> keypresses on the "new todo" input field.
// Handle <enter> keypresses on the "new todo" input field.
'
#new-todo
'
:
{
keypress
:
'
createTodo
'
},
'
#new-todo
'
:
{
keypress
:
'
createTodo
'
},
// Clear all completed items from the list when the "Clear" link is
// Clear all completed items from the list when the "Clear" link is
// clicked.
// clicked.
'
.todo-clear
'
:
{
click
:
'
clearDone
'
},
'
.todo-clear
'
:
{
click
:
'
clearDone
'
},
// Add and remove hover states on todo items.
// Add and remove hover states on todo items.
'
.todo-item
'
:
{
'
.todo-item
'
:
{
mouseover
:
'
hoverOn
'
,
mouseover
:
'
hoverOn
'
,
mouseout
:
'
hoverOff
'
mouseout
:
'
hoverOff
'
}
}
},
},
// The initializer runs when a TodoAppView instance is created, and gives
// The initializer runs when a TodoAppView instance is created, and gives
// us an opportunity to set up the view.
// us an opportunity to set up the view.
initializer
:
function
()
{
initializer
:
function
()
{
// Create a new TodoList instance to hold the todo items.
// Create a new TodoList instance to hold the todo items.
var
list
=
this
.
todoList
=
new
TodoList
();
var
list
=
this
.
todoList
=
new
TodoList
();
// Update the display when a new item is added to the list, or when the
// Update the display when a new item is added to the list, or when the
// entire list is reset.
// entire list is reset.
list
.
after
(
'
add
'
,
this
.
add
,
this
);
list
.
after
(
'
add
'
,
this
.
add
,
this
);
list
.
after
(
'
reset
'
,
this
.
reset
,
this
);
list
.
after
(
'
reset
'
,
this
.
reset
,
this
);
// Re-render the stats in the footer whenever an item is added, removed
// Re-render the stats in the footer whenever an item is added, removed
// or changed, or when the entire list is reset.
// or changed, or when the entire list is reset.
list
.
after
([
'
add
'
,
'
reset
'
,
'
remove
'
,
'
todoModel:doneChange
'
],
list
.
after
([
'
add
'
,
'
reset
'
,
'
remove
'
,
'
todoModel:doneChange
'
],
this
.
render
,
this
);
this
.
render
,
this
);
// Load saved items from localStorage, if available.
// Load saved items from localStorage, if available.
list
.
load
();
list
.
load
();
},
},
// The render function is called whenever a todo item is added, removed, or
// The render function is called whenever a todo item is added, removed, or
// changed, thanks to the list event handler we attached in the initializer
// changed, thanks to the list event handler we attached in the initializer
// above.
// above.
render
:
function
()
{
render
:
function
()
{
var
todoList
=
this
.
todoList
,
var
todoList
=
this
.
todoList
,
stats
=
this
.
container
.
one
(
'
#todo-stats
'
),
stats
=
this
.
container
.
one
(
'
#todo-stats
'
),
numRemaining
,
numDone
;
numRemaining
,
numDone
;
// If there are no todo items, then clear the stats.
// If there are no todo items, then clear the stats.
if
(
todoList
.
isEmpty
())
{
if
(
todoList
.
isEmpty
())
{
stats
.
empty
();
stats
.
empty
();
return
this
;
return
this
;
}
}
// Figure out how many todo items are completed and how many remain.
// Figure out how many todo items are completed and how many remain.
numDone
=
todoList
.
done
().
length
;
numDone
=
todoList
.
done
().
length
;
numRemaining
=
todoList
.
remaining
().
length
;
numRemaining
=
todoList
.
remaining
().
length
;
// Update the statistics.
// Update the statistics.
stats
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
stats
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
numDone
:
numDone
,
numDone
:
numDone
,
numRemaining
:
numRemaining
,
numRemaining
:
numRemaining
,
doneLabel
:
numDone
===
1
?
'
task
'
:
'
tasks
'
,
doneLabel
:
numDone
===
1
?
'
task
'
:
'
tasks
'
,
remainingLabel
:
numRemaining
===
1
?
'
task
'
:
'
tasks
'
remainingLabel
:
numRemaining
===
1
?
'
task
'
:
'
tasks
'
}));
}));
// If there are no completed todo items, don't show the "Clear
// If there are no completed todo items, don't show the "Clear
// completed items" link.
// completed items" link.
if
(
!
numDone
)
{
if
(
!
numDone
)
{
stats
.
one
(
'
.todo-clear
'
).
remove
();
stats
.
one
(
'
.todo-clear
'
).
remove
();
}
}
return
this
;
return
this
;
},
},
// -- Event Handlers -------------------------------------------------------
// -- Event Handlers -------------------------------------------------------
// Creates a new TodoView instance and renders it into the list whenever a
// Creates a new TodoView instance and renders it into the list whenever a
// todo item is added to the list.
// todo item is added to the list.
add
:
function
(
e
)
{
add
:
function
(
e
)
{
var
view
=
new
TodoView
({
model
:
e
.
model
});
var
view
=
new
TodoView
({
model
:
e
.
model
});
this
.
container
.
one
(
'
#todo-list
'
).
append
(
view
.
render
().
container
);
this
.
container
.
one
(
'
#todo-list
'
).
append
(
view
.
render
().
container
);
},
},
// Removes all finished todo items from the list.
// Removes all finished todo items from the list.
clearDone
:
function
(
e
)
{
clearDone
:
function
(
e
)
{
var
done
=
this
.
todoList
.
done
();
var
done
=
this
.
todoList
.
done
();
e
.
preventDefault
();
e
.
preventDefault
();
// Remove all finished items from the list, but do it silently so as not
// Remove all finished items from the list, but do it silently so as not
// to re-render the app view after each item is removed.
// to re-render the app view after each item is removed.
this
.
todoList
.
remove
(
done
,
{
silent
:
true
});
this
.
todoList
.
remove
(
done
,
{
silent
:
true
});
// Destroy each removed TodoModel instance.
// Destroy each removed TodoModel instance.
Y
.
Array
.
each
(
done
,
function
(
todo
)
{
Y
.
Array
.
each
(
done
,
function
(
todo
)
{
// Passing {'delete': true} to the todo model's `destroy()` method
// Passing {'delete': true} to the todo model's `destroy()` method
// tells it to delete itself from localStorage as well.
// tells it to delete itself from localStorage as well.
todo
.
destroy
({
'
delete
'
:
true
});
todo
.
destroy
({
'
delete
'
:
true
});
});
});
// Finally, re-render the app view.
// Finally, re-render the app view.
this
.
render
();
this
.
render
();
},
},
// Creates a new todo item when the enter key is pressed in the new todo
// Creates a new todo item when the enter key is pressed in the new todo
// input field.
// input field.
createTodo
:
function
(
e
)
{
createTodo
:
function
(
e
)
{
var
value
;
var
value
;
if
(
e
.
keyCode
===
13
)
{
// enter key
if
(
e
.
keyCode
===
13
)
{
// enter key
value
=
Y
.
Lang
.
trim
(
this
.
inputNode
.
get
(
'
value
'
));
value
=
Y
.
Lang
.
trim
(
this
.
inputNode
.
get
(
'
value
'
));
if
(
!
value
)
{
return
;
}
if
(
!
value
)
{
return
;
}
// This tells the list to create a new TodoModel instance with the
// This tells the list to create a new TodoModel instance with the
// specified text and automatically save it to localStorage in a
// specified text and automatically save it to localStorage in a
// single step.
// single step.
this
.
todoList
.
create
({
text
:
value
});
this
.
todoList
.
create
({
text
:
value
});
this
.
inputNode
.
set
(
'
value
'
,
''
);
this
.
inputNode
.
set
(
'
value
'
,
''
);
}
}
},
},
// Turns off the hover state on a todo item.
// Turns off the hover state on a todo item.
hoverOff
:
function
(
e
)
{
hoverOff
:
function
(
e
)
{
e
.
currentTarget
.
removeClass
(
'
todo-hover
'
);
e
.
currentTarget
.
removeClass
(
'
todo-hover
'
);
},
},
// Turns on the hover state on a todo item.
// Turns on the hover state on a todo item.
hoverOn
:
function
(
e
)
{
hoverOn
:
function
(
e
)
{
e
.
currentTarget
.
addClass
(
'
todo-hover
'
);
e
.
currentTarget
.
addClass
(
'
todo-hover
'
);
},
},
// Creates and renders views for every todo item in the list when the entire
// Creates and renders views for every todo item in the list when the entire
// list is reset.
// list is reset.
reset
:
function
(
e
)
{
reset
:
function
(
e
)
{
var
fragment
=
Y
.
one
(
Y
.
config
.
doc
.
createDocumentFragment
());
var
fragment
=
Y
.
one
(
Y
.
config
.
doc
.
createDocumentFragment
());
Y
.
Array
.
each
(
e
.
models
,
function
(
model
)
{
Y
.
Array
.
each
(
e
.
models
,
function
(
model
)
{
var
view
=
new
TodoView
({
model
:
model
});
var
view
=
new
TodoView
({
model
:
model
});
fragment
.
append
(
view
.
render
().
container
);
fragment
.
append
(
view
.
render
().
container
);
});
});
this
.
container
.
one
(
'
#todo-list
'
).
setContent
(
fragment
);
this
.
container
.
one
(
'
#todo-list
'
).
setContent
(
fragment
);
}
}
});
});
// -- Todo item view -----------------------------------------------------------
// -- Todo item view -----------------------------------------------------------
...
@@ -239,101 +239,101 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
...
@@ -239,101 +239,101 @@ TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
// allow it to be edited and removed from the list.
// allow it to be edited and removed from the list.
TodoView
=
Y
.
TodoView
=
Y
.
Base
.
create
(
'
todoView
'
,
Y
.
View
,
[],
{
TodoView
=
Y
.
TodoView
=
Y
.
Base
.
create
(
'
todoView
'
,
Y
.
View
,
[],
{
// Specifying an HTML string as this view's container element causes that
// Specifying an HTML string as this view's container element causes that
// HTML to be automatically converted into an unattached Y.Node instance.
// HTML to be automatically converted into an unattached Y.Node instance.
// The TodoAppView (above) will take care of appending it to the list.
// The TodoAppView (above) will take care of appending it to the list.
container
:
'
<li class="todo-item"/>
'
,
container
:
'
<li class="todo-item"/>
'
,
// The template property holds the contents of the #todo-item-template
// The template property holds the contents of the #todo-item-template
// element, which will be used as the HTML template for each todo item.
// element, which will be used as the HTML template for each todo item.
template
:
Y
.
one
(
'
#todo-item-template
'
).
getContent
(),
template
:
Y
.
one
(
'
#todo-item-template
'
).
getContent
(),
// Delegated DOM events to handle this view's interactions.
// Delegated DOM events to handle this view's interactions.
events
:
{
events
:
{
// Toggle the "done" state of this todo item when the checkbox is
// Toggle the "done" state of this todo item when the checkbox is
// clicked.
// clicked.
'
.todo-checkbox
'
:
{
click
:
'
toggleDone
'
},
'
.todo-checkbox
'
:
{
click
:
'
toggleDone
'
},
// When the text of this todo item is clicked or focused, switch to edit
// When the text of this todo item is clicked or focused, switch to edit
// mode to allow editing.
// mode to allow editing.
'
.todo-content
'
:
{
'
.todo-content
'
:
{
click
:
'
edit
'
,
click
:
'
edit
'
,
focus
:
'
edit
'
focus
:
'
edit
'
},
},
// On the edit field, when enter is pressed or the field loses focus,
// On the edit field, when enter is pressed or the field loses focus,
// save the current value and switch out of edit mode.
// save the current value and switch out of edit mode.
'
.todo-input
'
:
{
'
.todo-input
'
:
{
blur
:
'
save
'
,
blur
:
'
save
'
,
keypress
:
'
enter
'
keypress
:
'
enter
'
},
},
// When the remove icon is clicked, delete this todo item.
// When the remove icon is clicked, delete this todo item.
'
.todo-remove
'
:
{
click
:
'
remove
'
}
'
.todo-remove
'
:
{
click
:
'
remove
'
}
},
},
initializer
:
function
()
{
initializer
:
function
()
{
// The model property is set to a TodoModel instance by TodoAppView when
// The model property is set to a TodoModel instance by TodoAppView when
// it instantiates this TodoView.
// it instantiates this TodoView.
var
model
=
this
.
model
;
var
model
=
this
.
model
;
// Re-render this view when the model changes, and destroy this view
// Re-render this view when the model changes, and destroy this view
// when the model is destroyed.
// when the model is destroyed.
model
.
after
(
'
change
'
,
this
.
render
,
this
);
model
.
after
(
'
change
'
,
this
.
render
,
this
);
model
.
after
(
'
destroy
'
,
this
.
destroy
,
this
);
model
.
after
(
'
destroy
'
,
this
.
destroy
,
this
);
},
},
render
:
function
()
{
render
:
function
()
{
var
container
=
this
.
container
,
var
container
=
this
.
container
,
model
=
this
.
model
,
model
=
this
.
model
,
done
=
model
.
get
(
'
done
'
);
done
=
model
.
get
(
'
done
'
);
container
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
container
.
setContent
(
Y
.
Lang
.
sub
(
this
.
template
,
{
checked
:
done
?
'
checked
'
:
''
,
checked
:
done
?
'
checked
'
:
''
,
text
:
model
.
getAsHTML
(
'
text
'
)
text
:
model
.
getAsHTML
(
'
text
'
)
}));
}));
container
[
done
?
'
addClass
'
:
'
removeClass
'
](
'
todo-done
'
);
container
[
done
?
'
addClass
'
:
'
removeClass
'
](
'
todo-done
'
);
this
.
inputNode
=
container
.
one
(
'
.todo-input
'
);
this
.
inputNode
=
container
.
one
(
'
.todo-input
'
);
return
this
;
return
this
;
},
},
// -- Event Handlers -------------------------------------------------------
// -- Event Handlers -------------------------------------------------------
// Toggles this item into edit mode.
// Toggles this item into edit mode.
edit
:
function
()
{
edit
:
function
()
{
this
.
container
.
addClass
(
'
editing
'
);
this
.
container
.
addClass
(
'
editing
'
);
this
.
inputNode
.
focus
();
this
.
inputNode
.
focus
();
},
},
// When the enter key is pressed, focus the new todo input field. This
// When the enter key is pressed, focus the new todo input field. This
// causes a blur event on the current edit field, which calls the save()
// causes a blur event on the current edit field, which calls the save()
// handler below.
// handler below.
enter
:
function
(
e
)
{
enter
:
function
(
e
)
{
if
(
e
.
keyCode
===
13
)
{
// enter key
if
(
e
.
keyCode
===
13
)
{
// enter key
Y
.
one
(
'
#new-todo
'
).
focus
();
Y
.
one
(
'
#new-todo
'
).
focus
();
}
}
},
},
// Removes this item from the list.
// Removes this item from the list.
remove
:
function
(
e
)
{
remove
:
function
(
e
)
{
e
.
preventDefault
();
e
.
preventDefault
();
this
.
constructor
.
superclass
.
remove
.
call
(
this
);
this
.
constructor
.
superclass
.
remove
.
call
(
this
);
this
.
model
.
destroy
({
'
delete
'
:
true
});
this
.
model
.
destroy
({
'
delete
'
:
true
});
},
},
// Toggles this item out of edit mode and saves it.
// Toggles this item out of edit mode and saves it.
save
:
function
()
{
save
:
function
()
{
this
.
container
.
removeClass
(
'
editing
'
);
this
.
container
.
removeClass
(
'
editing
'
);
this
.
model
.
set
(
'
text
'
,
this
.
inputNode
.
get
(
'
value
'
)).
save
();
this
.
model
.
set
(
'
text
'
,
this
.
inputNode
.
get
(
'
value
'
)).
save
();
},
},
// Toggles the `done` state on this item's model.
// Toggles the `done` state on this item's model.
toggleDone
:
function
()
{
toggleDone
:
function
()
{
this
.
model
.
toggleDone
();
this
.
model
.
toggleDone
();
}
}
});
});
// -- localStorage Sync Implementation -----------------------------------------
// -- localStorage Sync Implementation -----------------------------------------
...
@@ -343,99 +343,99 @@ TodoView = Y.TodoView = Y.Base.create('todoView', Y.View, [], {
...
@@ -343,99 +343,99 @@ TodoView = Y.TodoView = Y.Base.create('todoView', Y.View, [], {
// TodoModel and TodoList instances above use it to save and load items.
// TodoModel and TodoList instances above use it to save and load items.
function
LocalStorageSync
(
key
)
{
function
LocalStorageSync
(
key
)
{
var
localStorage
;
var
localStorage
;
if
(
!
key
)
{
if
(
!
key
)
{
Y
.
error
(
'
No storage key specified.
'
);
Y
.
error
(
'
No storage key specified.
'
);
}
}
if
(
Y
.
config
.
win
.
localStorage
)
{
if
(
Y
.
config
.
win
.
localStorage
)
{
localStorage
=
Y
.
config
.
win
.
localStorage
;
localStorage
=
Y
.
config
.
win
.
localStorage
;
}
}
// Try to retrieve existing data from localStorage, if there is any.
// Try to retrieve existing data from localStorage, if there is any.
// Otherwise, initialize `data` to an empty object.
// Otherwise, initialize `data` to an empty object.
var
data
=
Y
.
JSON
.
parse
((
localStorage
&&
localStorage
.
getItem
(
key
))
||
'
{}
'
);
var
data
=
Y
.
JSON
.
parse
((
localStorage
&&
localStorage
.
getItem
(
key
))
||
'
{}
'
);
// Delete a model with the specified id.
// Delete a model with the specified id.
function
destroy
(
id
)
{
function
destroy
(
id
)
{
var
modelHash
;
var
modelHash
;
if
((
modelHash
=
data
[
id
]))
{
if
((
modelHash
=
data
[
id
]))
{
delete
data
[
id
];
delete
data
[
id
];
save
();
save
();
}
}
return
modelHash
;
return
modelHash
;
}
}
// Generate a unique id to assign to a newly-created model.
// Generate a unique id to assign to a newly-created model.
function
generateId
()
{
function
generateId
()
{
var
id
=
''
,
var
id
=
''
,
i
=
4
;
i
=
4
;
while
(
i
--
)
{
while
(
i
--
)
{
id
+=
(((
1
+
Math
.
random
())
*
0x10000
)
|
0
)
id
+=
(((
1
+
Math
.
random
())
*
0x10000
)
|
0
)
.
toString
(
16
).
substring
(
1
);
.
toString
(
16
).
substring
(
1
);
}
}
return
id
;
return
id
;
}
}
// Loads a model with the specified id. This method is a little tricky,
// Loads a model with the specified id. This method is a little tricky,
// since it handles loading for both individual models and for an entire
// since it handles loading for both individual models and for an entire
// model list.
// model list.
//
//
// If an id is specified, then it loads a single model. If no id is
// If an id is specified, then it loads a single model. If no id is
// specified then it loads an array of all models. This allows the same sync
// specified then it loads an array of all models. This allows the same sync
// layer to be used for both the TodoModel and TodoList classes.
// layer to be used for both the TodoModel and TodoList classes.
function
get
(
id
)
{
function
get
(
id
)
{
return
id
?
data
[
id
]
:
Y
.
Object
.
values
(
data
);
return
id
?
data
[
id
]
:
Y
.
Object
.
values
(
data
);
}
}
// Saves the entire `data` object to localStorage.
// Saves the entire `data` object to localStorage.
function
save
()
{
function
save
()
{
localStorage
&&
localStorage
.
setItem
(
key
,
Y
.
JSON
.
stringify
(
data
));
localStorage
&&
localStorage
.
setItem
(
key
,
Y
.
JSON
.
stringify
(
data
));
}
}
// Sets the id attribute of the specified model (generating a new id if
// Sets the id attribute of the specified model (generating a new id if
// necessary), then saves it to localStorage.
// necessary), then saves it to localStorage.
function
set
(
model
)
{
function
set
(
model
)
{
var
hash
=
model
.
toJSON
(),
var
hash
=
model
.
toJSON
(),
idAttribute
=
model
.
idAttribute
;
idAttribute
=
model
.
idAttribute
;
if
(
!
Y
.
Lang
.
isValue
(
hash
[
idAttribute
]))
{
if
(
!
Y
.
Lang
.
isValue
(
hash
[
idAttribute
]))
{
hash
[
idAttribute
]
=
generateId
();
hash
[
idAttribute
]
=
generateId
();
}
}
data
[
hash
[
idAttribute
]]
=
hash
;
data
[
hash
[
idAttribute
]]
=
hash
;
save
();
save
();
return
hash
;
return
hash
;
}
}
// Returns a `sync()` function that can be used with either a Model or a
// Returns a `sync()` function that can be used with either a Model or a
// ModelList instance.
// ModelList instance.
return
function
(
action
,
options
,
callback
)
{
return
function
(
action
,
options
,
callback
)
{
// `this` refers to the Model or ModelList instance to which this sync
// `this` refers to the Model or ModelList instance to which this sync
// method is attached.
// method is attached.
var
isModel
=
Y
.
Model
&&
this
instanceof
Y
.
Model
;
var
isModel
=
Y
.
Model
&&
this
instanceof
Y
.
Model
;
switch
(
action
)
{
switch
(
action
)
{
case
'
create
'
:
// intentional fallthru
case
'
create
'
:
// intentional fallthru
case
'
update
'
:
case
'
update
'
:
callback
(
null
,
set
(
this
));
callback
(
null
,
set
(
this
));
return
;
return
;
case
'
read
'
:
case
'
read
'
:
callback
(
null
,
get
(
isModel
&&
this
.
get
(
'
id
'
)));
callback
(
null
,
get
(
isModel
&&
this
.
get
(
'
id
'
)));
return
;
return
;
case
'
delete
'
:
case
'
delete
'
:
callback
(
null
,
destroy
(
isModel
&&
this
.
get
(
'
id
'
)));
callback
(
null
,
destroy
(
isModel
&&
this
.
get
(
'
id
'
)));
return
;
return
;
}
}
};
};
}
}
// -- Start your engines! ------------------------------------------------------
// -- Start your engines! ------------------------------------------------------
...
...
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