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
4453ce21
Commit
4453ce21
authored
Apr 03, 2013
by
Stephen Sawchuk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
puremvc updated with bower.
parent
52fa9a06
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
3644 additions
and
8 deletions
+3644
-8
labs/architecture-examples/puremvc/component.json
labs/architecture-examples/puremvc/component.json
+9
-0
labs/architecture-examples/puremvc/components/director/director.js
...itecture-examples/puremvc/components/director/director.js
+712
-0
labs/architecture-examples/puremvc/components/puremvc/puremvc-1.0.1.js
...ture-examples/puremvc/components/puremvc/puremvc-1.0.1.js
+2464
-0
labs/architecture-examples/puremvc/components/todomvc-common/base.css
...cture-examples/puremvc/components/todomvc-common/base.css
+414
-0
labs/architecture-examples/puremvc/components/todomvc-common/base.js
...ecture-examples/puremvc/components/todomvc-common/base.js
+40
-0
labs/architecture-examples/puremvc/components/todomvc-common/bg.png
...tecture-examples/puremvc/components/todomvc-common/bg.png
+0
-0
labs/architecture-examples/puremvc/index.html
labs/architecture-examples/puremvc/index.html
+4
-7
labs/architecture-examples/puremvc/js/view/component/TodoForm.js
...chitecture-examples/puremvc/js/view/component/TodoForm.js
+1
-1
No files found.
labs/architecture-examples/puremvc/component.json
0 → 100644
View file @
4453ce21
{
"name"
:
"todomvc-puremvc"
,
"version"
:
"0.0.0"
,
"dependencies"
:
{
"puremvc"
:
"latest"
,
"director"
:
"~1.2.0"
,
"todomvc-common"
:
"~0.1.2"
}
}
labs/architecture-examples/puremvc/components/director/director.js
0 → 100644
View file @
4453ce21
//
// Generated on Sun Dec 16 2012 22:47:05 GMT-0500 (EST) by Nodejitsu, Inc (Using Codesurgeon).
// Version 1.1.9
//
(
function
(
exports
)
{
/*
* browser.js: Browser specific functionality for director.
*
* (C) 2011, Nodejitsu Inc.
* MIT LICENSE
*
*/
if
(
!
Array
.
prototype
.
filter
)
{
Array
.
prototype
.
filter
=
function
(
filter
,
that
)
{
var
other
=
[],
v
;
for
(
var
i
=
0
,
n
=
this
.
length
;
i
<
n
;
i
++
)
{
if
(
i
in
this
&&
filter
.
call
(
that
,
v
=
this
[
i
],
i
,
this
))
{
other
.
push
(
v
);
}
}
return
other
;
};
}
if
(
!
Array
.
isArray
){
Array
.
isArray
=
function
(
obj
)
{
return
Object
.
prototype
.
toString
.
call
(
obj
)
===
'
[object Array]
'
;
};
}
var
dloc
=
document
.
location
;
function
dlocHashEmpty
()
{
// Non-IE browsers return '' when the address bar shows '#'; Director's logic
// assumes both mean empty.
return
dloc
.
hash
===
''
||
dloc
.
hash
===
'
#
'
;
}
var
listener
=
{
mode
:
'
modern
'
,
hash
:
dloc
.
hash
,
history
:
false
,
check
:
function
()
{
var
h
=
dloc
.
hash
;
if
(
h
!=
this
.
hash
)
{
this
.
hash
=
h
;
this
.
onHashChanged
();
}
},
fire
:
function
()
{
if
(
this
.
mode
===
'
modern
'
)
{
this
.
history
===
true
?
window
.
onpopstate
()
:
window
.
onhashchange
();
}
else
{
this
.
onHashChanged
();
}
},
init
:
function
(
fn
,
history
)
{
var
self
=
this
;
this
.
history
=
history
;
if
(
!
Router
.
listeners
)
{
Router
.
listeners
=
[];
}
function
onchange
(
onChangeEvent
)
{
for
(
var
i
=
0
,
l
=
Router
.
listeners
.
length
;
i
<
l
;
i
++
)
{
Router
.
listeners
[
i
](
onChangeEvent
);
}
}
//note IE8 is being counted as 'modern' because it has the hashchange event
if
(
'
onhashchange
'
in
window
&&
(
document
.
documentMode
===
undefined
||
document
.
documentMode
>
7
))
{
// At least for now HTML5 history is available for 'modern' browsers only
if
(
this
.
history
===
true
)
{
// There is an old bug in Chrome that causes onpopstate to fire even
// upon initial page load. Since the handler is run manually in init(),
// this would cause Chrome to run it twise. Currently the only
// workaround seems to be to set the handler after the initial page load
// http://code.google.com/p/chromium/issues/detail?id=63040
setTimeout
(
function
()
{
window
.
onpopstate
=
onchange
;
},
500
);
}
else
{
window
.
onhashchange
=
onchange
;
}
this
.
mode
=
'
modern
'
;
}
else
{
//
// IE support, based on a concept by Erik Arvidson ...
//
var
frame
=
document
.
createElement
(
'
iframe
'
);
frame
.
id
=
'
state-frame
'
;
frame
.
style
.
display
=
'
none
'
;
document
.
body
.
appendChild
(
frame
);
this
.
writeFrame
(
''
);
if
(
'
onpropertychange
'
in
document
&&
'
attachEvent
'
in
document
)
{
document
.
attachEvent
(
'
onpropertychange
'
,
function
()
{
if
(
event
.
propertyName
===
'
location
'
)
{
self
.
check
();
}
});
}
window
.
setInterval
(
function
()
{
self
.
check
();
},
50
);
this
.
onHashChanged
=
onchange
;
this
.
mode
=
'
legacy
'
;
}
Router
.
listeners
.
push
(
fn
);
return
this
.
mode
;
},
destroy
:
function
(
fn
)
{
if
(
!
Router
||
!
Router
.
listeners
)
{
return
;
}
var
listeners
=
Router
.
listeners
;
for
(
var
i
=
listeners
.
length
-
1
;
i
>=
0
;
i
--
)
{
if
(
listeners
[
i
]
===
fn
)
{
listeners
.
splice
(
i
,
1
);
}
}
},
setHash
:
function
(
s
)
{
// Mozilla always adds an entry to the history
if
(
this
.
mode
===
'
legacy
'
)
{
this
.
writeFrame
(
s
);
}
if
(
this
.
history
===
true
)
{
window
.
history
.
pushState
({},
document
.
title
,
s
);
// Fire an onpopstate event manually since pushing does not obviously
// trigger the pop event.
this
.
fire
();
}
else
{
dloc
.
hash
=
(
s
[
0
]
===
'
/
'
)
?
s
:
'
/
'
+
s
;
}
return
this
;
},
writeFrame
:
function
(
s
)
{
// IE support...
var
f
=
document
.
getElementById
(
'
state-frame
'
);
var
d
=
f
.
contentDocument
||
f
.
contentWindow
.
document
;
d
.
open
();
d
.
write
(
"
<script>_hash = '
"
+
s
+
"
'; onload = parent.listener.syncHash;<script>
"
);
d
.
close
();
},
syncHash
:
function
()
{
// IE support...
var
s
=
this
.
_hash
;
if
(
s
!=
dloc
.
hash
)
{
dloc
.
hash
=
s
;
}
return
this
;
},
onHashChanged
:
function
()
{}
};
var
Router
=
exports
.
Router
=
function
(
routes
)
{
if
(
!
(
this
instanceof
Router
))
return
new
Router
(
routes
);
this
.
params
=
{};
this
.
routes
=
{};
this
.
methods
=
[
'
on
'
,
'
once
'
,
'
after
'
,
'
before
'
];
this
.
scope
=
[];
this
.
_methods
=
{};
this
.
_insert
=
this
.
insert
;
this
.
insert
=
this
.
insertEx
;
this
.
historySupport
=
(
window
.
history
!=
null
?
window
.
history
.
pushState
:
null
)
!=
null
this
.
configure
();
this
.
mount
(
routes
||
{});
};
Router
.
prototype
.
init
=
function
(
r
)
{
var
self
=
this
;
this
.
handler
=
function
(
onChangeEvent
)
{
var
newURL
=
onChangeEvent
&&
onChangeEvent
.
newURL
||
window
.
location
.
hash
;
var
url
=
self
.
history
===
true
?
self
.
getPath
()
:
newURL
.
replace
(
/.*#/
,
''
);
self
.
dispatch
(
'
on
'
,
url
);
};
listener
.
init
(
this
.
handler
,
this
.
history
);
if
(
this
.
history
===
false
)
{
if
(
dlocHashEmpty
()
&&
r
)
{
dloc
.
hash
=
r
;
}
else
if
(
!
dlocHashEmpty
())
{
self
.
dispatch
(
'
on
'
,
dloc
.
hash
.
replace
(
/^#/
,
''
));
}
}
else
{
var
routeTo
=
dlocHashEmpty
()
&&
r
?
r
:
!
dlocHashEmpty
()
?
dloc
.
hash
.
replace
(
/^#/
,
''
)
:
null
;
if
(
routeTo
)
{
window
.
history
.
replaceState
({},
document
.
title
,
routeTo
);
}
// Router has been initialized, but due to the chrome bug it will not
// yet actually route HTML5 history state changes. Thus, decide if should route.
if
(
routeTo
||
this
.
run_in_init
===
true
)
{
this
.
handler
();
}
}
return
this
;
};
Router
.
prototype
.
explode
=
function
()
{
var
v
=
this
.
history
===
true
?
this
.
getPath
()
:
dloc
.
hash
;
if
(
v
.
charAt
(
1
)
===
'
/
'
)
{
v
=
v
.
slice
(
1
)
}
return
v
.
slice
(
1
,
v
.
length
).
split
(
"
/
"
);
};
Router
.
prototype
.
setRoute
=
function
(
i
,
v
,
val
)
{
var
url
=
this
.
explode
();
if
(
typeof
i
===
'
number
'
&&
typeof
v
===
'
string
'
)
{
url
[
i
]
=
v
;
}
else
if
(
typeof
val
===
'
string
'
)
{
url
.
splice
(
i
,
v
,
s
);
}
else
{
url
=
[
i
];
}
listener
.
setHash
(
url
.
join
(
'
/
'
));
return
url
;
};
//
// ### function insertEx(method, path, route, parent)
// #### @method {string} Method to insert the specific `route`.
// #### @path {Array} Parsed path to insert the `route` at.
// #### @route {Array|function} Route handlers to insert.
// #### @parent {Object} **Optional** Parent "routes" to insert into.
// insert a callback that will only occur once per the matched route.
//
Router
.
prototype
.
insertEx
=
function
(
method
,
path
,
route
,
parent
)
{
if
(
method
===
"
once
"
)
{
method
=
"
on
"
;
route
=
function
(
route
)
{
var
once
=
false
;
return
function
()
{
if
(
once
)
return
;
once
=
true
;
return
route
.
apply
(
this
,
arguments
);
};
}(
route
);
}
return
this
.
_insert
(
method
,
path
,
route
,
parent
);
};
Router
.
prototype
.
getRoute
=
function
(
v
)
{
var
ret
=
v
;
if
(
typeof
v
===
"
number
"
)
{
ret
=
this
.
explode
()[
v
];
}
else
if
(
typeof
v
===
"
string
"
){
var
h
=
this
.
explode
();
ret
=
h
.
indexOf
(
v
);
}
else
{
ret
=
this
.
explode
();
}
return
ret
;
};
Router
.
prototype
.
destroy
=
function
()
{
listener
.
destroy
(
this
.
handler
);
return
this
;
};
Router
.
prototype
.
getPath
=
function
()
{
var
path
=
window
.
location
.
pathname
;
if
(
path
.
substr
(
0
,
1
)
!==
'
/
'
)
{
path
=
'
/
'
+
path
;
}
return
path
;
};
function
_every
(
arr
,
iterator
)
{
for
(
var
i
=
0
;
i
<
arr
.
length
;
i
+=
1
)
{
if
(
iterator
(
arr
[
i
],
i
,
arr
)
===
false
)
{
return
;
}
}
}
function
_flatten
(
arr
)
{
var
flat
=
[];
for
(
var
i
=
0
,
n
=
arr
.
length
;
i
<
n
;
i
++
)
{
flat
=
flat
.
concat
(
arr
[
i
]);
}
return
flat
;
}
function
_asyncEverySeries
(
arr
,
iterator
,
callback
)
{
if
(
!
arr
.
length
)
{
return
callback
();
}
var
completed
=
0
;
(
function
iterate
()
{
iterator
(
arr
[
completed
],
function
(
err
)
{
if
(
err
||
err
===
false
)
{
callback
(
err
);
callback
=
function
()
{};
}
else
{
completed
+=
1
;
if
(
completed
===
arr
.
length
)
{
callback
();
}
else
{
iterate
();
}
}
});
})();
}
function
paramifyString
(
str
,
params
,
mod
)
{
mod
=
str
;
for
(
var
param
in
params
)
{
if
(
params
.
hasOwnProperty
(
param
))
{
mod
=
params
[
param
](
str
);
if
(
mod
!==
str
)
{
break
;
}
}
}
return
mod
===
str
?
"
([._a-zA-Z0-9-]+)
"
:
mod
;
}
function
regifyString
(
str
,
params
)
{
var
matches
,
last
=
0
,
out
=
""
;
while
(
matches
=
str
.
substr
(
last
).
match
(
/
[^\w\d\-
%@&
]
*
\*[^\w\d\-
%@&
]
*/
))
{
last
=
matches
.
index
+
matches
[
0
].
length
;
matches
[
0
]
=
matches
[
0
].
replace
(
/^
\*
/
,
"
([_.()!
\\
%@&a-zA-Z0-9-]+)
"
);
out
+=
str
.
substr
(
0
,
matches
.
index
)
+
matches
[
0
];
}
str
=
out
+=
str
.
substr
(
last
);
var
captures
=
str
.
match
(
/:
([^\/]
+
)
/ig
),
length
;
if
(
captures
)
{
length
=
captures
.
length
;
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
str
=
str
.
replace
(
captures
[
i
],
paramifyString
(
captures
[
i
],
params
));
}
}
return
str
;
}
function
terminator
(
routes
,
delimiter
,
start
,
stop
)
{
var
last
=
0
,
left
=
0
,
right
=
0
,
start
=
(
start
||
"
(
"
).
toString
(),
stop
=
(
stop
||
"
)
"
).
toString
(),
i
;
for
(
i
=
0
;
i
<
routes
.
length
;
i
++
)
{
var
chunk
=
routes
[
i
];
if
(
chunk
.
indexOf
(
start
,
last
)
>
chunk
.
indexOf
(
stop
,
last
)
||
~
chunk
.
indexOf
(
start
,
last
)
&&
!~
chunk
.
indexOf
(
stop
,
last
)
||
!~
chunk
.
indexOf
(
start
,
last
)
&&
~
chunk
.
indexOf
(
stop
,
last
))
{
left
=
chunk
.
indexOf
(
start
,
last
);
right
=
chunk
.
indexOf
(
stop
,
last
);
if
(
~
left
&&
!~
right
||
!~
left
&&
~
right
)
{
var
tmp
=
routes
.
slice
(
0
,
(
i
||
1
)
+
1
).
join
(
delimiter
);
routes
=
[
tmp
].
concat
(
routes
.
slice
((
i
||
1
)
+
1
));
}
last
=
(
right
>
left
?
right
:
left
)
+
1
;
i
=
0
;
}
else
{
last
=
0
;
}
}
return
routes
;
}
Router
.
prototype
.
configure
=
function
(
options
)
{
options
=
options
||
{};
for
(
var
i
=
0
;
i
<
this
.
methods
.
length
;
i
++
)
{
this
.
_methods
[
this
.
methods
[
i
]]
=
true
;
}
this
.
recurse
=
options
.
recurse
||
this
.
recurse
||
false
;
this
.
async
=
options
.
async
||
false
;
this
.
delimiter
=
options
.
delimiter
||
"
/
"
;
this
.
strict
=
typeof
options
.
strict
===
"
undefined
"
?
true
:
options
.
strict
;
this
.
notfound
=
options
.
notfound
;
this
.
resource
=
options
.
resource
;
this
.
history
=
options
.
html5history
&&
this
.
historySupport
||
false
;
this
.
run_in_init
=
this
.
history
===
true
&&
options
.
run_handler_in_init
!==
false
;
this
.
every
=
{
after
:
options
.
after
||
null
,
before
:
options
.
before
||
null
,
on
:
options
.
on
||
null
};
return
this
;
};
Router
.
prototype
.
param
=
function
(
token
,
matcher
)
{
if
(
token
[
0
]
!==
"
:
"
)
{
token
=
"
:
"
+
token
;
}
var
compiled
=
new
RegExp
(
token
,
"
g
"
);
this
.
params
[
token
]
=
function
(
str
)
{
return
str
.
replace
(
compiled
,
matcher
.
source
||
matcher
);
};
};
Router
.
prototype
.
on
=
Router
.
prototype
.
route
=
function
(
method
,
path
,
route
)
{
var
self
=
this
;
if
(
!
route
&&
typeof
path
==
"
function
"
)
{
route
=
path
;
path
=
method
;
method
=
"
on
"
;
}
if
(
Array
.
isArray
(
path
))
{
return
path
.
forEach
(
function
(
p
)
{
self
.
on
(
method
,
p
,
route
);
});
}
if
(
path
.
source
)
{
path
=
path
.
source
.
replace
(
/
\\\/
/ig
,
"
/
"
);
}
if
(
Array
.
isArray
(
method
))
{
return
method
.
forEach
(
function
(
m
)
{
self
.
on
(
m
.
toLowerCase
(),
path
,
route
);
});
}
path
=
path
.
split
(
new
RegExp
(
this
.
delimiter
));
path
=
terminator
(
path
,
this
.
delimiter
);
this
.
insert
(
method
,
this
.
scope
.
concat
(
path
),
route
);
};
Router
.
prototype
.
dispatch
=
function
(
method
,
path
,
callback
)
{
var
self
=
this
,
fns
=
this
.
traverse
(
method
,
path
,
this
.
routes
,
""
),
invoked
=
this
.
_invoked
,
after
;
this
.
_invoked
=
true
;
if
(
!
fns
||
fns
.
length
===
0
)
{
this
.
last
=
[];
if
(
typeof
this
.
notfound
===
"
function
"
)
{
this
.
invoke
([
this
.
notfound
],
{
method
:
method
,
path
:
path
},
callback
);
}
return
false
;
}
if
(
this
.
recurse
===
"
forward
"
)
{
fns
=
fns
.
reverse
();
}
function
updateAndInvoke
()
{
self
.
last
=
fns
.
after
;
self
.
invoke
(
self
.
runlist
(
fns
),
self
,
callback
);
}
after
=
this
.
every
&&
this
.
every
.
after
?
[
this
.
every
.
after
].
concat
(
this
.
last
)
:
[
this
.
last
];
if
(
after
&&
after
.
length
>
0
&&
invoked
)
{
if
(
this
.
async
)
{
this
.
invoke
(
after
,
this
,
updateAndInvoke
);
}
else
{
this
.
invoke
(
after
,
this
);
updateAndInvoke
();
}
return
true
;
}
updateAndInvoke
();
return
true
;
};
Router
.
prototype
.
invoke
=
function
(
fns
,
thisArg
,
callback
)
{
var
self
=
this
;
if
(
this
.
async
)
{
_asyncEverySeries
(
fns
,
function
apply
(
fn
,
next
)
{
if
(
Array
.
isArray
(
fn
))
{
return
_asyncEverySeries
(
fn
,
apply
,
next
);
}
else
if
(
typeof
fn
==
"
function
"
)
{
fn
.
apply
(
thisArg
,
fns
.
captures
.
concat
(
next
));
}
},
function
()
{
if
(
callback
)
{
callback
.
apply
(
thisArg
,
arguments
);
}
});
}
else
{
_every
(
fns
,
function
apply
(
fn
)
{
if
(
Array
.
isArray
(
fn
))
{
return
_every
(
fn
,
apply
);
}
else
if
(
typeof
fn
===
"
function
"
)
{
return
fn
.
apply
(
thisArg
,
fns
.
captures
||
[]);
}
else
if
(
typeof
fn
===
"
string
"
&&
self
.
resource
)
{
self
.
resource
[
fn
].
apply
(
thisArg
,
fns
.
captures
||
[]);
}
});
}
};
Router
.
prototype
.
traverse
=
function
(
method
,
path
,
routes
,
regexp
,
filter
)
{
var
fns
=
[],
current
,
exact
,
match
,
next
,
that
;
function
filterRoutes
(
routes
)
{
if
(
!
filter
)
{
return
routes
;
}
function
deepCopy
(
source
)
{
var
result
=
[];
for
(
var
i
=
0
;
i
<
source
.
length
;
i
++
)
{
result
[
i
]
=
Array
.
isArray
(
source
[
i
])
?
deepCopy
(
source
[
i
])
:
source
[
i
];
}
return
result
;
}
function
applyFilter
(
fns
)
{
for
(
var
i
=
fns
.
length
-
1
;
i
>=
0
;
i
--
)
{
if
(
Array
.
isArray
(
fns
[
i
]))
{
applyFilter
(
fns
[
i
]);
if
(
fns
[
i
].
length
===
0
)
{
fns
.
splice
(
i
,
1
);
}
}
else
{
if
(
!
filter
(
fns
[
i
]))
{
fns
.
splice
(
i
,
1
);
}
}
}
}
var
newRoutes
=
deepCopy
(
routes
);
newRoutes
.
matched
=
routes
.
matched
;
newRoutes
.
captures
=
routes
.
captures
;
newRoutes
.
after
=
routes
.
after
.
filter
(
filter
);
applyFilter
(
newRoutes
);
return
newRoutes
;
}
if
(
path
===
this
.
delimiter
&&
routes
[
method
])
{
next
=
[
[
routes
.
before
,
routes
[
method
]
].
filter
(
Boolean
)
];
next
.
after
=
[
routes
.
after
].
filter
(
Boolean
);
next
.
matched
=
true
;
next
.
captures
=
[];
return
filterRoutes
(
next
);
}
for
(
var
r
in
routes
)
{
if
(
routes
.
hasOwnProperty
(
r
)
&&
(
!
this
.
_methods
[
r
]
||
this
.
_methods
[
r
]
&&
typeof
routes
[
r
]
===
"
object
"
&&
!
Array
.
isArray
(
routes
[
r
])))
{
current
=
exact
=
regexp
+
this
.
delimiter
+
r
;
if
(
!
this
.
strict
)
{
exact
+=
"
[
"
+
this
.
delimiter
+
"
]?
"
;
}
match
=
path
.
match
(
new
RegExp
(
"
^
"
+
exact
));
if
(
!
match
)
{
continue
;
}
if
(
match
[
0
]
&&
match
[
0
]
==
path
&&
routes
[
r
][
method
])
{
next
=
[
[
routes
[
r
].
before
,
routes
[
r
][
method
]
].
filter
(
Boolean
)
];
next
.
after
=
[
routes
[
r
].
after
].
filter
(
Boolean
);
next
.
matched
=
true
;
next
.
captures
=
match
.
slice
(
1
);
if
(
this
.
recurse
&&
routes
===
this
.
routes
)
{
next
.
push
([
routes
.
before
,
routes
.
on
].
filter
(
Boolean
));
next
.
after
=
next
.
after
.
concat
([
routes
.
after
].
filter
(
Boolean
));
}
return
filterRoutes
(
next
);
}
next
=
this
.
traverse
(
method
,
path
,
routes
[
r
],
current
);
if
(
next
.
matched
)
{
if
(
next
.
length
>
0
)
{
fns
=
fns
.
concat
(
next
);
}
if
(
this
.
recurse
)
{
fns
.
push
([
routes
[
r
].
before
,
routes
[
r
].
on
].
filter
(
Boolean
));
next
.
after
=
next
.
after
.
concat
([
routes
[
r
].
after
].
filter
(
Boolean
));
if
(
routes
===
this
.
routes
)
{
fns
.
push
([
routes
[
"
before
"
],
routes
[
"
on
"
]
].
filter
(
Boolean
));
next
.
after
=
next
.
after
.
concat
([
routes
[
"
after
"
]
].
filter
(
Boolean
));
}
}
fns
.
matched
=
true
;
fns
.
captures
=
next
.
captures
;
fns
.
after
=
next
.
after
;
return
filterRoutes
(
fns
);
}
}
}
return
false
;
};
Router
.
prototype
.
insert
=
function
(
method
,
path
,
route
,
parent
)
{
var
methodType
,
parentType
,
isArray
,
nested
,
part
;
path
=
path
.
filter
(
function
(
p
)
{
return
p
&&
p
.
length
>
0
;
});
parent
=
parent
||
this
.
routes
;
part
=
path
.
shift
();
if
(
/
\:
|
\*
/
.
test
(
part
)
&&
!
/
\\
d|
\\
w/
.
test
(
part
))
{
part
=
regifyString
(
part
,
this
.
params
);
}
if
(
path
.
length
>
0
)
{
parent
[
part
]
=
parent
[
part
]
||
{};
return
this
.
insert
(
method
,
path
,
route
,
parent
[
part
]);
}
if
(
!
part
&&
!
path
.
length
&&
parent
===
this
.
routes
)
{
methodType
=
typeof
parent
[
method
];
switch
(
methodType
)
{
case
"
function
"
:
parent
[
method
]
=
[
parent
[
method
],
route
];
return
;
case
"
object
"
:
parent
[
method
].
push
(
route
);
return
;
case
"
undefined
"
:
parent
[
method
]
=
route
;
return
;
}
return
;
}
parentType
=
typeof
parent
[
part
];
isArray
=
Array
.
isArray
(
parent
[
part
]);
if
(
parent
[
part
]
&&
!
isArray
&&
parentType
==
"
object
"
)
{
methodType
=
typeof
parent
[
part
][
method
];
switch
(
methodType
)
{
case
"
function
"
:
parent
[
part
][
method
]
=
[
parent
[
part
][
method
],
route
];
return
;
case
"
object
"
:
parent
[
part
][
method
].
push
(
route
);
return
;
case
"
undefined
"
:
parent
[
part
][
method
]
=
route
;
return
;
}
}
else
if
(
parentType
==
"
undefined
"
)
{
nested
=
{};
nested
[
method
]
=
route
;
parent
[
part
]
=
nested
;
return
;
}
throw
new
Error
(
"
Invalid route context:
"
+
parentType
);
};
Router
.
prototype
.
extend
=
function
(
methods
)
{
var
self
=
this
,
len
=
methods
.
length
,
i
;
function
extend
(
method
)
{
self
.
_methods
[
method
]
=
true
;
self
[
method
]
=
function
()
{
var
extra
=
arguments
.
length
===
1
?
[
method
,
""
]
:
[
method
];
self
.
on
.
apply
(
self
,
extra
.
concat
(
Array
.
prototype
.
slice
.
call
(
arguments
)));
};
}
for
(
i
=
0
;
i
<
len
;
i
++
)
{
extend
(
methods
[
i
]);
}
};
Router
.
prototype
.
runlist
=
function
(
fns
)
{
var
runlist
=
this
.
every
&&
this
.
every
.
before
?
[
this
.
every
.
before
].
concat
(
_flatten
(
fns
))
:
_flatten
(
fns
);
if
(
this
.
every
&&
this
.
every
.
on
)
{
runlist
.
push
(
this
.
every
.
on
);
}
runlist
.
captures
=
fns
.
captures
;
runlist
.
source
=
fns
.
source
;
return
runlist
;
};
Router
.
prototype
.
mount
=
function
(
routes
,
path
)
{
if
(
!
routes
||
typeof
routes
!==
"
object
"
||
Array
.
isArray
(
routes
))
{
return
;
}
var
self
=
this
;
path
=
path
||
[];
if
(
!
Array
.
isArray
(
path
))
{
path
=
path
.
split
(
self
.
delimiter
);
}
function
insertOrMount
(
route
,
local
)
{
var
rename
=
route
,
parts
=
route
.
split
(
self
.
delimiter
),
routeType
=
typeof
routes
[
route
],
isRoute
=
parts
[
0
]
===
""
||
!
self
.
_methods
[
parts
[
0
]],
event
=
isRoute
?
"
on
"
:
rename
;
if
(
isRoute
)
{
rename
=
rename
.
slice
((
rename
.
match
(
new
RegExp
(
self
.
delimiter
))
||
[
""
])[
0
].
length
);
parts
.
shift
();
}
if
(
isRoute
&&
routeType
===
"
object
"
&&
!
Array
.
isArray
(
routes
[
route
]))
{
local
=
local
.
concat
(
parts
);
self
.
mount
(
routes
[
route
],
local
);
return
;
}
if
(
isRoute
)
{
local
=
local
.
concat
(
rename
.
split
(
self
.
delimiter
));
local
=
terminator
(
local
,
self
.
delimiter
);
}
self
.
insert
(
event
,
local
,
routes
[
route
]);
}
for
(
var
route
in
routes
)
{
if
(
routes
.
hasOwnProperty
(
route
))
{
insertOrMount
(
route
,
path
.
slice
(
0
));
}
}
};
}(
typeof
exports
===
"
object
"
?
exports
:
window
));
\ No newline at end of file
labs/architecture-examples/puremvc/components/puremvc/puremvc-1.0.1.js
0 → 100644
View file @
4453ce21
/**
* @fileOverview
* PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
* Reuse governed by Creative Commons Attribution 3.0
* http://creativecommons.org/licenses/by/3.0/us/
* @author david.foley@puremvc.org
*/
(
function
(
scope
){
if
(
null
==
scope
)
scope
=
window
;
// if the global puremvc namespace already exists, turn back now
if
(
scope
.
puremvc
)
{
return
;
}
/* implementation begin */
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.Observer
*
* A base Observer implementation.
*
* An Observer is an object that encapsulates information
* about an interested object with a method that should
* be called when a particular Notification is broadcast.
*
* In PureMVC, the Observer class assumes these responsibilities:
*
* - Encapsulate the notification (callback) method of the interested object.
* - Encapsulate the notification context (this) of the interested object.
* - Provide methods for setting the notification method and context.
* - Provide a method for notifying the interested object.
*
*
* The notification method on the interested object should take
* one parameter of type Notification.
*
*
* @param {Function} notifyMethod
* the notification method of the interested object
* @param {Object} notifyContext
* the notification context of the interested object
* @constructor
*/
function
Observer
(
notifyMethod
,
notifyContext
)
{
this
.
setNotifyMethod
(
notifyMethod
);
this
.
setNotifyContext
(
notifyContext
);
};
/**
* Set the Observers notification method.
*
* The notification method should take one parameter of type Notification
* @param {Function} notifyMethod
* the notification (callback) method of the interested object.
* @return {void}
*/
Observer
.
prototype
.
setNotifyMethod
=
function
(
notifyMethod
)
{
this
.
notify
=
notifyMethod
;
};
/**
* Set the Observers notification context.
*
* @param {Object} notifyContext
* the notification context (this) of the interested object.
*
* @return {void}
*/
Observer
.
prototype
.
setNotifyContext
=
function
(
notifyContext
)
{
this
.
context
=
notifyContext
;
};
/**
* Get the Function that this Observer will invoke when it is notified.
*
* @private
* @return {Function}
*/
Observer
.
prototype
.
getNotifyMethod
=
function
()
{
return
this
.
notify
;
};
/**
* Get the Object that will serve as the Observers callback execution context
*
* @private
* @return {Object}
*/
Observer
.
prototype
.
getNotifyContext
=
function
()
{
return
this
.
context
;
};
/**
* Notify the interested object.
*
* @param {puremvc.Notification} notification
* The Notification to pass to the interested objects notification method
* @return {void}
*/
Observer
.
prototype
.
notifyObserver
=
function
(
notification
)
{
this
.
getNotifyMethod
().
call
(
this
.
getNotifyContext
(),
notification
);
};
/**
* Compare an object to this Observers notification context.
*
* @param {Object} object
*
* @return {boolean}
*/
Observer
.
prototype
.
compareNotifyContext
=
function
(
object
)
{
return
object
===
this
.
context
;
};
/**
* The Observers callback Function
*
* @private
* @type {Function}
*/
Observer
.
prototype
.
notify
=
null
;
/**
* The Observers callback Object
* @private
* @type {Object}
*/
Observer
.
prototype
.
context
=
null
;
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.Notification
*
* A base Notification implementation.
*
* PureMVC does not rely upon underlying event models such as the one provided
* with the DOM or other browser centric W3C event models.
*
* The Observer Pattern as implemented within PureMVC exists to support
* event-driven communication between the application and the actors of the MVC
* triad.
*
* Notifications are not meant to be a replacement for events in the browser.
* Generally, Mediator implementors place event listeners on their view
* components, which they then handle in the usual way. This may lead to the
* broadcast of Notifications to trigger commands or to communicate with other
* Mediators. {@link puremvc.Proxy Proxy},
* {@link puremvc.SimpleCommand SimpleCommand}
* and {@link puremvc.MacroCommand MacroCommand}
* instances communicate with each other and
* {@link puremvc.Mediator Mediator}s
* by broadcasting Notifications.
*
* A key difference between browser events and PureMVC Notifications is that
* events follow the 'Chain of Responsibility' pattern, 'bubbling' up the
* display hierarchy until some parent component handles the event, while
* PureMVC Notification follow a 'Publish/Subscribe' pattern. PureMVC classes
* need not be related to each other in a parent/child relationship in order to
* communicate with one another using Notifications.
*
* @constructor
* @param {string} name
* The Notification name
* @param {Object} [body]
* The Notification body
* @param {Object} [type]
* The Notification type
*/
function
Notification
(
name
,
body
,
type
)
{
this
.
name
=
name
;
this
.
body
=
body
;
this
.
type
=
type
;
};
/**
* Get the name of the Notification instance
*
* @return {string}
* The name of the Notification instance
*/
Notification
.
prototype
.
getName
=
function
()
{
return
this
.
name
;
};
/**
* Set this Notifications body.
* @param {Object} body
* @return {void}
*/
Notification
.
prototype
.
setBody
=
function
(
body
)
{
this
.
body
=
body
;
};
/**
* Get the Notification body.
*
* @return {Object}
*/
Notification
.
prototype
.
getBody
=
function
()
{
return
this
.
body
};
/**
* Set the type of the Notification instance.
*
* @param {Object} type
* @return {void}
*/
Notification
.
prototype
.
setType
=
function
(
type
)
{
this
.
type
=
type
;
};
/**
* Get the type of the Notification instance.
*
* @return {Object}
*/
Notification
.
prototype
.
getType
=
function
()
{
return
this
.
type
;
};
/**
* Get a string representation of the Notification instance
*
* @return {string}
*/
Notification
.
prototype
.
toString
=
function
()
{
var
msg
=
"
Notification Name:
"
+
this
.
getName
();
msg
+=
"
\n
Body:
"
+
((
this
.
body
==
null
)
?
"
null
"
:
this
.
body
.
toString
());
msg
+=
"
\n
Type:
"
+
((
this
.
type
==
null
)
?
"
null
"
:
this
.
type
);
return
msg
;
};
/**
* The Notifications name.
*
* @type {string}
* @private
*/
Notification
.
prototype
.
name
=
null
;
/**
* The Notifications type.
*
* @type {string}
* @private
*/
Notification
.
prototype
.
type
=
null
;
/**
* The Notifications body.
*
* @type {Object}
* @private
*/
Notification
.
prototype
.
body
=
null
;
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.Notifier
*
* A Base Notifier implementation.
*
* {@link puremvc.MacroCommand MacroCommand},
* {@link puremvc.SimpleCommand SimpleCommand},
* {@link puremvc.Mediator Mediator} and
* {@link puremvc.Proxy Proxy}
* all have a need to send Notifications
*
* The Notifier interface provides a common method called #sendNotification that
* relieves implementation code of the necessity to actually construct
* Notifications.
*
* The Notifier class, which all of the above mentioned classes
* extend, provides an initialized reference to the
* {@link puremvc.Facade Facade}
* Multiton, which is required for the convienience method
* for sending Notifications but also eases implementation as these
* classes have frequent
* {@link puremvc.Facade Facade} interactions
* and usually require access to the facade anyway.
*
* NOTE: In the MultiCore version of the framework, there is one caveat to
* notifiers, they cannot send notifications or reach the facade until they
* have a valid multitonKey.
*
* The multitonKey is set:
* - on a Command when it is executed by the Controller
* - on a Mediator is registered with the View
* - on a Proxy is registered with the Model.
*
* @constructor
*/
function
Notifier
()
{
};
/**
* Create and send a Notification.
*
* Keeps us from having to construct new Notification instances in our
* implementation code.
*
* @param {string} notificationName
* A notification name
* @param {Object} [body]
* The body of the notification
* @param {string} [type]
* The notification type
* @return {void}
*/
Notifier
.
prototype
.
sendNotification
=
function
(
notificationName
,
body
,
type
)
{
var
facade
=
this
.
getFacade
();
if
(
facade
)
{
facade
.
sendNotification
(
notificationName
,
body
,
type
);
}
};
/**
* @protected
* A reference to this Notifier's Facade. This reference will not be available
* until #initializeNotifier has been called.
*
* @type {puremvc.Facade}
*/
Notifier
.
prototype
.
facade
;
/**
* Initialize this Notifier instance.
*
* This is how a Notifier gets its multitonKey.
* Calls to #sendNotification or to access the
* facade will fail until after this method
* has been called.
*
* Mediators, Commands or Proxies may override
* this method in order to send notifications
* or access the Multiton Facade instance as
* soon as possible. They CANNOT access the facade
* in their constructors, since this method will not
* yet have been called.
*
*
* @param {string} key
* The Notifiers multiton key;
* @return {void}
*/
Notifier
.
prototype
.
initializeNotifier
=
function
(
key
)
{
this
.
multitonKey
=
String
(
key
);
this
.
facade
=
this
.
getFacade
();
};
/**
* Retrieve the Multiton Facade instance
*
*
* @protected
* @return {puremvc.Facade}
*/
Notifier
.
prototype
.
getFacade
=
function
()
{
if
(
this
.
multitonKey
==
null
)
{
throw
new
Error
(
Notifier
.
MULTITON_MSG
);
};
return
Facade
.
getInstance
(
this
.
multitonKey
);
};
/**
* @ignore
* The Notifiers internal multiton key.
*
* @protected
* @type string
*/
Notifier
.
prototype
.
multitonKey
=
null
;
/**
* @ignore
* The error message used if the Notifier is not initialized correctly and
* attempts to retrieve its own multiton key
*
* @static
* @protected
* @const
* @type string
*/
Notifier
.
MULTITON_MSG
=
"
multitonKey for this Notifier not yet initialized!
"
;
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.SimpleCommand
* @extends puremvc.Notifier
*
* SimpleCommands encapsulate the business logic of your application. Your
* subclass should override the #execute method where your business logic will
* handle the
* {@link puremvc.Notification Notification}
*
* Take a look at
* {@link puremvc.Facade#registerCommand Facade's registerCommand}
* or {@link puremvc.Controller#registerCommand Controllers registerCommand}
* methods to see how to add commands to your application.
*
* @constructor
*/
function
SimpleCommand
()
{
};
SimpleCommand
.
prototype
=
new
Notifier
;
SimpleCommand
.
prototype
.
constructor
=
SimpleCommand
;
/**
* Fulfill the use-case initiated by the given Notification
*
* In the Command Pattern, an application use-case typically begins with some
* user action, which results in a Notification is handled by the business logic
* in the #execute method of a command.
*
* @param {puremvc.Notification} notification
* The notification to handle.
* @return {void}
*/
SimpleCommand
.
prototype
.
execute
=
function
(
notification
)
{
};
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.MacroCommand
* @extends puremvc.Notifier
*
* A base command implementation that executes other commands, such as
* {@link puremvc.SimpleCommand SimpleCommand}
* or {@link puremvc.MacroCommand MacroCommand}
* subclasses.
*
* A MacroCommand maintains an list of
* command constructor references called *SubCommands*.
*
* When #execute is called, the MacroCommand
* instantiates and calls #execute on each of its *SubCommands* in turn.
* Each *SubCommand* will be passed a reference to the original
* {@link puremvc.Notification Notification}
* that was passed to the MacroCommands #execute method
*
* Unlike {@link puremvc.SimpleCommand SimpleCommand},
* your subclass should not override #execute but instead, should
* override the #initializeMacroCommand method, calling #addSubCommand once for
* each *SubCommand* to be executed.
*
* If your subclass does define a constructor, be sure to call "super" like so
*
* function MyMacroCommand ()
* {
* MacroCommand.call(this);
* };
* @constructor
*/
function
MacroCommand
()
{
this
.
subCommands
=
[];
this
.
initializeMacroCommand
();
};
/* subclass Notifier */
MacroCommand
.
prototype
=
new
Notifier
;
MacroCommand
.
prototype
.
constructor
=
MacroCommand
;
/**
* @private
* @type {Array.<puremvc.SimpleCommand|puremvc.MacroCommand>}
*/
MacroCommand
.
prototype
.
subCommands
=
null
;
/**
* @protected
* Initialize the MacroCommand.
*
* In your subclass, override this method to
* initialize the MacroCommand's *SubCommand*
* list with command class references like
* this:
*
* // Initialize MyMacroCommand
* MyMacroCommand.prototype.initializeMacroCommand= function ()
* {
* this.addSubCommand( com.me.myapp.controller.FirstCommand );
* this.addSubCommand( com.me.myapp.controller.SecondCommand );
* this.addSubCommand( com.me.myapp.controller.ThirdCommand );
* };
*
* Note that *SubCommand*s may be any command implementor,
* MacroCommands or SimpleCommands are both acceptable.
* @return {void}
*/
MacroCommand
.
prototype
.
initializeMacroCommand
=
function
()
{}
/**
* @protected
* Add a *SubCommand*
*
* The *SubCommand*s will be called in First In / First Out (FIFO) order
* @param {Function} commandClassRef
* A reference to a subclassed SimpleCommand or MacroCommand constructor
*/
MacroCommand
.
prototype
.
addSubCommand
=
function
(
commandClassRef
)
{
this
.
subCommands
.
push
(
commandClassRef
);
};
/**
* Execute this MacroCommands *SubCommands*
*
* The *SubCommand*s will be called in First In / First Out (FIFO) order
* @param {puremvc.Notification} note
* The Notification object to be passed to each *SubCommand*
*/
MacroCommand
.
prototype
.
execute
=
function
(
note
)
{
// SIC- TODO optimize
while
(
this
.
subCommands
.
length
>
0
)
{
var
ref
=
this
.
subCommands
.
shift
();
var
cmd
=
new
ref
;
cmd
.
initializeNotifier
(
this
.
multitonKey
);
cmd
.
execute
(
note
);
}
};
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.Mediator
* @extends puremvc.Notifier
*
* A base Mediator implementation.
*
* In PureMVC, Mediator classes are used to mediate communication between a view
* component and the rest of the application.
*
* A Mediator should listen to its view components for events, and handle them
* by sending notifications (to be handled by other Mediators,
* {@link puremvc.SimpleCommand SimpleCommands}
* or
* {@link puremvc.MacroCommand MacroCommands})
* or passing data from the view component directly to a
* {@link puremvc.Proxy Proxy}, such as submitting
* the contents of a form to a service.
*
* Mediators should not perform business logic, maintain state or other
* information for its view component, or break the encapsulation of the view
* component by manipulating the view component's children. It should only call
* methods or set properties on the view component.
*
* The view component should encapsulate its own behavior and implementation by
* exposing methods and properties that the Mediator can call without having to
* know about the view component's children.
*
* @constructor
* @param {string} [mediatorName]
* The Mediators name. The Mediators static #NAME value is used by default
* @param {Object} [viewComponent]
* The Mediators {@link #setViewComponent viewComponent}.
*/
function
Mediator
(
mediatorName
,
viewComponent
)
{
this
.
mediatorName
=
mediatorName
||
this
.
constructor
.
NAME
;
this
.
viewComponent
=
viewComponent
;
};
/**
* @static
* The name of the Mediator.
*
* Typically, a Mediator will be written to serve one specific control or group
* of controls and so, will not have a need to be dynamically named.
*
* @type {string}
*/
Mediator
.
NAME
=
"
Mediator
"
;
/* subclass */
Mediator
.
prototype
=
new
Notifier
;
Mediator
.
prototype
.
constructor
=
Mediator
;
/**
* Get the name of the Mediator
*
* @return {string}
* The Mediator name
*/
Mediator
.
prototype
.
getMediatorName
=
function
()
{
return
this
.
mediatorName
;
};
/**
* Set the Mediators view component. This could
* be a HTMLElement, a bespoke UiComponent wrapper
* class, a MooTools Element, a jQuery result or a
* css selector, depending on which DOM abstraction
* library you are using.
*
*
* @param {Object} the view component
* @return {void}
*/
Mediator
.
prototype
.
setViewComponent
=
function
(
viewComponent
)
{
this
.
viewComponent
=
viewComponent
;
};
/**
* Get the Mediators view component.
*
* Additionally, an optional explicit getter can be
* be defined in the subclass that defines the
* view components, providing a more semantic interface
* to the Mediator.
*
* This is different from the AS3 implementation in
* the sense that no casting is required from the
* object supplied as the view component.
*
* MyMediator.prototype.getComboBox= function ()
* {
* return this.viewComponent;
* }
*
* @return {Object}
* The view component
*/
Mediator
.
prototype
.
getViewComponent
=
function
()
{
return
this
.
viewComponent
;
};
/**
* List the Notification names this Mediator is interested
* in being notified of.
*
* @return {Array}
* The list of Notification names.
*/
Mediator
.
prototype
.
listNotificationInterests
=
function
()
{
return
[];
};
/**
* Handle Notifications.
*
* Typically this will be handled in a switch statement
* with one 'case' entry per Notification the Mediator
* is interested in
*
* @param {puremvc.Notification} notification
* @return {void}
*/
Mediator
.
prototype
.
handleNotification
=
function
(
notification
)
{
return
;
};
/**
* Called by the View when the Mediator is registered
* @return {void}
*/
Mediator
.
prototype
.
onRegister
=
function
()
{
return
;
};
/**
* Called by the View when the Mediator is removed
*/
Mediator
.
prototype
.
onRemove
=
function
()
{
return
;
};
/**
* @ignore
* The Mediators name. Should only be accessed by Mediator subclasses.
*
* @protected
* @type string
*/
Mediator
.
prototype
.
mediatorName
=
null
;
/**
* @ignore
* The Mediators viewComponent. Should only be accessed by Mediator subclasses.
*
* @protected
* @type Object
*/
Mediator
.
prototype
.
viewComponent
=
null
;
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.Proxy
* @extends puremvc.Notifier
*
* A base Proxy implementation.
*
* In PureMVC, Proxy classes are used to manage parts of the application's data
* model.
*
* A Proxy might simply manage a reference to a local data object, in which case
* interacting with it might involve setting and getting of its data in
* synchronous fashion.
*
* Proxy classes are also used to encapsulate the application's interaction with
* remote services to save or retrieve data, in which case, we adopt an
* asyncronous idiom; setting data (or calling a method) on the Proxy and
* listening for a
* {@link puremvc.Notification Notification}
* to be sent when the Proxy has retrieved the data from the service.
*
*
* @param {string} [proxyName]
* The Proxy's name. If none is provided, the Proxy will use its constructors
* NAME property.
* @param {Object} [data]
* The Proxy's data object
* @constructor
*/
function
Proxy
(
proxyName
,
data
)
{
this
.
proxyName
=
proxyName
||
this
.
constructor
.
NAME
;
if
(
data
!=
null
)
{
this
.
setData
(
data
);
}
};
Proxy
.
NAME
=
"
Proxy
"
;
Proxy
.
prototype
=
new
Notifier
;
Proxy
.
prototype
.
constructor
=
Proxy
;
/**
* Get the Proxy's name.
*
* @return {string}
*/
Proxy
.
prototype
.
getProxyName
=
function
()
{
return
this
.
proxyName
;
};
/**
* Set the Proxy's data object
*
* @param {Object} data
* @return {void}
*/
Proxy
.
prototype
.
setData
=
function
(
data
)
{
this
.
data
=
data
;
};
/**
* Get the Proxy's data object
*
* @return {Object}
*/
Proxy
.
prototype
.
getData
=
function
()
{
return
this
.
data
;
};
/**
* Called by the {@link puremvc.Model Model} when
* the Proxy is registered.
*
* @return {void}
*/
Proxy
.
prototype
.
onRegister
=
function
()
{
return
;
};
/**
* Called by the {@link puremvc.Model Model} when
* the Proxy is removed.
*
* @return {void}
*/
Proxy
.
prototype
.
onRemove
=
function
()
{
return
;
};
/**
* @ignore
* The Proxys name.
*
* @protected
* @type String
*/
Proxy
.
prototype
.
proxyName
=
null
;
/**
* @ignore
* The Proxy's data object.
*
* @protected
* @type Object
*/
Proxy
.
prototype
.
data
=
null
;
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.Facade
* Facade exposes the functionality of the Controller, Model and View
* actors to client facing code.
*
* This Facade implementation is a Multiton, so you should not call the
* constructor directly, but instead call the static Factory method,
* passing the unique key for this instance to #getInstance
*
* @constructor
* @param {string} key
* The multiton key to use to retrieve the Facade instance.
* @throws {Error}
* If an attempt is made to instantiate Facade directly
*/
function
Facade
(
key
)
{
if
(
Facade
.
instanceMap
[
key
]
!=
null
)
{
throw
new
Error
(
Facade
.
MULTITON_MSG
);
}
this
.
initializeNotifier
(
key
);
Facade
.
instanceMap
[
key
]
=
this
;
this
.
initializeFacade
();
};
/**
* Initialize the Multiton Facade instance.
*
* Called automatically by the constructor. Override in your subclass to any
* subclass specific initializations. Be sure to call the 'super'
* initializeFacade method, though
*
* MyFacade.prototype.initializeFacade= function ()
* {
* Facade.call(this);
* };
* @protected
* @return {void}
*/
Facade
.
prototype
.
initializeFacade
=
function
()
{
this
.
initializeModel
();
this
.
initializeController
();
this
.
initializeView
();
};
/**
* Facade Multiton Factory method.
* Note that this method will return null if supplied a
* null or undefined multiton key.
*
* @param {string} key
* The multiton key use to retrieve a particular Facade instance
* @return {puremvc.Facade}
*/
Facade
.
getInstance
=
function
(
key
)
{
if
(
null
==
key
)
return
null
;
if
(
Facade
.
instanceMap
[
key
]
==
null
)
{
Facade
.
instanceMap
[
key
]
=
new
Facade
(
key
);
}
return
Facade
.
instanceMap
[
key
];
};
/**
* Initialize the {@link puremvc.Controller Controller}.
*
* Called by the #initializeFacade method.
*
* Override this method in your subclass of Facade
* if one or both of the following are true:
* - You wish to initialize a different Controller
* - You have
* {@link puremvc.SimpleCommand SimpleCommand}s
* or {@link puremvc.MacroCommand MacroCommand}s
* to register with the Controllerat startup.
*
* If you don't want to initialize a different Controller,
* call the 'super' initializeControlle method at the beginning of your
* method, then register commands.
*
* MyFacade.prototype.initializeController= function ()
* {
* Facade.prototype.initializeController.call(this);
* this.registerCommand(AppConstants.A_NOTE_NAME, ABespokeCommand)
* }
*
* @protected
* @return {void}
*/
Facade
.
prototype
.
initializeController
=
function
()
{
if
(
this
.
controller
!=
null
)
return
;
this
.
controller
=
Controller
.
getInstance
(
this
.
multitonKey
);
};
/**
* @protected
* Initialize the {@link puremvc.Model Model};
*
* Called by the #initializeFacade method.
* Override this method in your subclass of Facade if one of the following are
* true:
*
* - You wish to initialize a different Model.
*
* - You have {@link puremvc.Proxy Proxy}s to
* register with the Model that do not retrieve a reference to the Facade at
* construction time.
*
* If you don't want to initialize a different Model
* call 'super' #initializeModel at the beginning of your method, then register
* Proxys.
*
* Note: This method is *rarely* overridden; in practice you are more
* likely to use a command to create and registerProxys with the Model>,
* since Proxys with mutable data will likely
* need to send Notifications and thus will likely want to fetch a reference to
* the Facade during their construction.
*
* @return {void}
*/
Facade
.
prototype
.
initializeModel
=
function
()
{
if
(
this
.
model
!=
null
)
return
;
this
.
model
=
Model
.
getInstance
(
this
.
multitonKey
);
};
/**
* @protected
*
* Initialize the {@link puremvc.View View}.
*
* Called by the #initializeFacade method.
*
* Override this method in your subclass of Facade if one or both of the
* following are true:
*
* - You wish to initialize a different View.
* - You have Observers to register with the View
*
* If you don't want to initialize a different View
* call 'super' #initializeView at the beginning of your
* method, then register Mediator instances.
*
* MyFacade.prototype.initializeView= function ()
* {
* Facade.prototype.initializeView.call(this);
* this.registerMediator(new MyMediator());
* };
*
* Note: This method is *rarely* overridden; in practice you are more
* likely to use a command to create and register Mediators
* with the View, since Mediator instances will need to send
* Notifications and thus will likely want to fetch a reference
* to the Facade during their construction.
* @return {void}
*/
Facade
.
prototype
.
initializeView
=
function
()
{
if
(
this
.
view
!=
null
)
return
;
this
.
view
=
View
.
getInstance
(
this
.
multitonKey
);
};
/**
* Register a command with the Controller by Notification name
* @param {string} notificationName
* The name of the Notification to associate the command with
* @param {Function} commandClassRef
* A reference ot the commands constructor.
* @return {void}
*/
Facade
.
prototype
.
registerCommand
=
function
(
notificationName
,
commandClassRef
)
{
this
.
controller
.
registerCommand
(
notificationName
,
commandClassRef
);
};
/**
* Remove a previously registered command to Notification mapping from the
* {@link puremvc.Controller#removeCommand Controller}
* @param {string} notificationName
* The name of the the Notification to remove from the command mapping for.
* @return {void}
*/
Facade
.
prototype
.
removeCommand
=
function
(
notificationName
)
{
this
.
controller
.
removeCommand
(
notificationName
);
};
/**
* Check if a command is registered for a given notification.
*
* @param {string} notificationName
* A Notification name
* @return {boolean}
* Whether a comman is currently registered for the given notificationName
*/
Facade
.
prototype
.
hasCommand
=
function
(
notificationName
)
{
return
this
.
controller
.
hasCommand
(
notificationName
);
};
/**
* Register a Proxy with the {@link puremvc.Model#registerProxy Model}
* by name.
*
* @param {puremvc.Proxy} proxy
* The Proxy instance to be registered with the Model.
* @return {void}
*/
Facade
.
prototype
.
registerProxy
=
function
(
proxy
)
{
this
.
model
.
registerProxy
(
proxy
);
};
/**
* Retrieve a Proxy from the Model
*
* @param {string} proxyName
* @return {puremvc.Proxy}
*/
Facade
.
prototype
.
retrieveProxy
=
function
(
proxyName
)
{
return
this
.
model
.
retrieveProxy
(
proxyName
);
};
/**
* Remove a Proxy from the Model by name
* @param {string} proxyName
* The name of the Proxy
* @return {puremvc.Proxy}
* The Proxy that was removed from the Model
*/
Facade
.
prototype
.
removeProxy
=
function
(
proxyName
)
{
var
proxy
=
null
;
if
(
this
.
model
!=
null
)
{
proxy
=
this
.
model
.
removeProxy
(
proxyName
);
}
return
proxy
;
};
/**
* Check it a Proxy is registered.
* @param {string} proxyName
* A Proxy name
* @return {boolean}
* Whether a Proxy is currently registered with the given proxyName
*/
Facade
.
prototype
.
hasProxy
=
function
(
proxyName
)
{
return
this
.
model
.
hasProxy
(
proxyName
);
};
/**
* Register a Mediator with with the View.
*
* @param {puremvc.Mediator} mediator
* A reference to the Mediator to register
* @return {void}
*/
Facade
.
prototype
.
registerMediator
=
function
(
mediator
)
{
if
(
this
.
view
!=
null
)
{
this
.
view
.
registerMediator
(
mediator
);
}
};
/**
* Retrieve a Mediator from the View by name
*
* @param {string} mediatorName
* The Mediators name
* @return {puremvc.Mediator}
* The retrieved Mediator
*/
Facade
.
prototype
.
retrieveMediator
=
function
(
mediatorName
)
{
return
this
.
view
.
retrieveMediator
(
mediatorName
);
};
/**
* Remove a Mediator from the View.
*
* @param {string} mediatorName
* The name of the Mediator to remove.
* @return {puremvc.Mediator}
* The removed Mediator
*/
Facade
.
prototype
.
removeMediator
=
function
(
mediatorName
)
{
var
mediator
=
null
;
if
(
this
.
view
!=
null
)
{
mediator
=
this
.
view
.
removeMediator
(
mediatorName
);
}
return
mediator
;
};
/**
* Check if a Mediator is registered or not.
*
* @param {string} mediatorName
* A Mediator name
* @return {boolean}
* Whether a Mediator is registered with the given mediatorName
*/
Facade
.
prototype
.
hasMediator
=
function
(
mediatorName
)
{
return
this
.
view
.
hasMediator
(
mediatorName
);
};
/**
* Create and send a
* {@link puremvc.Notification Notification}
*
* Keeps us from having to construct new Notification instances in our
* implementation
*
* @param {string} notificationName
* The name of the Notification to send
* @param {Object} [body]
* The body of the notification
* @param {string} [type]
* The type of the notification
* @return {void}
*/
Facade
.
prototype
.
sendNotification
=
function
(
notificationName
,
body
,
type
)
{
this
.
notifyObservers
(
new
Notification
(
notificationName
,
body
,
type
));
};
/**
* Notify {@link puremvc.Observer Observer}s
*
* This method is left public mostly for backward compatibility, and to allow
* you to send custom notification classes using the facade.
*
* Usually you should just call sendNotification and pass the parameters, never
* having to construct the notification yourself.
*
* @param {puremvc.Notification} notification
* The Notification to send
* @return {void}
*/
Facade
.
prototype
.
notifyObservers
=
function
(
notification
)
{
if
(
this
.
view
!=
null
)
{
this
.
view
.
notifyObservers
(
notification
);
}
};
/**
* Initialize the Facades Notifier capabilities by setting the Multiton key for
* this facade instance.
*
* Not called directly, but instead from the constructor when #getInstance is
* invoked. It is necessary to be public in order to implement Notifier
*
* @param {string} key
* @return {void}
*/
Facade
.
prototype
.
initializeNotifier
=
function
(
key
)
{
this
.
multitonKey
=
key
;
};
/**
* Check if a *Core* is registered or not
*
* @static
* @param {string} key
* The multiton key for the *Core* in question
* @return {boolean}
* Whether a *Core* is registered with the given key
*/
Facade
.
hasCore
=
function
(
key
)
{
return
Facade
.
instanceMap
[
key
]
!=
null
;
};
/**
* Remove a *Core*
*
* Remove the Model, View, Controller and Facade for a given key.
*
* @static
* @param {string} key
* @return {void}
*/
Facade
.
removeCore
=
function
(
key
)
{
if
(
Facade
.
instanceMap
[
key
]
==
null
)
return
;
Model
.
removeModel
(
key
);
View
.
removeView
(
key
);
Controller
.
removeController
(
key
);
delete
Facade
.
instanceMap
[
key
];
};
/**
* @ignore
* The Facades corresponding Controller
*
* @protected
* @type puremvc.Controller
*/
Facade
.
prototype
.
controller
=
null
;
/**
* @ignore
* The Facades corresponding Model instance
*
* @protected
* @type puremvc.Model
*/
Facade
.
prototype
.
model
=
null
;
/**
* @ignore
* The Facades correspnding View instance.
*
* @protected
* @type puremvc.View
*/
Facade
.
prototype
.
view
=
null
;
/**
* @ignore
* The Facades multiton key.
*
* @protected
* @type string
*/
Facade
.
prototype
.
multitonKey
=
null
;
/**
* @ignore
* The Multiton Facade instance map.
* @static
* @protected
* @type Array
*/
Facade
.
instanceMap
=
[];
/**
* @ignore
* Message Constants
* @protected
* @type {string}
* @const
* @static
*/
Facade
.
MULTITON_MSG
=
"
Facade instance for this Multiton key already constructed!
"
;
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.View
*
* A Multiton View implementation.
*
* In PureMVC, the View class assumes these responsibilities
*
* - Maintain a cache of {@link puremvc.Mediator Mediator}
* instances.
*
* - Provide methods for registering, retrieving, and removing
* {@link puremvc.Mediator Mediator}.
*
* - Notifiying {@link puremvc.Mediator Mediator} when they are registered or
* removed.
*
* - Managing the observer lists for each {@link puremvc.Notification Notification}
* in the application.
*
* - Providing a method for attaching {@link puremvc.Observer Observer} to an
* {@link puremvc.Notification Notification}'s observer list.
*
* - Providing a method for broadcasting a {@link puremvc.Notification Notification}.
*
* - Notifying the {@link puremvc.Observer Observer}s of a given
* {@link puremvc.Notification Notification} when it broadcast.
*
* This View implementation is a Multiton, so you should not call the
* constructor directly, but instead call the static Multiton
* Factory #getInstance method.
*
* @param {string} key
* @constructor
* @throws {Error}
* if instance for this Multiton key has already been constructed
*/
function
View
(
key
)
{
if
(
View
.
instanceMap
[
key
]
!=
null
)
{
throw
new
Error
(
View
.
MULTITON_MSG
);
};
this
.
multitonKey
=
key
;
View
.
instanceMap
[
this
.
multitonKey
]
=
this
;
this
.
mediatorMap
=
[];
this
.
observerMap
=
[];
this
.
initializeView
();
};
/**
* @protected
* Initialize the Singleton View instance
*
* Called automatically by the constructor, this is your opportunity to
* initialize the Singleton instance in your subclass without overriding the
* constructor
*
* @return {void}
*/
View
.
prototype
.
initializeView
=
function
()
{
return
;
};
/**
* View Singleton Factory method.
* Note that this method will return null if supplied a null
* or undefined multiton key.
*
* @return {puremvc.View}
* The Singleton instance of View
*/
View
.
getInstance
=
function
(
key
)
{
if
(
null
==
key
)
return
null
;
if
(
View
.
instanceMap
[
key
]
==
null
)
{
View
.
instanceMap
[
key
]
=
new
View
(
key
);
};
return
View
.
instanceMap
[
key
];
};
/**
* Register an Observer to be notified of Notifications with a given name
*
* @param {string} notificationName
* The name of the Notifications to notify this Observer of
* @param {puremvc.Observer} observer
* The Observer to register.
* @return {void}
*/
View
.
prototype
.
registerObserver
=
function
(
notificationName
,
observer
)
{
if
(
this
.
observerMap
[
notificationName
]
!=
null
)
{
this
.
observerMap
[
notificationName
].
push
(
observer
);
}
else
{
this
.
observerMap
[
notificationName
]
=
[
observer
];
}
};
/**
* Notify the Observersfor a particular Notification.
*
* All previously attached Observers for this Notification's
* list are notified and are passed a reference to the INotification in
* the order in which they were registered.
*
* @param {puremvc.Notification} notification
* The Notification to notify Observers of
* @return {void}
*/
View
.
prototype
.
notifyObservers
=
function
(
notification
)
{
// SIC
if
(
this
.
observerMap
[
notification
.
getName
()]
!=
null
)
{
var
observers_ref
=
this
.
observerMap
[
notification
.
getName
()],
observers
=
[],
observer
for
(
var
i
=
0
;
i
<
observers_ref
.
length
;
i
++
)
{
observer
=
observers_ref
[
i
];
observers
.
push
(
observer
);
}
for
(
var
i
=
0
;
i
<
observers
.
length
;
i
++
)
{
observer
=
observers
[
i
];
observer
.
notifyObserver
(
notification
);
}
}
};
/**
* Remove the Observer for a given notifyContext from an observer list for
* a given Notification name
*
* @param {string} notificationName
* Which observer list to remove from
* @param {Object} notifyContext
* Remove the Observer with this object as its notifyContext
* @return {void}
*/
View
.
prototype
.
removeObserver
=
function
(
notificationName
,
notifyContext
)
{
// SIC
var
observers
=
this
.
observerMap
[
notificationName
];
for
(
var
i
=
0
;
i
<
observers
.
length
;
i
++
)
{
if
(
observers
[
i
].
compareNotifyContext
(
notifyContext
)
==
true
)
{
observers
.
splice
(
i
,
1
);
break
;
}
}
if
(
observers
.
length
==
0
)
{
delete
this
.
observerMap
[
notificationName
];
}
};
/**
* Register a Mediator instance with the View.
*
* Registers the Mediator so that it can be retrieved by name,
* and further interrogates the Mediator for its
* {@link puremvc.Mediator#listNotificationInterests interests}.
*
* If the Mediator returns any Notification
* names to be notified about, an Observer is created encapsulating
* the Mediator instance's
* {@link puremvc.Mediator#handleNotification handleNotification}
* method and registering it as an Observer for all Notifications the
* Mediator is interested in.
*
* @param {puremvc.Mediator}
* a reference to the Mediator instance
*/
View
.
prototype
.
registerMediator
=
function
(
mediator
)
{
if
(
this
.
mediatorMap
[
mediator
.
getMediatorName
()]
!=
null
)
{
return
;
}
mediator
.
initializeNotifier
(
this
.
multitonKey
);
// register the mediator for retrieval by name
this
.
mediatorMap
[
mediator
.
getMediatorName
()]
=
mediator
;
// get notification interests if any
var
interests
=
mediator
.
listNotificationInterests
();
// register mediator as an observer for each notification
if
(
interests
.
length
>
0
)
{
// create observer referencing this mediators handleNotification method
var
observer
=
new
Observer
(
mediator
.
handleNotification
,
mediator
);
for
(
var
i
=
0
;
i
<
interests
.
length
;
i
++
)
{
this
.
registerObserver
(
interests
[
i
],
observer
);
}
}
mediator
.
onRegister
();
}
/**
* Retrieve a Mediator from the View
*
* @param {string} mediatorName
* The name of the Mediator instance to retrieve
* @return {puremvc.Mediator}
* The Mediator instance previously registered with the given mediatorName
*/
View
.
prototype
.
retrieveMediator
=
function
(
mediatorName
)
{
return
this
.
mediatorMap
[
mediatorName
];
};
/**
* Remove a Mediator from the View.
*
* @param {string} mediatorName
* Name of the Mediator instance to be removed
* @return {puremvc.Mediator}
* The Mediator that was removed from the View
*/
View
.
prototype
.
removeMediator
=
function
(
mediatorName
)
{
var
mediator
=
this
.
mediatorMap
[
mediatorName
];
if
(
mediator
)
{
// for every notification the mediator is interested in...
var
interests
=
mediator
.
listNotificationInterests
();
for
(
var
i
=
0
;
i
<
interests
.
length
;
i
++
)
{
// remove the observer linking the mediator to the notification
// interest
this
.
removeObserver
(
interests
[
i
],
mediator
);
}
// remove the mediator from the map
delete
this
.
mediatorMap
[
mediatorName
];
// alert the mediator that it has been removed
mediator
.
onRemove
();
}
return
mediator
;
};
/**
* Check if a Mediator is registered or not.
*
* @param {string} mediatorName
* @return {boolean}
* Whether a Mediator is registered with the given mediatorname
*/
View
.
prototype
.
hasMediator
=
function
(
mediatorName
)
{
return
this
.
mediatorMap
[
mediatorName
]
!=
null
;
};
/**
* Remove a View instance
*
* @return {void}
*/
View
.
removeView
=
function
(
key
)
{
delete
View
.
instanceMap
[
key
];
};
/**
* @ignore
* The Views internal mapping of mediator names to mediator instances
*
* @type Array
* @protected
*/
View
.
prototype
.
mediatorMap
=
null
;
/**
* @ignore
* The Views internal mapping of Notification names to Observer lists
*
* @type Array
* @protected
*/
View
.
prototype
.
observerMap
=
null
;
/**
* @ignore
* The internal map used to store multiton View instances
*
* @type Array
* @protected
*/
View
.
instanceMap
=
[];
/**
* @ignore
* The Views internal multiton key.
*
* @type string
* @protected
*/
View
.
prototype
.
multitonKey
=
null
;
/**
* @ignore
* The error message used if an attempt is made to instantiate View directly
*
* @type string
* @protected
* @const
* @static
*/
View
.
MULTITON_MSG
=
"
View instance for this Multiton key already constructed!
"
;
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.Model
*
* A Multiton Model implementation.
*
* In PureMVC, the Model class provides
* access to model objects (Proxies) by named lookup.
*
* The Model assumes these responsibilities:
*
* - Maintain a cache of {@link puremvc.Proxy Proxy}
* instances.
* - Provide methods for registering, retrieving, and removing
* {@link puremvc.Proxy Proxy} instances.
*
* Your application must register
* {@link puremvc.Proxy Proxy} instances with the Model.
* Typically, you use a
* {@link puremvc.SimpleCommand SimpleCommand}
* or
* {@link puremvc.MacroCommand MacroCommand}
* to create and register Proxy instances once the Facade has initialized the
* *Core* actors.
*
* This Model implementation is a Multiton, so you should not call the
* constructor directly, but instead call the
* {@link #getInstance static Multiton Factory method}
* @constructor
* @param {string} key
* The Models multiton key
* @throws {Error}
* An error is thrown if this multitons key is already in use by another instance
*/
function
Model
(
key
)
{
if
(
Model
.
instanceMap
[
key
])
{
throw
new
Error
(
Model
.
MULTITON_MSG
);
}
this
.
multitonKey
=
key
;
Model
.
instanceMap
[
key
]
=
this
;
this
.
proxyMap
=
[];
this
.
initializeModel
();
};
/**
* Initialize the Model instance.
*
* Called automatically by the constructor, this
* is your opportunity to initialize the Singleton
* instance in your subclass without overriding the
* constructor.
*
* @return void
*/
Model
.
prototype
.
initializeModel
=
function
(){};
/**
* Model Multiton Factory method.
* Note that this method will return null if supplied a null
* or undefined multiton key.
*
* @param {string} key
* The multiton key for the Model to retrieve
* @return {puremvc.Model}
* the instance for this Multiton key
*/
Model
.
getInstance
=
function
(
key
)
{
if
(
null
==
key
)
return
null
;
if
(
Model
.
instanceMap
[
key
]
==
null
)
{
Model
.
instanceMap
[
key
]
=
new
Model
(
key
);
}
return
Model
.
instanceMap
[
key
];
};
/**
* Register a Proxy with the Model
* @param {puremvc.Proxy}
*/
Model
.
prototype
.
registerProxy
=
function
(
proxy
)
{
proxy
.
initializeNotifier
(
this
.
multitonKey
);
this
.
proxyMap
[
proxy
.
getProxyName
()]
=
proxy
;
proxy
.
onRegister
();
};
/**
* Retrieve a Proxy from the Model
*
* @param {string} proxyName
* @return {puremvc.Proxy}
* The Proxy instance previously registered with the provided proxyName
*/
Model
.
prototype
.
retrieveProxy
=
function
(
proxyName
)
{
return
this
.
proxyMap
[
proxyName
];
};
/**
* Check if a Proxy is registered
* @param {string} proxyName
* @return {boolean}
* whether a Proxy is currently registered with the given proxyName.
*/
Model
.
prototype
.
hasProxy
=
function
(
proxyName
)
{
return
this
.
proxyMap
[
proxyName
]
!=
null
;
};
/**
* Remove a Proxy from the Model.
*
* @param {string} proxyName
* The name of the Proxy instance to remove
* @return {puremvc.Proxy}
* The Proxy that was removed from the Model
*/
Model
.
prototype
.
removeProxy
=
function
(
proxyName
)
{
var
proxy
=
this
.
proxyMap
[
proxyName
];
if
(
proxy
)
{
this
.
proxyMap
[
proxyName
]
=
null
;
proxy
.
onRemove
();
}
return
proxy
;
};
/**
* @static
* Remove a Model instance.
*
* @param {string} key
* @return {void}
*/
Model
.
removeModel
=
function
(
key
)
{
delete
Model
.
instanceMap
[
key
];
};
/**
* @ignore
* The map used by the Model to store Proxy instances.
*
* @protected
* @type Array
*/
Model
.
prototype
.
proxyMap
=
null
;
/**
* @ignore
* The map used by the Model to store multiton instances
*
* @protected
* @static
* @type Array
*/
Model
.
instanceMap
=
[];
/**
* @ignore
* The Models multiton key.
*
* @protected
* @type string
*/
Model
.
prototype
.
multitonKey
;
/**
* @ignore
* Message Constants
*
* @static
* @type {string}
*/
Model
.
MULTITON_MSG
=
"
Model instance for this Multiton key already constructed!
"
;
/**
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @class puremvc.Controller
*
* In PureMVC, the Controller class follows the 'Command and Controller'
* strategy, and assumes these responsibilities:
*
* - Remembering which
* {@link puremvc.SimpleCommand SimpleCommand}s
* or
* {@link puremvc.MacroCommand MacroCommand}s
* are intended to handle which
* {@link puremvc.Notification Notification}s
* - Registering itself as an
* {@link puremvc.Observer Observer} with
* the {@link puremvc.View View} for each
* {@link puremvc.Notification Notification}
* that it has an
* {@link puremvc.SimpleCommand SimpleCommand}
* or {@link puremvc.MacroCommand MacroCommand}
* mapping for.
* - Creating a new instance of the proper
* {@link puremvc.SimpleCommand SimpleCommand}s
* or
* {@link puremvc.MacroCommand MacroCommand}s
* to handle a given
* {@link puremvc.Notification Notification}
* when notified by the
* {@link puremvc.View View}.
* - Calling the command's execute method, passing in the
* {@link puremvc.Notification Notification}.
*
* Your application must register
* {@link puremvc.SimpleCommand SimpleCommand}s
* or {@link puremvc.MacroCommand MacroCommand}s
* with the Controller.
*
* The simplest way is to subclass
* {@link puremvc.Facade Facade},
* and use its
* {@link puremvc.Facade#initializeController initializeController}
* method to add your registrations.
*
* @constructor
* This Controller implementation is a Multiton, so you should not call the
* constructor directly, but instead call the static #getInstance factory method,
* passing the unique key for this instance to it.
* @param {string} key
* @throws {Error}
* If instance for this Multiton key has already been constructed
*/
function
Controller
(
key
)
{
if
(
Controller
.
instanceMap
[
key
]
!=
null
)
{
throw
new
Error
(
Controller
.
MULTITON_MSG
);
}
this
.
multitonKey
=
key
;
Controller
.
instanceMap
[
this
.
multitonKey
]
=
this
;
this
.
commandMap
=
new
Array
();
this
.
initializeController
();
}
/**
* @protected
*
* Initialize the multiton Controller instance.
*
* Called automatically by the constructor.
*
* Note that if you are using a subclass of View
* in your application, you should *also* subclass Controller
* and override the initializeController method in the
* following way.
*
* MyController.prototype.initializeController= function ()
* {
* this.view= MyView.getInstance(this.multitonKey);
* };
*
* @return {void}
*/
Controller
.
prototype
.
initializeController
=
function
()
{
this
.
view
=
View
.
getInstance
(
this
.
multitonKey
);
};
/**
* The Controllers multiton factory method.
* Note that this method will return null if supplied a null
* or undefined multiton key.
*
* @param {string} key
* A Controller's multiton key
* @return {puremvc.Controller}
* the Multiton instance of Controller
*/
Controller
.
getInstance
=
function
(
key
)
{
if
(
null
==
key
)
return
null
;
if
(
null
==
this
.
instanceMap
[
key
])
{
this
.
instanceMap
[
key
]
=
new
this
(
key
);
}
return
this
.
instanceMap
[
key
];
};
/**
* If a SimpleCommand or MacroCommand has previously been registered to handle
* the given Notification then it is executed.
*
* @param {puremvc.Notification} note
* @return {void}
*/
Controller
.
prototype
.
executeCommand
=
function
(
note
)
{
var
commandClassRef
=
this
.
commandMap
[
note
.
getName
()];
if
(
commandClassRef
==
null
)
return
;
var
commandInstance
=
new
commandClassRef
();
commandInstance
.
initializeNotifier
(
this
.
multitonKey
);
commandInstance
.
execute
(
note
);
};
/**
* Register a particular SimpleCommand or MacroCommand class as the handler for
* a particular Notification.
*
* If an command already been registered to handle Notifications with this name,
* it is no longer used, the new command is used instead.
*
* The Observer for the new command is only created if this the irst time a
* command has been regisered for this Notification name.
*
* @param {string} notificationName
* the name of the Notification
* @param {Function} commandClassRef
* a command constructor
* @return {void}
*/
Controller
.
prototype
.
registerCommand
=
function
(
notificationName
,
commandClassRef
)
{
if
(
this
.
commandMap
[
notificationName
]
==
null
)
{
this
.
view
.
registerObserver
(
notificationName
,
new
Observer
(
this
.
executeCommand
,
this
));
}
this
.
commandMap
[
notificationName
]
=
commandClassRef
;
};
/**
* Check if a command is registered for a given Notification
*
* @param {string} notificationName
* @return {boolean}
* whether a Command is currently registered for the given notificationName.
*/
Controller
.
prototype
.
hasCommand
=
function
(
notificationName
)
{
return
this
.
commandMap
[
notificationName
]
!=
null
;
};
/**
* Remove a previously registered command to
* {@link puremvc.Notification Notification}
* mapping.
*
* @param {string} notificationName
* the name of the Notification to remove the command mapping for
* @return {void}
*/
Controller
.
prototype
.
removeCommand
=
function
(
notificationName
)
{
if
(
this
.
hasCommand
(
notificationName
))
{
this
.
view
.
removeObserver
(
notificationName
,
this
);
this
.
commandMap
[
notificationName
]
=
null
;
}
};
/**
* @static
* Remove a Controller instance.
*
* @param {string} key
* multitonKey of Controller instance to remove
* @return {void}
*/
Controller
.
removeController
=
function
(
key
)
{
delete
this
.
instanceMap
[
key
];
};
/**
* Local reference to the Controller's View
*
* @protected
* @type {puremvc.View}
*/
Controller
.
prototype
.
view
=
null
;
/**
* Note name to command constructor mappings
*
* @protected
* @type {Object}
*/
Controller
.
prototype
.
commandMap
=
null
;
/**
* The Controller's multiton key
*
* @protected
* @type {string}
*/
Controller
.
prototype
.
multitonKey
=
null
;
/**
* Multiton key to Controller instance mappings
*
* @static
* @protected
* @type {Object}
*/
Controller
.
instanceMap
=
[];
/**
* @ignore
*
* Message constants
* @static
* @protected
* @type {string}
*/
Controller
.
MULTITON_MSG
=
"
controller key for this Multiton key already constructed
"
/*
* @author PureMVC JS Native Port by David Foley, Frédéric Saunier, & Alain Duchesneau
* @author Copyright(c) 2006-2012 Futurescale, Inc., Some rights reserved.
*
* @hide
* A an internal helper class used to assist classlet implementation. This
* class is not accessible by client code.
*/
var
OopHelp
=
{
/*
* @private
* A reference to the global scope. We use this rather than window
* in order to support both browser based and non browser baed
* JavaScript interpreters.
* @type {Object}
*/
global
:
(
function
(){
return
this
})()
/*
* @private
* Extend one Function's prototype by another, emulating classic
* inheritance.
*
* @param {Function} child
* The Function to extend (subclass)
*
* @param {Function} parent
* The Function to extend from (superclass)
*
* @return {Function}
*
* A reference to the extended Function (subclass)
*/
,
extend
:
function
(
child
,
parent
)
{
if
(
'
function
'
!==
typeof
child
)
throw
new
TypeError
(
'
#extend- child should be Function
'
);
if
(
'
function
'
!==
typeof
parent
)
throw
new
TypeError
(
'
#extend- parent should be Function
'
);
if
(
parent
===
child
)
return
;
var
Transitive
=
new
Function
;
Transitive
.
prototype
=
parent
.
prototype
;
child
.
prototype
=
new
Transitive
;
return
child
.
prototype
.
constructor
=
child
;
}
/*
* @private
* Decoarate one object with the properties of another.
*
* @param {Object} object
* The object to decorate.
*
* @param {Object} traits
* The object providing the properites that the first object
* will be decorated with. Note that only properties defined on
* this object will be copied- i.e. inherited properties will
* be ignored.
*
* @return {Object}
* THe decorated object (first argument)
*/
,
decorate
:
function
(
object
,
traits
)
{
for
(
var
accessor
in
traits
)
{
object
[
accessor
]
=
traits
[
accessor
];
}
return
object
;
}
};
/**
* @member puremvc
*
* Declare a namespace and optionally make an Object the referent
* of that namespace.
*
* console.assert(null == window.tld, 'No tld namespace');
* // declare the tld namespace
* puremvc.declare('tld');
* console.assert('object' === typeof tld, 'The tld namespace was declared');
*
* // the method returns a reference to last namespace node in a created hierarchy
* var reference= puremvc.declare('tld.domain.app');
* console.assert(reference === tld.domain.app)
*
* // of course you can also declare your own objects as well
* var AppConstants=
* {
* APP_NAME: 'tld.domain.app.App'
* };
*
* puremvc.declare('tld.domain.app.AppConstants', AppConstants);
* console.assert(AppConstants === tld.domain.app.AppConstants
* , 'AppConstants was exported to the namespace');
*
* Note that you can also #declare within a closure. That way you
* can selectively export Objects to your own namespaces without
* leaking variables into the global scope.
*
* (function(){
* // this var is not accessible outside of this
* // closures call scope
* var hiddenValue= 'defaultValue';
*
* // export an object that references the hidden
* // variable and which can mutate it
* puremvc.declare
* (
* 'tld.domain.app.backdoor'
*
* , {
* setValue: function (value)
* {
* // assigns to the hidden var
* hiddenValue= value;
* }
*
* , getValue: function ()
* {
* // reads from the hidden var
* return hiddenValue;
* }
* }
* );
* })();
* // indirectly retrieve the hidden variables value
* console.assert('defaultValue' === tld.domain.app.backdoor.getValue());
* // indirectly set the hidden variables value
* tld.domain.app.backdoor.setValue('newValue');
* // the hidden var was mutated
* console.assert('newValue' === tld.domain.app.backdoor.getValue());
*
* On occasion, primarily during testing, you may want to use declare,
* but not have the global object be the namespace root. In these cases you
* can supply the optional third scope argument.
*
* var localScope= {}
* , object= {}
*
* puremvc.declare('mock.object', object, localScope);
*
* console.assert(null == window.mock, 'mock namespace is not in global scope');
* console.assert(object === localScope.mock.object, 'mock.object is available in localScope');
*
* @param {string} string
* A qualified object name, e.g. 'com.example.Class'
*
* @param {Object} [object]
* An object to make the referent of the namespace.
*
* @param {Object} [scope]
* The namespace's root node. If not supplied, the global
* scope will be namespaces root node.
*
* @return {Object}
*
* A reference to the last node of the Object hierarchy created.
*/
function
declare
(
qualifiedName
,
object
,
scope
)
{
var
nodes
=
qualifiedName
.
split
(
'
.
'
)
,
node
=
scope
||
OopHelp
.
global
,
lastNode
,
newNode
,
nodeName
;
for
(
var
i
=
0
,
n
=
nodes
.
length
;
i
<
n
;
i
++
)
{
lastNode
=
node
;
nodeName
=
nodes
[
i
];
node
=
(
null
==
node
[
nodeName
]
?
node
[
nodeName
]
=
{}
:
node
[
nodeName
]);
}
if
(
null
==
object
)
return
node
;
return
lastNode
[
nodeName
]
=
object
;
};
/**
* @member puremvc
*
* Define a new classlet. Current editions of JavaScript do not have classes,
* but they can be emulated, and this method does this for you, saving you
* from having to work with Function prototype directly. The method does
* not extend any Native objects and is entirely opt in. Its particularly
* usefull if you want to make your PureMvc applications more portable, by
* decoupling them from a specific OOP abstraction library.
*
*
* puremvc.define
* (
* // the first object supplied is a class descriptor. None of these
* // properties are added to your class, the exception being the
* // constructor property, which if supplied, will be your classes
* // constructor.
* {
* // your classes namespace- if supplied, it will be
* // created for you
* name: 'com.example.UserMediator'
*
* // your classes parent class. If supplied, inheritance
* // will be taken care of for you
* , parent: puremvc.Mediator
*
* // your classes constructor. If not supplied, one will be
* // created for you
* , constructor: function UserMediator (component)
* {
* puremvc.Mediator.call(this, this.constructor.NAME, component);
* }
* }
*
* // the second object supplied defines your class traits, that is
* // the properties that will be defined on your classes prototype
* // and thereby on all instances of this class
* , {
* businessMethod: function ()
* {
* // impl
* }
* }
*
* // the third object supplied defines your classes 'static' traits
* // that is, the methods and properties which will be defined on
* // your classes constructor
* , {
* NAME: 'userMediator'
* }
* );
*
* @param {Object} [classinfo]
* An object describing the class. This object can have any or all of
* the following properties:
*
* - name: String
* The classlets name. This can be any arbitrary qualified object
* name. 'com.example.Classlet' or simply 'MyClasslet' for example
* The method will automatically create an object hierarchy refering
* to your class for you. Note that you will need to capture the
* methods return value to retrieve a reference to your class if the
* class name property is not defined.
* - parent: Function
* The classlets 'superclass'. Your class will be extended from this
* if supplied.
*
* - constructor: Function
* The classlets constructor. Note this is *not* a post construct
* initialize method, but your classes constructor Function.
* If this attribute is not defined, a constructor will be created for
* you automatically. If you have supplied a parent class
* value and not defined the classes constructor, the automatically
* created constructor will invoke the super class constructor
* automatically. If you have supplied your own constructor and you
* wish to invoke it's super constructor, you must do this manually, as
* there is no reference to the classes parent added to the constructor
* prototype.
*
* - scope: Object.
* For use in advanced scenarios. If the name attribute has been supplied,
* this value will be the root of the object hierarchy created for you.
* Use it do define your own class hierarchies in private scopes,
* accross iFrames, in your unit tests, or avoid collision with third
* party library namespaces.
*
* @param {Object} [traits]
* An Object, the properties of which will be added to the
* class constructors prototype.
*
* @param {Object} [staitcTraits]
* An Object, the properties of which will be added directly
* to this class constructor
*
* @return {Function}
* A reference to the classlets constructor
*/
function
define
(
classInfo
,
traits
,
staticTraits
)
{
if
(
!
classInfo
)
{
classInfo
=
{}
}
var
className
=
classInfo
.
name
,
classParent
=
classInfo
.
parent
,
doExtend
=
'
function
'
===
typeof
classParent
,
classConstructor
,
classScope
=
classInfo
.
scope
||
null
,
prototype
if
(
'
parent
'
in
classInfo
&&
!
doExtend
)
{
throw
new
TypeError
(
'
Class parent must be Function
'
);
}
if
(
classInfo
.
hasOwnProperty
(
'
constructor
'
))
{
classConstructor
=
classInfo
.
constructor
if
(
'
function
'
!==
typeof
classConstructor
)
{
throw
new
TypeError
(
'
Class constructor must be Function
'
)
}
}
else
// there is no constructor, create one
{
if
(
doExtend
)
// ensure to call the super constructor
{
classConstructor
=
function
()
{
classParent
.
apply
(
this
,
arguments
);
}
}
else
// just create a Function
{
classConstructor
=
new
Function
;
}
}
if
(
doExtend
)
{
OopHelp
.
extend
(
classConstructor
,
classParent
);
}
if
(
traits
)
{
prototype
=
classConstructor
.
prototype
OopHelp
.
decorate
(
prototype
,
traits
);
// reassign constructor
prototype
.
constructor
=
classConstructor
;
}
if
(
staticTraits
)
{
OopHelp
.
decorate
(
classConstructor
,
staticTraits
)
}
if
(
className
)
{
if
(
'
string
'
!==
typeof
className
)
{
throw
new
TypeError
(
'
Class name must be primitive string
'
);
}
declare
(
className
,
classConstructor
,
classScope
);
}
return
classConstructor
;
};
/* implementation end */
// define the puremvc global namespace and export the actors
scope
.
puremvc
=
{
View
:
View
,
Model
:
Model
,
Controller
:
Controller
,
SimpleCommand
:
SimpleCommand
,
MacroCommand
:
MacroCommand
,
Facade
:
Facade
,
Mediator
:
Mediator
,
Observer
:
Observer
,
Notification
:
Notification
,
Notifier
:
Notifier
,
Proxy
:
Proxy
,
define
:
define
,
declare
:
declare
};
})(
this
);
// the 'this' parameter will resolve to global scope in all environments
labs/architecture-examples/puremvc/components/todomvc-common/base.css
0 → 100644
View file @
4453ce21
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
:
#eaeaea
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
input
::-webkit-input-placeholder
{
font-style
:
italic
;
}
#todoapp
input
:-moz-placeholder
{
font-style
:
italic
;
color
:
#a9a9a9
;
}
#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
;
}
#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-top-left-radius
:
1px
;
border-top-right-radius
:
1px
;
}
#new-todo
,
.edit
{
position
:
relative
;
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
);
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
:
-4px
;
width
:
40px
;
text-align
:
center
;
border
:
none
;
/* Mobile Safari */
}
#toggle-all
:before
{
content
:
'»'
;
font-size
:
28px
;
color
:
#d9d9d9
;
padding
:
0
25px
7px
;
}
#toggle-all
:checked:before
{
color
:
#737373
;
}
#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
:
40px
;
/* auto, since non-WebKit browsers doesn't support input styling */
height
:
auto
;
position
:
absolute
;
top
:
0
;
bottom
:
0
;
margin
:
auto
0
;
border
:
none
;
/* Mobile Safari */
-webkit-appearance
:
none
;
/*-moz-appearance: none;*/
-ms-appearance
:
none
;
-o-appearance
:
none
;
appearance
:
none
;
}
#todo-list
li
.toggle
:after
{
content
:
'✔'
;
line-height
:
43px
;
/* 40 + a couple of pixels visual adjustment */
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
;
padding
:
15px
;
margin-left
:
45px
;
display
:
block
;
line-height
:
1.2
;
-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
.completed
label
{
color
:
#a9a9a9
;
text-decoration
:
line-through
;
}
#todo-list
li
.destroy
{
display
:
none
;
position
:
absolute
;
top
:
0
;
right
:
10px
;
bottom
:
0
;
width
:
40px
;
height
:
40px
;
margin
:
auto
0
;
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
;
height
:
20px
;
z-index
:
1
;
text-align
:
center
;
}
#footer
:before
{
content
:
''
;
position
:
absolute
;
right
:
0
;
bottom
:
31px
;
left
:
0
;
height
:
50px
;
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
43px
0
-6px
rgba
(
255
,
255
,
255
,
0.8
),
0
44px
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
;
position
:
relative
;
line-height
:
20px
;
text-decoration
:
none
;
background
:
rgba
(
0
,
0
,
0
,
0.1
);
font-size
:
11px
;
padding
:
0
10px
;
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
;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox and Opera
*/
@media
screen
and
(
-webkit-min-device-pixel-ratio
:
0
)
{
#toggle-all
,
#todo-list
li
.toggle
{
background
:
none
;
}
#todo-list
li
.toggle
{
height
:
40px
;
}
#toggle-all
{
top
:
-56px
;
left
:
-15px
;
width
:
65px
;
height
:
41px
;
-webkit-transform
:
rotate
(
90deg
);
transform
:
rotate
(
90deg
);
-webkit-appearance
:
none
;
appearance
:
none
;
}
}
.hidden
{
display
:
none
;
}
labs/architecture-examples/puremvc/components/todomvc-common/base.js
0 → 100644
View file @
4453ce21
(
function
()
{
'
use strict
'
;
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
getSourcePath
()
{
// If accessed via addyosmani.github.com/todomvc/, strip the project
// path.
if
(
location
.
hostname
.
indexOf
(
'
github.com
'
)
>
0
)
{
return
location
.
pathname
.
replace
(
/todomvc
\/
/
,
''
);
}
return
location
.
pathname
;
}
function
appendSourceLink
()
{
var
sourceLink
=
document
.
createElement
(
'
a
'
);
var
paragraph
=
document
.
createElement
(
'
p
'
);
var
footer
=
document
.
getElementById
(
'
info
'
);
var
urlBase
=
'
https://github.com/addyosmani/todomvc/tree/gh-pages
'
;
if
(
footer
)
{
sourceLink
.
href
=
urlBase
+
getSourcePath
();
sourceLink
.
appendChild
(
document
.
createTextNode
(
'
Check out the source
'
));
paragraph
.
appendChild
(
sourceLink
);
footer
.
appendChild
(
paragraph
);
}
}
function
redirect
()
{
if
(
location
.
hostname
===
'
addyosmani.github.com
'
)
{
location
.
href
=
location
.
href
.
replace
(
'
addyosmani.github.com/todomvc
'
,
'
todomvc.com
'
);
}
}
appendSourceLink
();
redirect
();
})();
labs/architecture-examples/puremvc/components/todomvc-common/bg.png
0 → 100644
View file @
4453ce21
2.08 KB
labs/architecture-examples/puremvc/index.html
View file @
4453ce21
...
...
@@ -4,10 +4,7 @@
<meta
charset=
"utf-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge,chrome=1"
>
<title>
PureMVC • TodoMVC
</title>
<link
rel=
"stylesheet"
href=
"../../../assets/base.css"
>
<!--[if IE]>
<script src="assets/ie.js"></script>
<![endif]-->
<link
rel=
"stylesheet"
href=
"components/todomvc-common/base.css"
>
</head>
<body>
<section
id=
"todoapp"
>
...
...
@@ -44,13 +41,13 @@
</footer>
<!-- TODOMVC PROJECT BASE -->
<script
src=
"
../../../assets
/base.js"
></script>
<script
src=
"
components/todomvc-common
/base.js"
></script>
<!-- FLATIRION DIRECTOR ROUTING LIBRARY -->
<script
src=
"
../../../assets/director.min
.js"
></script>
<script
src=
"
components/director/director
.js"
></script>
<!-- PUREMVC LIBRARY -->
<script
src=
"
js/lib/puremvc.min
.js"
></script>
<script
src=
"
components/puremvc/puremvc-1.0.1
.js"
></script>
<!-- APPLICATION CONSTANTS -->
<script
src=
"js/AppConstants.js"
></script>
...
...
labs/architecture-examples/puremvc/js/view/component/TodoForm.js
View file @
4453ce21
...
...
@@ -194,7 +194,7 @@ puremvc.define({
li
.
appendChild
(
divDisplay
);
li
.
appendChild
(
inputEditTodo
);
if
(
todo
.
completed
)
{
li
.
className
+=
'
complete
'
;
li
.
className
+=
'
complete
d
'
;
checkbox
.
checked
=
true
;
}
this
.
todoList
.
appendChild
(
li
);
...
...
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