Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
brainfood
/
rivets
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
d06e350d
authored
2012-06-30 16:20:47 -0700
by
Michael Richards
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Namespace everything under Rivets and rewrite the registerBinding function as a new class.
1 parent
77351bb8
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
102 additions
and
58 deletions
lib/rivets.js
src/rivets.coffee
lib/rivets.js
View file @
d06e350
// Generated by CoffeeScript 1.3.1
(
function
()
{
var
attributeBinding
,
bidirectionals
,
bindings
,
getInputValue
,
registerBinding
,
rivets
,
stateBinding
,
var
Rivets
,
__bind
=
function
(
fn
,
me
){
return
function
(){
return
fn
.
apply
(
me
,
arguments
);
};
},
__indexOf
=
[].
indexOf
||
function
(
item
)
{
for
(
var
i
=
0
,
l
=
this
.
length
;
i
<
l
;
i
++
)
{
if
(
i
in
this
&&
this
[
i
]
===
item
)
return
i
;
}
return
-
1
;
};
registerBinding
=
function
(
el
,
adapter
,
type
,
context
,
keypath
)
{
var
bind
;
bind
=
bindings
[
type
]
||
attributeBinding
(
type
);
bind
(
el
,
adapter
.
read
(
context
,
keypath
));
adapter
.
subscribe
(
context
,
keypath
,
function
(
value
)
{
return
bind
(
el
,
value
);
Rivets
=
{
Helpers
:
{}
};
Rivets
.
Binding
=
(
function
()
{
Binding
.
name
=
'Binding'
;
function
Binding
(
el
,
adapter
,
type
,
context
,
keypath
)
{
this
.
el
=
el
;
this
.
adapter
=
adapter
;
this
.
type
=
type
;
this
.
context
=
context
;
this
.
keypath
=
keypath
;
this
.
bind
=
__bind
(
this
.
bind
,
this
);
this
.
set
=
__bind
(
this
.
set
,
this
);
this
.
routine
=
Rivets
.
bindings
[
this
.
type
]
||
Rivets
.
Helpers
.
attributeBinding
(
this
.
type
);
}
Binding
.
prototype
.
set
=
function
(
value
)
{
if
(
value
==
null
)
{
value
=
null
;
}
return
this
.
routine
(
this
.
el
,
value
||
this
.
adapter
.
read
(
this
.
context
,
this
.
keypath
));
};
Binding
.
prototype
.
bind
=
function
()
{
var
_ref
,
_this
=
this
;
this
.
adapter
.
subscribe
(
this
.
context
,
this
.
keypath
,
function
(
value
)
{
return
_this
.
set
(
value
);
});
if
(
__indexOf
.
call
(
bidirectionals
,
type
)
>=
0
)
{
return
el
.
addEventListener
(
'change'
,
function
(
)
{
return
adapter
.
publish
(
context
,
keypath
,
getInputValue
(
this
));
if
(
_ref
=
this
.
type
,
__indexOf
.
call
(
Rivets
.
bidirectionals
,
_ref
)
>=
0
)
{
return
this
.
el
.
addEventListener
(
'change'
,
function
(
el
)
{
return
_this
.
adapter
.
publish
(
_this
.
context
,
_this
.
keypath
,
Rivets
.
Helpers
.
getInputValue
(
el
));
});
}
};
getInputValue
=
function
(
el
)
{
return
Binding
;
})();
Rivets
.
Helpers
.
getInputValue
=
function
(
el
)
{
switch
(
el
.
type
)
{
case
'text'
:
case
'textarea'
:
...
...
@@ -30,7 +62,7 @@
}
};
attributeBinding
=
function
(
attr
)
{
Rivets
.
Helpers
.
attributeBinding
=
function
(
attr
)
{
return
function
(
el
,
value
)
{
if
(
value
)
{
return
el
.
setAttribute
(
attr
,
value
);
...
...
@@ -40,22 +72,24 @@
};
};
stateBinding
=
function
(
attr
,
inverse
)
{
Rivets
.
Helpers
.
stateBinding
=
function
(
attr
,
inverse
)
{
if
(
inverse
==
null
)
{
inverse
=
false
;
}
return
function
(
el
,
value
)
{
return
attributeBinding
(
attr
)(
el
,
inverse
===
!
value
?
attr
:
false
);
var
binding
;
binding
=
Rivets
.
Helpers
.
attributeBinding
(
attr
);
return
binding
(
el
,
inverse
===
!
value
?
attr
:
false
);
};
};
bindings
=
{
checked
:
stateBinding
(
'checked'
),
selected
:
stateBinding
(
'selected'
),
disabled
:
stateBinding
(
'disabled'
),
unchecked
:
stateBinding
(
'checked'
,
true
),
unselected
:
stateBinding
(
'selected'
,
true
),
enabled
:
stateBinding
(
'disabled'
,
true
),
Rivets
.
bindings
=
{
checked
:
Rivets
.
Helpers
.
stateBinding
(
'checked'
),
selected
:
Rivets
.
Helpers
.
stateBinding
(
'selected'
),
disabled
:
Rivets
.
Helpers
.
stateBinding
(
'disabled'
),
unchecked
:
Rivets
.
Helpers
.
stateBinding
(
'checked'
,
true
),
unselected
:
Rivets
.
Helpers
.
stateBinding
(
'selected'
,
true
),
enabled
:
Rivets
.
Helpers
.
stateBinding
(
'disabled'
,
true
),
text
:
function
(
el
,
value
)
{
return
el
.
innerText
=
value
||
''
;
},
...
...
@@ -73,14 +107,14 @@
}
};
bidirectionals
=
[
'value'
,
'checked'
,
'unchecked'
,
'selected'
,
'unselected'
];
Rivets
.
bidirectionals
=
[
'value'
,
'checked'
,
'unchecked'
,
'selected'
,
'unselected'
];
rivets
=
{
Rivets
[
"interface"
]
=
{
register
:
function
(
routine
,
routineFunction
)
{
return
bindings
[
routine
]
=
routineFunction
;
return
Rivets
.
bindings
[
routine
]
=
routineFunction
;
},
bind
:
function
(
el
,
adapter
,
contexts
)
{
var
attribute
,
context
,
keypath
,
node
,
path
,
type
,
_i
,
_len
,
_ref
,
_results
;
var
attribute
,
binding
,
context
,
keypath
,
node
,
path
,
type
,
_i
,
_len
,
_ref
,
_results
;
if
(
contexts
==
null
)
{
contexts
=
{};
}
...
...
@@ -99,7 +133,8 @@
path
=
attribute
.
value
.
split
(
'.'
);
context
=
path
.
shift
();
keypath
=
path
.
join
(
'.'
);
_results1
.
push
(
registerBinding
(
node
,
adapter
,
type
,
contexts
[
context
],
keypath
));
binding
=
new
Rivets
.
Binding
(
node
,
adapter
,
type
,
contexts
[
context
],
keypath
);
_results1
.
push
(
binding
.
bind
());
}
else
{
_results1
.
push
(
void
0
);
}
...
...
@@ -112,9 +147,9 @@
};
if
(
typeof
module
!==
"undefined"
&&
module
!==
null
)
{
module
.
exports
=
rivets
;
module
.
exports
=
Rivets
[
"interface"
]
;
}
else
{
this
.
rivets
=
rivets
;
this
.
rivets
=
Rivets
[
"interface"
]
;
}
}).
call
(
this
);
...
...
src/rivets.coffee
View file @
d06e350
...
...
@@ -3,53 +3,60 @@
# author : Michael Richards
# license : MIT
# Registers a specific binding routine between a model object and a DOM element.
# All information for that routine is passed in when calling this function; the
# specific element to bind to, an adapter interface for the model object, the
# type of binding, the context object and the keypath at which to subscribe to
# on the model object.
registerBinding
=
(
el
,
adapter
,
type
,
context
,
keypath
)
->
bind
=
bindings
[
type
]
||
attributeBinding
type
bind
el
,
adapter
.
read
context
,
keypath
Rivets
=
Helpers
:
{}
adapter
.
subscribe
context
,
keypath
,
(
value
)
->
bind
el
,
value
class
Rivets
.
Binding
constructor
:
(
@
el
,
@
adapter
,
@
type
,
@
context
,
@
keypath
)
->
@
routine
=
Rivets
.
bindings
[
@
type
]
||
Rivets
.
Helpers
.
attributeBinding
@
type
if
type
in
bidirectionals
el
.
addEventListener
'change'
,
->
adapter
.
publish
context
,
keypath
,
getInputValue
this
# Sets a value for this binding. Basically just runs the routine on the
# element with a suplied value.
set
:
(
value
=
null
)
=>
@
routine
@
el
,
value
||
@
adapter
.
read
@
context
,
@
keypath
# Subscribes to the context object for changes on the specific keypath.
# Conditionally also does the inverse and listens to the element for changes
# to propogate back to the context object.
bind
:
=>
@
adapter
.
subscribe
@
context
,
@
keypath
,
(
value
)
=>
@
set
value
if
@
type
in
Rivets
.
bidirectionals
@
el
.
addEventListener
'change'
,
(
el
)
=>
@
adapter
.
publish
@
context
,
@
keypath
,
Rivets
.
Helpers
.
getInputValue
el
# Returns the current input value for the specified element.
getInputValue
=
(
el
)
->
Rivets
.
Helpers
.
getInputValue
=
(
el
)
->
switch
el
.
type
when
'text'
,
'textarea'
,
'password'
,
'select-one'
then
el
.
value
when
'checkbox'
,
'radio'
then
el
.
checked
# Returns an attribute binding routine for the specified attribute. This is what
# `registerBinding` falls back to when there is no routine for the binding type.
attributeBinding
=
(
attr
)
->
(
el
,
value
)
->
Rivets
.
Helpers
.
attributeBinding
=
(
attr
)
->
(
el
,
value
)
->
if
value
then
el
.
setAttribute
attr
,
value
else
el
.
removeAttribute
attr
# Returns a state binding routine for the specified attribute. Can optionally be
# negatively evaluated. This is used to build a lot of the core state binding
# routines.
stateBinding
=
(
attr
,
inverse
=
false
)
->
(
el
,
value
)
->
attributeBinding
(
attr
)
el
,
if
inverse
is
!
value
then
attr
else
false
Rivets
.
Helpers
.
stateBinding
=
(
attr
,
inverse
=
false
)
->
(
el
,
value
)
->
binding
=
Rivets
.
Helpers
.
attributeBinding
(
attr
)
binding
el
,
if
inverse
is
!
value
then
attr
else
false
# Core binding routines.
bindings
=
Rivets
.
bindings
=
checked
:
stateBinding
'checked'
Rivets
.
Helpers
.
stateBinding
'checked'
selected
:
stateBinding
'selected'
Rivets
.
Helpers
.
stateBinding
'selected'
disabled
:
stateBinding
'disabled'
Rivets
.
Helpers
.
stateBinding
'disabled'
unchecked
:
stateBinding
'checked'
,
true
Rivets
.
Helpers
.
stateBinding
'checked'
,
true
unselected
:
stateBinding
'selected'
,
true
Rivets
.
Helpers
.
stateBinding
'selected'
,
true
enabled
:
stateBinding
'disabled'
,
true
Rivets
.
Helpers
.
stateBinding
'disabled'
,
true
text
:
(
el
,
value
)
->
el
.
innerText
=
value
or
''
html
:
(
el
,
value
)
->
...
...
@@ -63,13 +70,13 @@ bindings =
# Bindings that should also be observed for changes on the DOM element in order
# to propogate those changes back to the model object.
bidirectionals
=
[
'value'
,
'checked'
,
'unchecked'
,
'selected'
,
'unselected'
]
Rivets
.
bidirectionals
=
[
'value'
,
'checked'
,
'unchecked'
,
'selected'
,
'unselected'
]
# The rivets module exposes `register` and `bind` functions to register new
# binding routines and bind contexts to DOM elements.
rivets
=
Rivets
.
interface
=
register
:
(
routine
,
routineFunction
)
->
bindings
[
routine
]
=
routineFunction
Rivets
.
bindings
[
routine
]
=
routineFunction
bind
:
(
el
,
adapter
,
contexts
=
{})
->
for
node
in
el
.
getElementsByTagName
'*'
...
...
@@ -79,10 +86,12 @@ rivets =
path
=
attribute
.
value
.
split
'.'
context
=
path
.
shift
()
keypath
=
path
.
join
'.'
registerBinding
node
,
adapter
,
type
,
contexts
[
context
],
keypath
binding
=
new
Rivets
.
Binding
node
,
adapter
,
type
,
contexts
[
context
],
keypath
binding
.
bind
()
# Exports rivets for both CommonJS and the browser.
if
module
?
module
.
exports
=
rivets
module
.
exports
=
Rivets
.
interface
else
@
rivets
=
rivets
\ No newline at end of file
@
rivets
=
Rivets
.
interface
\ No newline at end of file
...
...
Please
register
or
sign in
to post a comment