View Codevar
validValueType = $.oneObject(
"Null,NaN,Undefined,Boolean,Number,String"
)
$.dependencyDetection = (
function
() {
var
_frames = [];
return
{
begin:
function
(ret) {
_frames.push(ret);
},
end:
function
() {
_frames.pop();
},
collect:
function
(self) {
if
(_frames.length > 0) {
self.list = self.list || [];
var
fn = _frames[_frames.length - 1];
if
( self.list.indexOf( fn ) >= 0)
return
;
self.list.push(fn);
}
}
};
})();
$.valueWillMutate =
function
(observable){
var
list = observable.list
if
($.type(list,
"Array"
)){
for
(
var
i = 0, el; el = list[i++];){
el();
}
}
}
$.observable =
function
(value){
var
v = value;
function
ret(neo){
if
(arguments.length){
if
(!validValueType[$.type(neo)]){
$.error(
"arguments must be primitive type!"
)
return
ret
}
if
(v !== neo ){
v = neo;
$.valueWillMutate(ret);
}
return
ret;
}
else
{
$.dependencyDetection.collect(ret);
return
v;
}
}
value = validValueType[$.type(value)] ? value : void 0;
ret(arguments[0]);
return
ret
}
$.computed =
function
(obj, scope){
var
getter, setter
if
(
typeof
obj ==
"function"
){
getter = obj
}
else
if
(obj &&
typeof
obj ==
"object"
){
getter = obj.getter;
setter = obj.setter;
scope = obj.scope;
}
var
v
var
ret =
function
(neo){
if
(arguments.length ){
if
(
typeof
setter ==
"function"
){
if
(!validValueType[$.type(neo)]){
$.error(
"arguments must be primitive type!"
)
return
ret
}
if
(v !== neo ){
setter.call(scope, neo);
v = neo;
$.valueWillMutate(ret);
}
}
return
ret;
}
else
{
$.dependencyDetection.begin(ret);
v = getter.call(scope);
$.dependencyDetection.end();
return
v;
}
}
ret();
return
ret;
}
function
MyViewModel() {
this
.firstName = $.observable(
'Planet'
);
this
.lastName = $.observable(
'Earth'
);
this
.fullName = $.computed({
getter:
function
() {
return
this
.firstName() +
" "
+
this
.lastName();
},
setter:
function
(value) {
var
lastSpacePos = value.lastIndexOf(
" "
);
if
(lastSpacePos > 0) {
this
.firstName(value.substring(0, lastSpacePos));
this
.lastName(value.substring(lastSpacePos + 1));
}
},
scope:
this
});
}
$.buildEvalWithinScopeFunction =
function
(expression, scopeLevels) {
var
functionBody =
"return ("
+ expression +
")"
;
for
(
var
i = 0; i < scopeLevels; i++) {
functionBody =
"with(sc["
+ i +
"]) { "
+ functionBody +
" } "
;
}
return
new
Function(
"sc"
, functionBody);
}
$.applyBindings =
function
(model, node){
var
nodeBind = $.computed(
function
(){
var
str =
"{"
+ node.getAttribute(
"data-bind"
)+
"}"
var
fn = $.buildEvalWithinScopeFunction(str,2);
var
bindings = fn([node,model]);
for
(
var
key
in
bindings){
if
(bindings.hasOwnProperty(key)){
var
fn = $.bindingHandlers[
"text"
][
"update"
];
var
observable = bindings[key]
$.dependencyDetection.collect(observable);
fn(node, observable)
}
}
},node);
return
nodeBind
}
$.bindingHandlers = {}
$.bindingHandlers[
"text"
] = {
'update'
:
function
(node, observable) {
var
val = observable()
val = val ==
null
?
""
: val+
""
;
if
(
"textContent"
in
node){
node.textContent = val;
}
else
{
node.innerText = val;
}
if
(document.documentMode == 9) {
node.style.display = node.style.display;
}
}
}
window.onload =
function
(){
var
model =
new
MyViewModel();
var
node = document.getElementById(
"node"
);
var
nodeBind = $.applyBindings(model, node);
$.log(
"+++++++++++++++++++++++++++"
)
$.log(model.fullName.list[0] == nodeBind);
$.log(model.lastName.list[0] == model.fullName);
$.log(model.firstName.list[0] == model.fullName);
setTimeout(
function
(){
model.fullName(
"xxx yyy"
)
},1500)
setTimeout(
function
(){
model.fullName(
"111 222"
)
},3000)
}