/
mapping.go
122 lines (105 loc) · 2.58 KB
/
mapping.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package ko
import (
"github.com/Archs/js/utils/property"
"github.com/gopherjs/gopherjs/js"
)
// ViewModel can be used to wrap ko vm object
type ViewModel struct {
*js.Object
}
type Mapper struct {
*js.Object
data interface{}
options *js.Object
target interface{}
}
func Mapping() *Mapper {
return &Mapper{
Object: Global().Get("mapping"),
}
}
func (m *Mapper) args() []interface{} {
args := []interface{}{m.data}
if m.options != nil {
args = append(args, m.options)
}
if m.target != nil {
if m.options == nil {
args = append(args, js.M{})
}
args = append(args, m.target)
}
return args
}
func (m *Mapper) FromJS(data interface{}) (vm *ViewModel) {
vm = new(ViewModel)
m.data = data
vm.Object = m.Object.Call("fromJS", m.args()...)
return
}
// Specifying the target to update, can be a *ViewModel or a *js.Object
// or a struct with *js.Object embeded which is a ViewModel then
func (m *Mapper) Target(obj interface{}) *Mapper {
m.target = obj
return m
}
func (m *Mapper) ToJS(vm *ViewModel) *js.Object {
return m.Object.Call("toJS", vm.Object)
}
func (m *Mapper) FromJSON(data string) (vm *ViewModel) {
vm = new(ViewModel)
m.data = data
vm.Object = m.Object.Call("fromJSON", m.args()...)
return
}
func (m *Mapper) ToJSON(vm *ViewModel) string {
return m.Object.Call("toJSON", vm.Object).String()
}
// Set mapping options
func (m *Mapper) Option(key string, value interface{}) *Mapper {
if m.options == nil {
m.options = js.Global.Get("Object").New()
}
m.options.Set(key, value)
return m
}
// Ignoring certain properties using “ignore”
func (m *Mapper) Ignore(properties ...string) *Mapper {
return m.Option("ignore", properties)
}
// Observing only certain properties using “observe”
func (m *Mapper) Observe(properties ...string) *Mapper {
return m.Option("observe", properties)
}
// func isArray(i interface{}) bool {
// v := reflect.ValueOf(i)
// v = reflect.Indirect(v)
// if v.Type().Kind() == reflect.Array {
// return true
// }
// return false
// }
func (v *ViewModel) Set(keyPath string, value interface{}) {
obj := property.Get(v.Object, keyPath)
if obj == js.Undefined {
// if isArray(value) {
// v.Set(key, NewObservableArray(value))
// } else {
// v.Set(key, NewObservable(value))
// }
panic("ViewModel has no key: " + keyPath)
} else {
obj.Invoke(value)
}
}
func (v *ViewModel) Get(keyPath string) *js.Object {
obj := property.Get(v.Object, keyPath)
if obj == js.Undefined {
return obj
}
return obj.Invoke()
}
func (v *ViewModel) Update(data interface{}) *ViewModel {
Mapping().Call("fromJS", data, v.Object)
return v
}