fluentd-ui 0.3.8 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fluentd-ui might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ChangeLog +9 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +4 -1
- data/app/assets/javascripts/vue/fluent_log.js +4 -4
- data/app/assets/javascripts/vue/in_tail_format.js +43 -49
- data/app/assets/javascripts/{alert.js → vue/notification.js} +21 -7
- data/app/assets/javascripts/vue/settings.js +121 -0
- data/app/assets/javascripts/vue/treeview.js +3 -3
- data/app/assets/stylesheets/common.css.scss +7 -1
- data/app/controllers/api/settings_controller.rb +55 -0
- data/app/controllers/api_controller.rb +6 -2
- data/app/controllers/concerns/setting_concern.rb +2 -2
- data/app/controllers/fluentd/settings_controller.rb +17 -2
- data/app/models/fluentd/setting/config.rb +39 -0
- data/app/views/api/settings/_element.json.jbuilder +6 -0
- data/app/views/api/settings/index.json.jbuilder +3 -0
- data/app/views/api/settings/show.json.jbuilder +1 -0
- data/app/views/fluentd/settings/edit.html.haml +3 -0
- data/app/views/fluentd/settings/source_and_output.html.haml +19 -2
- data/app/views/layouts/application.html.erb +1 -30
- data/app/views/shared/vue/_in_tail_format.html.erb +11 -36
- data/app/views/shared/vue/_notification.html.erb +31 -0
- data/app/views/shared/vue/_setting.html.erb +23 -0
- data/app/views/shared/vue/_treeview.html.erb +2 -2
- data/bower.json +1 -1
- data/config/application.rb +1 -0
- data/config/locales/translation_en.yml +11 -7
- data/config/locales/translation_ja.yml +4 -0
- data/config/routes.rb +2 -0
- data/lib/fluentd-ui/version.rb +1 -1
- data/spec/features/fluentd/setting/source_and_output_spec.rb +157 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/javascript_macro.rb +21 -0
- data/vendor/assets/javascripts/bower/vue/.bower.json +7 -7
- data/vendor/assets/javascripts/bower/vue/LICENSE +1 -1
- data/vendor/assets/javascripts/bower/vue/dist/vue.js +7822 -4768
- data/vendor/assets/javascripts/bower/vue/dist/vue.min.js +7 -7
- data/vendor/assets/javascripts/bower/vue/src/api/child.js +53 -0
- data/vendor/assets/javascripts/bower/vue/src/api/data.js +161 -0
- data/vendor/assets/javascripts/bower/vue/src/api/dom.js +211 -0
- data/vendor/assets/javascripts/bower/vue/src/api/events.js +176 -0
- data/vendor/assets/javascripts/bower/vue/src/api/global.js +146 -0
- data/vendor/assets/javascripts/bower/vue/src/api/lifecycle.js +144 -0
- data/vendor/assets/javascripts/bower/vue/src/batcher.js +52 -32
- data/vendor/assets/javascripts/bower/vue/src/cache.js +112 -0
- data/vendor/assets/javascripts/bower/vue/src/compiler/compile.js +549 -0
- data/vendor/assets/javascripts/bower/vue/src/compiler/transclude.js +163 -0
- data/vendor/assets/javascripts/bower/vue/src/config.js +74 -14
- data/vendor/assets/javascripts/bower/vue/src/directive.js +179 -219
- data/vendor/assets/javascripts/bower/vue/src/directives/attr.js +32 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/class.js +18 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/cloak.js +12 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/component.js +214 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/el.js +13 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/html.js +30 -34
- data/vendor/assets/javascripts/bower/vue/src/directives/if.js +77 -46
- data/vendor/assets/javascripts/bower/vue/src/directives/index.js +22 -129
- data/vendor/assets/javascripts/bower/vue/src/directives/model/checkbox.js +25 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/model/default.js +123 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/model/index.js +56 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/model/radio.js +26 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/model/select.js +166 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/on.js +51 -50
- data/vendor/assets/javascripts/bower/vue/src/directives/partial.js +36 -42
- data/vendor/assets/javascripts/bower/vue/src/directives/ref.js +24 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/repeat.js +477 -226
- data/vendor/assets/javascripts/bower/vue/src/directives/show.js +8 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/style.js +49 -37
- data/vendor/assets/javascripts/bower/vue/src/directives/text.js +15 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/transition.js +12 -0
- data/vendor/assets/javascripts/bower/vue/src/directives/with.js +38 -41
- data/vendor/assets/javascripts/bower/vue/src/filters/array-filters.js +87 -0
- data/vendor/assets/javascripts/bower/vue/src/filters/index.js +135 -0
- data/vendor/assets/javascripts/bower/vue/src/instance/compile.js +71 -0
- data/vendor/assets/javascripts/bower/vue/src/instance/events.js +122 -0
- data/vendor/assets/javascripts/bower/vue/src/instance/init.js +76 -0
- data/vendor/assets/javascripts/bower/vue/src/instance/scope.js +217 -0
- data/vendor/assets/javascripts/bower/vue/src/observer/array.js +90 -0
- data/vendor/assets/javascripts/bower/vue/src/observer/dep.js +50 -0
- data/vendor/assets/javascripts/bower/vue/src/observer/index.js +235 -0
- data/vendor/assets/javascripts/bower/vue/src/observer/object.js +75 -0
- data/vendor/assets/javascripts/bower/vue/src/parsers/directive.js +159 -0
- data/vendor/assets/javascripts/bower/vue/src/parsers/expression.js +226 -0
- data/vendor/assets/javascripts/bower/vue/src/parsers/path.js +300 -0
- data/vendor/assets/javascripts/bower/vue/src/parsers/template.js +246 -0
- data/vendor/assets/javascripts/bower/vue/src/parsers/text.js +178 -0
- data/vendor/assets/javascripts/bower/vue/src/transition/css.js +189 -0
- data/vendor/assets/javascripts/bower/vue/src/transition/index.js +151 -0
- data/vendor/assets/javascripts/bower/vue/src/transition/js.js +43 -0
- data/vendor/assets/javascripts/bower/vue/src/util/debug.js +50 -0
- data/vendor/assets/javascripts/bower/vue/src/util/dom.js +176 -0
- data/vendor/assets/javascripts/bower/vue/src/util/env.js +74 -0
- data/vendor/assets/javascripts/bower/vue/src/util/filter.js +72 -0
- data/vendor/assets/javascripts/bower/vue/src/util/index.js +8 -0
- data/vendor/assets/javascripts/bower/vue/src/util/lang.js +175 -0
- data/vendor/assets/javascripts/bower/vue/src/util/merge-option.js +258 -0
- data/vendor/assets/javascripts/bower/vue/src/vue.js +84 -0
- data/vendor/assets/javascripts/bower/vue/src/watcher.js +240 -0
- metadata +65 -20
- data/app/assets/javascripts/setting_format.js +0 -15
- data/vendor/assets/javascripts/bower/vue/src/binding.js +0 -103
- data/vendor/assets/javascripts/bower/vue/src/compiler.js +0 -1037
- data/vendor/assets/javascripts/bower/vue/src/deps-parser.js +0 -65
- data/vendor/assets/javascripts/bower/vue/src/directives/model.js +0 -174
- data/vendor/assets/javascripts/bower/vue/src/directives/view.js +0 -56
- data/vendor/assets/javascripts/bower/vue/src/emitter.js +0 -97
- data/vendor/assets/javascripts/bower/vue/src/exp-parser.js +0 -190
- data/vendor/assets/javascripts/bower/vue/src/filters.js +0 -191
- data/vendor/assets/javascripts/bower/vue/src/fragment.js +0 -67
- data/vendor/assets/javascripts/bower/vue/src/main.js +0 -188
- data/vendor/assets/javascripts/bower/vue/src/observer.js +0 -446
- data/vendor/assets/javascripts/bower/vue/src/template-parser.js +0 -46
- data/vendor/assets/javascripts/bower/vue/src/text-parser.js +0 -96
- data/vendor/assets/javascripts/bower/vue/src/transition.js +0 -228
- data/vendor/assets/javascripts/bower/vue/src/utils.js +0 -326
- data/vendor/assets/javascripts/bower/vue/src/viewmodel.js +0 -190
@@ -1,191 +0,0 @@
|
|
1
|
-
var utils = require('./utils'),
|
2
|
-
get = utils.get,
|
3
|
-
slice = [].slice,
|
4
|
-
QUOTE_RE = /^'.*'$/,
|
5
|
-
filters = module.exports = utils.hash()
|
6
|
-
|
7
|
-
/**
|
8
|
-
* 'abc' => 'Abc'
|
9
|
-
*/
|
10
|
-
filters.capitalize = function (value) {
|
11
|
-
if (!value && value !== 0) return ''
|
12
|
-
value = value.toString()
|
13
|
-
return value.charAt(0).toUpperCase() + value.slice(1)
|
14
|
-
}
|
15
|
-
|
16
|
-
/**
|
17
|
-
* 'abc' => 'ABC'
|
18
|
-
*/
|
19
|
-
filters.uppercase = function (value) {
|
20
|
-
return (value || value === 0)
|
21
|
-
? value.toString().toUpperCase()
|
22
|
-
: ''
|
23
|
-
}
|
24
|
-
|
25
|
-
/**
|
26
|
-
* 'AbC' => 'abc'
|
27
|
-
*/
|
28
|
-
filters.lowercase = function (value) {
|
29
|
-
return (value || value === 0)
|
30
|
-
? value.toString().toLowerCase()
|
31
|
-
: ''
|
32
|
-
}
|
33
|
-
|
34
|
-
/**
|
35
|
-
* 12345 => $12,345.00
|
36
|
-
*/
|
37
|
-
filters.currency = function (value, sign) {
|
38
|
-
value = parseFloat(value)
|
39
|
-
if (!value && value !== 0) return ''
|
40
|
-
sign = sign || '$'
|
41
|
-
var s = Math.floor(value).toString(),
|
42
|
-
i = s.length % 3,
|
43
|
-
h = i > 0 ? (s.slice(0, i) + (s.length > 3 ? ',' : '')) : '',
|
44
|
-
f = '.' + value.toFixed(2).slice(-2)
|
45
|
-
return sign + h + s.slice(i).replace(/(\d{3})(?=\d)/g, '$1,') + f
|
46
|
-
}
|
47
|
-
|
48
|
-
/**
|
49
|
-
* args: an array of strings corresponding to
|
50
|
-
* the single, double, triple ... forms of the word to
|
51
|
-
* be pluralized. When the number to be pluralized
|
52
|
-
* exceeds the length of the args, it will use the last
|
53
|
-
* entry in the array.
|
54
|
-
*
|
55
|
-
* e.g. ['single', 'double', 'triple', 'multiple']
|
56
|
-
*/
|
57
|
-
filters.pluralize = function (value) {
|
58
|
-
var args = slice.call(arguments, 1)
|
59
|
-
return args.length > 1
|
60
|
-
? (args[value - 1] || args[args.length - 1])
|
61
|
-
: (args[value - 1] || args[0] + 's')
|
62
|
-
}
|
63
|
-
|
64
|
-
/**
|
65
|
-
* A special filter that takes a handler function,
|
66
|
-
* wraps it so it only gets triggered on specific keypresses.
|
67
|
-
*
|
68
|
-
* v-on only
|
69
|
-
*/
|
70
|
-
|
71
|
-
var keyCodes = {
|
72
|
-
enter : 13,
|
73
|
-
tab : 9,
|
74
|
-
'delete' : 46,
|
75
|
-
up : 38,
|
76
|
-
left : 37,
|
77
|
-
right : 39,
|
78
|
-
down : 40,
|
79
|
-
esc : 27
|
80
|
-
}
|
81
|
-
|
82
|
-
filters.key = function (handler, key) {
|
83
|
-
if (!handler) return
|
84
|
-
var code = keyCodes[key]
|
85
|
-
if (!code) {
|
86
|
-
code = parseInt(key, 10)
|
87
|
-
}
|
88
|
-
return function (e) {
|
89
|
-
if (e.keyCode === code) {
|
90
|
-
return handler.call(this, e)
|
91
|
-
}
|
92
|
-
}
|
93
|
-
}
|
94
|
-
|
95
|
-
/**
|
96
|
-
* Filter filter for v-repeat
|
97
|
-
*/
|
98
|
-
filters.filterBy = function (arr, searchKey, delimiter, dataKey) {
|
99
|
-
|
100
|
-
// allow optional `in` delimiter
|
101
|
-
// because why not
|
102
|
-
if (delimiter && delimiter !== 'in') {
|
103
|
-
dataKey = delimiter
|
104
|
-
}
|
105
|
-
|
106
|
-
// get the search string
|
107
|
-
var search = stripQuotes(searchKey) || this.$get(searchKey)
|
108
|
-
if (!search) return arr
|
109
|
-
search = search.toLowerCase()
|
110
|
-
|
111
|
-
// get the optional dataKey
|
112
|
-
dataKey = dataKey && (stripQuotes(dataKey) || this.$get(dataKey))
|
113
|
-
|
114
|
-
// convert object to array
|
115
|
-
if (!Array.isArray(arr)) {
|
116
|
-
arr = utils.objectToArray(arr)
|
117
|
-
}
|
118
|
-
|
119
|
-
return arr.filter(function (item) {
|
120
|
-
return dataKey
|
121
|
-
? contains(get(item, dataKey), search)
|
122
|
-
: contains(item, search)
|
123
|
-
})
|
124
|
-
|
125
|
-
}
|
126
|
-
|
127
|
-
filters.filterBy.computed = true
|
128
|
-
|
129
|
-
/**
|
130
|
-
* Sort fitler for v-repeat
|
131
|
-
*/
|
132
|
-
filters.orderBy = function (arr, sortKey, reverseKey) {
|
133
|
-
|
134
|
-
var key = stripQuotes(sortKey) || this.$get(sortKey)
|
135
|
-
if (!key) return arr
|
136
|
-
|
137
|
-
// convert object to array
|
138
|
-
if (!Array.isArray(arr)) {
|
139
|
-
arr = utils.objectToArray(arr)
|
140
|
-
}
|
141
|
-
|
142
|
-
var order = 1
|
143
|
-
if (reverseKey) {
|
144
|
-
if (reverseKey === '-1') {
|
145
|
-
order = -1
|
146
|
-
} else if (reverseKey.charAt(0) === '!') {
|
147
|
-
reverseKey = reverseKey.slice(1)
|
148
|
-
order = this.$get(reverseKey) ? 1 : -1
|
149
|
-
} else {
|
150
|
-
order = this.$get(reverseKey) ? -1 : 1
|
151
|
-
}
|
152
|
-
}
|
153
|
-
|
154
|
-
// sort on a copy to avoid mutating original array
|
155
|
-
return arr.slice().sort(function (a, b) {
|
156
|
-
a = get(a, key)
|
157
|
-
b = get(b, key)
|
158
|
-
return a === b ? 0 : a > b ? order : -order
|
159
|
-
})
|
160
|
-
|
161
|
-
}
|
162
|
-
|
163
|
-
filters.orderBy.computed = true
|
164
|
-
|
165
|
-
// Array filter helpers -------------------------------------------------------
|
166
|
-
|
167
|
-
/**
|
168
|
-
* String contain helper
|
169
|
-
*/
|
170
|
-
function contains (val, search) {
|
171
|
-
/* jshint eqeqeq: false */
|
172
|
-
if (utils.isObject(val)) {
|
173
|
-
for (var key in val) {
|
174
|
-
if (contains(val[key], search)) {
|
175
|
-
return true
|
176
|
-
}
|
177
|
-
}
|
178
|
-
} else if (val != null) {
|
179
|
-
return val.toString().toLowerCase().indexOf(search) > -1
|
180
|
-
}
|
181
|
-
}
|
182
|
-
|
183
|
-
/**
|
184
|
-
* Test whether a string is in quotes,
|
185
|
-
* if yes return stripped string
|
186
|
-
*/
|
187
|
-
function stripQuotes (str) {
|
188
|
-
if (QUOTE_RE.test(str)) {
|
189
|
-
return str.slice(1, -1)
|
190
|
-
}
|
191
|
-
}
|
@@ -1,67 +0,0 @@
|
|
1
|
-
// string -> DOM conversion
|
2
|
-
// wrappers originally from jQuery, scooped from component/domify
|
3
|
-
var map = {
|
4
|
-
legend : [1, '<fieldset>', '</fieldset>'],
|
5
|
-
tr : [2, '<table><tbody>', '</tbody></table>'],
|
6
|
-
col : [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
|
7
|
-
_default : [0, '', '']
|
8
|
-
}
|
9
|
-
|
10
|
-
map.td =
|
11
|
-
map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>']
|
12
|
-
|
13
|
-
map.option =
|
14
|
-
map.optgroup = [1, '<select multiple="multiple">', '</select>']
|
15
|
-
|
16
|
-
map.thead =
|
17
|
-
map.tbody =
|
18
|
-
map.colgroup =
|
19
|
-
map.caption =
|
20
|
-
map.tfoot = [1, '<table>', '</table>']
|
21
|
-
|
22
|
-
map.text =
|
23
|
-
map.circle =
|
24
|
-
map.ellipse =
|
25
|
-
map.line =
|
26
|
-
map.path =
|
27
|
-
map.polygon =
|
28
|
-
map.polyline =
|
29
|
-
map.rect = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>']
|
30
|
-
|
31
|
-
var TAG_RE = /<([\w:]+)/
|
32
|
-
|
33
|
-
module.exports = function (templateString) {
|
34
|
-
var frag = document.createDocumentFragment(),
|
35
|
-
m = TAG_RE.exec(templateString)
|
36
|
-
// text only
|
37
|
-
if (!m) {
|
38
|
-
frag.appendChild(document.createTextNode(templateString))
|
39
|
-
return frag
|
40
|
-
}
|
41
|
-
|
42
|
-
var tag = m[1],
|
43
|
-
wrap = map[tag] || map._default,
|
44
|
-
depth = wrap[0],
|
45
|
-
prefix = wrap[1],
|
46
|
-
suffix = wrap[2],
|
47
|
-
node = document.createElement('div')
|
48
|
-
|
49
|
-
node.innerHTML = prefix + templateString.trim() + suffix
|
50
|
-
while (depth--) node = node.lastChild
|
51
|
-
|
52
|
-
// one element
|
53
|
-
if (node.firstChild === node.lastChild) {
|
54
|
-
frag.appendChild(node.firstChild)
|
55
|
-
return frag
|
56
|
-
}
|
57
|
-
|
58
|
-
// multiple nodes, return a fragment
|
59
|
-
var child
|
60
|
-
/* jshint boss: true */
|
61
|
-
while (child = node.firstChild) {
|
62
|
-
if (node.nodeType === 1) {
|
63
|
-
frag.appendChild(child)
|
64
|
-
}
|
65
|
-
}
|
66
|
-
return frag
|
67
|
-
}
|
@@ -1,188 +0,0 @@
|
|
1
|
-
var config = require('./config'),
|
2
|
-
ViewModel = require('./viewmodel'),
|
3
|
-
utils = require('./utils'),
|
4
|
-
makeHash = utils.hash,
|
5
|
-
assetTypes = ['directive', 'filter', 'partial', 'effect', 'component'],
|
6
|
-
// Internal modules that are exposed for plugins
|
7
|
-
pluginAPI = {
|
8
|
-
utils: utils,
|
9
|
-
config: config,
|
10
|
-
transition: require('./transition'),
|
11
|
-
observer: require('./observer')
|
12
|
-
}
|
13
|
-
|
14
|
-
ViewModel.options = config.globalAssets = {
|
15
|
-
directives : require('./directives'),
|
16
|
-
filters : require('./filters'),
|
17
|
-
partials : makeHash(),
|
18
|
-
effects : makeHash(),
|
19
|
-
components : makeHash()
|
20
|
-
}
|
21
|
-
|
22
|
-
/**
|
23
|
-
* Expose asset registration methods
|
24
|
-
*/
|
25
|
-
assetTypes.forEach(function (type) {
|
26
|
-
ViewModel[type] = function (id, value) {
|
27
|
-
var hash = this.options[type + 's']
|
28
|
-
if (!hash) {
|
29
|
-
hash = this.options[type + 's'] = makeHash()
|
30
|
-
}
|
31
|
-
if (!value) return hash[id]
|
32
|
-
if (type === 'partial') {
|
33
|
-
value = utils.parseTemplateOption(value)
|
34
|
-
} else if (type === 'component') {
|
35
|
-
value = utils.toConstructor(value)
|
36
|
-
} else if (type === 'filter') {
|
37
|
-
utils.checkFilter(value)
|
38
|
-
}
|
39
|
-
hash[id] = value
|
40
|
-
return this
|
41
|
-
}
|
42
|
-
})
|
43
|
-
|
44
|
-
/**
|
45
|
-
* Set config options
|
46
|
-
*/
|
47
|
-
ViewModel.config = function (opts, val) {
|
48
|
-
if (typeof opts === 'string') {
|
49
|
-
if (val === undefined) {
|
50
|
-
return config[opts]
|
51
|
-
} else {
|
52
|
-
config[opts] = val
|
53
|
-
}
|
54
|
-
} else {
|
55
|
-
utils.extend(config, opts)
|
56
|
-
}
|
57
|
-
return this
|
58
|
-
}
|
59
|
-
|
60
|
-
/**
|
61
|
-
* Expose an interface for plugins
|
62
|
-
*/
|
63
|
-
ViewModel.use = function (plugin) {
|
64
|
-
if (typeof plugin === 'string') {
|
65
|
-
try {
|
66
|
-
plugin = require(plugin)
|
67
|
-
} catch (e) {
|
68
|
-
utils.warn('Cannot find plugin: ' + plugin)
|
69
|
-
return
|
70
|
-
}
|
71
|
-
}
|
72
|
-
|
73
|
-
// additional parameters
|
74
|
-
var args = [].slice.call(arguments, 1)
|
75
|
-
args.unshift(this)
|
76
|
-
|
77
|
-
if (typeof plugin.install === 'function') {
|
78
|
-
plugin.install.apply(plugin, args)
|
79
|
-
} else {
|
80
|
-
plugin.apply(null, args)
|
81
|
-
}
|
82
|
-
return this
|
83
|
-
}
|
84
|
-
|
85
|
-
/**
|
86
|
-
* Expose internal modules for plugins
|
87
|
-
*/
|
88
|
-
ViewModel.require = function (module) {
|
89
|
-
return pluginAPI[module]
|
90
|
-
}
|
91
|
-
|
92
|
-
ViewModel.extend = extend
|
93
|
-
ViewModel.nextTick = utils.nextTick
|
94
|
-
|
95
|
-
/**
|
96
|
-
* Expose the main ViewModel class
|
97
|
-
* and add extend method
|
98
|
-
*/
|
99
|
-
function extend (options) {
|
100
|
-
|
101
|
-
var ParentVM = this
|
102
|
-
|
103
|
-
// extend data options need to be copied
|
104
|
-
// on instantiation
|
105
|
-
if (options.data) {
|
106
|
-
options.defaultData = options.data
|
107
|
-
delete options.data
|
108
|
-
}
|
109
|
-
|
110
|
-
// inherit options
|
111
|
-
// but only when the super class is not the native Vue.
|
112
|
-
if (ParentVM !== ViewModel) {
|
113
|
-
options = inheritOptions(options, ParentVM.options, true)
|
114
|
-
}
|
115
|
-
utils.processOptions(options)
|
116
|
-
|
117
|
-
var ExtendedVM = function (opts, asParent) {
|
118
|
-
if (!asParent) {
|
119
|
-
opts = inheritOptions(opts, options, true)
|
120
|
-
}
|
121
|
-
ParentVM.call(this, opts, true)
|
122
|
-
}
|
123
|
-
|
124
|
-
// inherit prototype props
|
125
|
-
var proto = ExtendedVM.prototype = Object.create(ParentVM.prototype)
|
126
|
-
utils.defProtected(proto, 'constructor', ExtendedVM)
|
127
|
-
|
128
|
-
// allow extended VM to be further extended
|
129
|
-
ExtendedVM.extend = extend
|
130
|
-
ExtendedVM.super = ParentVM
|
131
|
-
ExtendedVM.options = options
|
132
|
-
|
133
|
-
// allow extended VM to add its own assets
|
134
|
-
assetTypes.forEach(function (type) {
|
135
|
-
ExtendedVM[type] = ViewModel[type]
|
136
|
-
})
|
137
|
-
|
138
|
-
// allow extended VM to use plugins
|
139
|
-
ExtendedVM.use = ViewModel.use
|
140
|
-
ExtendedVM.require = ViewModel.require
|
141
|
-
|
142
|
-
return ExtendedVM
|
143
|
-
}
|
144
|
-
|
145
|
-
/**
|
146
|
-
* Inherit options
|
147
|
-
*
|
148
|
-
* For options such as `data`, `vms`, `directives`, 'partials',
|
149
|
-
* they should be further extended. However extending should only
|
150
|
-
* be done at top level.
|
151
|
-
*
|
152
|
-
* `proto` is an exception because it's handled directly on the
|
153
|
-
* prototype.
|
154
|
-
*
|
155
|
-
* `el` is an exception because it's not allowed as an
|
156
|
-
* extension option, but only as an instance option.
|
157
|
-
*/
|
158
|
-
function inheritOptions (child, parent, topLevel) {
|
159
|
-
child = child || {}
|
160
|
-
if (!parent) return child
|
161
|
-
for (var key in parent) {
|
162
|
-
if (key === 'el') continue
|
163
|
-
var val = child[key],
|
164
|
-
parentVal = parent[key]
|
165
|
-
if (topLevel && typeof val === 'function' && parentVal) {
|
166
|
-
// merge hook functions into an array
|
167
|
-
child[key] = [val]
|
168
|
-
if (Array.isArray(parentVal)) {
|
169
|
-
child[key] = child[key].concat(parentVal)
|
170
|
-
} else {
|
171
|
-
child[key].push(parentVal)
|
172
|
-
}
|
173
|
-
} else if (
|
174
|
-
topLevel &&
|
175
|
-
(utils.isTrueObject(val) || utils.isTrueObject(parentVal))
|
176
|
-
&& !(parentVal instanceof ViewModel)
|
177
|
-
) {
|
178
|
-
// merge toplevel object options
|
179
|
-
child[key] = inheritOptions(val, parentVal)
|
180
|
-
} else if (val === undefined) {
|
181
|
-
// inherit if child doesn't override
|
182
|
-
child[key] = parentVal
|
183
|
-
}
|
184
|
-
}
|
185
|
-
return child
|
186
|
-
}
|
187
|
-
|
188
|
-
module.exports = ViewModel
|
@@ -1,446 +0,0 @@
|
|
1
|
-
/* jshint proto:true */
|
2
|
-
|
3
|
-
var Emitter = require('./emitter'),
|
4
|
-
utils = require('./utils'),
|
5
|
-
// cache methods
|
6
|
-
def = utils.defProtected,
|
7
|
-
isObject = utils.isObject,
|
8
|
-
isArray = Array.isArray,
|
9
|
-
hasOwn = ({}).hasOwnProperty,
|
10
|
-
oDef = Object.defineProperty,
|
11
|
-
slice = [].slice,
|
12
|
-
// fix for IE + __proto__ problem
|
13
|
-
// define methods as inenumerable if __proto__ is present,
|
14
|
-
// otherwise enumerable so we can loop through and manually
|
15
|
-
// attach to array instances
|
16
|
-
hasProto = ({}).__proto__
|
17
|
-
|
18
|
-
// Array Mutation Handlers & Augmentations ------------------------------------
|
19
|
-
|
20
|
-
// The proxy prototype to replace the __proto__ of
|
21
|
-
// an observed array
|
22
|
-
var ArrayProxy = Object.create(Array.prototype)
|
23
|
-
|
24
|
-
// intercept mutation methods
|
25
|
-
;[
|
26
|
-
'push',
|
27
|
-
'pop',
|
28
|
-
'shift',
|
29
|
-
'unshift',
|
30
|
-
'splice',
|
31
|
-
'sort',
|
32
|
-
'reverse'
|
33
|
-
].forEach(watchMutation)
|
34
|
-
|
35
|
-
// Augment the ArrayProxy with convenience methods
|
36
|
-
def(ArrayProxy, '$set', function (index, data) {
|
37
|
-
return this.splice(index, 1, data)[0]
|
38
|
-
}, !hasProto)
|
39
|
-
|
40
|
-
def(ArrayProxy, '$remove', function (index) {
|
41
|
-
if (typeof index !== 'number') {
|
42
|
-
index = this.indexOf(index)
|
43
|
-
}
|
44
|
-
if (index > -1) {
|
45
|
-
return this.splice(index, 1)[0]
|
46
|
-
}
|
47
|
-
}, !hasProto)
|
48
|
-
|
49
|
-
/**
|
50
|
-
* Intercep a mutation event so we can emit the mutation info.
|
51
|
-
* we also analyze what elements are added/removed and link/unlink
|
52
|
-
* them with the parent Array.
|
53
|
-
*/
|
54
|
-
function watchMutation (method) {
|
55
|
-
def(ArrayProxy, method, function () {
|
56
|
-
|
57
|
-
var args = slice.call(arguments),
|
58
|
-
result = Array.prototype[method].apply(this, args),
|
59
|
-
inserted, removed
|
60
|
-
|
61
|
-
// determine new / removed elements
|
62
|
-
if (method === 'push' || method === 'unshift') {
|
63
|
-
inserted = args
|
64
|
-
} else if (method === 'pop' || method === 'shift') {
|
65
|
-
removed = [result]
|
66
|
-
} else if (method === 'splice') {
|
67
|
-
inserted = args.slice(2)
|
68
|
-
removed = result
|
69
|
-
}
|
70
|
-
|
71
|
-
// link & unlink
|
72
|
-
linkArrayElements(this, inserted)
|
73
|
-
unlinkArrayElements(this, removed)
|
74
|
-
|
75
|
-
// emit the mutation event
|
76
|
-
this.__emitter__.emit('mutate', '', this, {
|
77
|
-
method : method,
|
78
|
-
args : args,
|
79
|
-
result : result,
|
80
|
-
inserted : inserted,
|
81
|
-
removed : removed
|
82
|
-
})
|
83
|
-
|
84
|
-
return result
|
85
|
-
|
86
|
-
}, !hasProto)
|
87
|
-
}
|
88
|
-
|
89
|
-
/**
|
90
|
-
* Link new elements to an Array, so when they change
|
91
|
-
* and emit events, the owner Array can be notified.
|
92
|
-
*/
|
93
|
-
function linkArrayElements (arr, items) {
|
94
|
-
if (items) {
|
95
|
-
var i = items.length, item, owners
|
96
|
-
while (i--) {
|
97
|
-
item = items[i]
|
98
|
-
if (isWatchable(item)) {
|
99
|
-
// if object is not converted for observing
|
100
|
-
// convert it...
|
101
|
-
if (!item.__emitter__) {
|
102
|
-
convert(item)
|
103
|
-
watch(item)
|
104
|
-
}
|
105
|
-
owners = item.__emitter__.owners
|
106
|
-
if (owners.indexOf(arr) < 0) {
|
107
|
-
owners.push(arr)
|
108
|
-
}
|
109
|
-
}
|
110
|
-
}
|
111
|
-
}
|
112
|
-
}
|
113
|
-
|
114
|
-
/**
|
115
|
-
* Unlink removed elements from the ex-owner Array.
|
116
|
-
*/
|
117
|
-
function unlinkArrayElements (arr, items) {
|
118
|
-
if (items) {
|
119
|
-
var i = items.length, item
|
120
|
-
while (i--) {
|
121
|
-
item = items[i]
|
122
|
-
if (item && item.__emitter__) {
|
123
|
-
var owners = item.__emitter__.owners
|
124
|
-
if (owners) owners.splice(owners.indexOf(arr))
|
125
|
-
}
|
126
|
-
}
|
127
|
-
}
|
128
|
-
}
|
129
|
-
|
130
|
-
// Object add/delete key augmentation -----------------------------------------
|
131
|
-
|
132
|
-
var ObjProxy = Object.create(Object.prototype)
|
133
|
-
|
134
|
-
def(ObjProxy, '$add', function (key, val) {
|
135
|
-
if (hasOwn.call(this, key)) return
|
136
|
-
this[key] = val
|
137
|
-
convertKey(this, key, true)
|
138
|
-
}, !hasProto)
|
139
|
-
|
140
|
-
def(ObjProxy, '$delete', function (key) {
|
141
|
-
if (!(hasOwn.call(this, key))) return
|
142
|
-
// trigger set events
|
143
|
-
this[key] = undefined
|
144
|
-
delete this[key]
|
145
|
-
this.__emitter__.emit('delete', key)
|
146
|
-
}, !hasProto)
|
147
|
-
|
148
|
-
// Watch Helpers --------------------------------------------------------------
|
149
|
-
|
150
|
-
/**
|
151
|
-
* Check if a value is watchable
|
152
|
-
*/
|
153
|
-
function isWatchable (obj) {
|
154
|
-
return typeof obj === 'object' && obj && !obj.$compiler
|
155
|
-
}
|
156
|
-
|
157
|
-
/**
|
158
|
-
* Convert an Object/Array to give it a change emitter.
|
159
|
-
*/
|
160
|
-
function convert (obj) {
|
161
|
-
if (obj.__emitter__) return true
|
162
|
-
var emitter = new Emitter()
|
163
|
-
def(obj, '__emitter__', emitter)
|
164
|
-
emitter
|
165
|
-
.on('set', function (key, val, propagate) {
|
166
|
-
if (propagate) propagateChange(obj)
|
167
|
-
})
|
168
|
-
.on('mutate', function () {
|
169
|
-
propagateChange(obj)
|
170
|
-
})
|
171
|
-
emitter.values = utils.hash()
|
172
|
-
emitter.owners = []
|
173
|
-
return false
|
174
|
-
}
|
175
|
-
|
176
|
-
/**
|
177
|
-
* Propagate an array element's change to its owner arrays
|
178
|
-
*/
|
179
|
-
function propagateChange (obj) {
|
180
|
-
var owners = obj.__emitter__.owners,
|
181
|
-
i = owners.length
|
182
|
-
while (i--) {
|
183
|
-
owners[i].__emitter__.emit('set', '', '', true)
|
184
|
-
}
|
185
|
-
}
|
186
|
-
|
187
|
-
/**
|
188
|
-
* Watch target based on its type
|
189
|
-
*/
|
190
|
-
function watch (obj) {
|
191
|
-
if (isArray(obj)) {
|
192
|
-
watchArray(obj)
|
193
|
-
} else {
|
194
|
-
watchObject(obj)
|
195
|
-
}
|
196
|
-
}
|
197
|
-
|
198
|
-
/**
|
199
|
-
* Augment target objects with modified
|
200
|
-
* methods
|
201
|
-
*/
|
202
|
-
function augment (target, src) {
|
203
|
-
if (hasProto) {
|
204
|
-
target.__proto__ = src
|
205
|
-
} else {
|
206
|
-
for (var key in src) {
|
207
|
-
def(target, key, src[key])
|
208
|
-
}
|
209
|
-
}
|
210
|
-
}
|
211
|
-
|
212
|
-
/**
|
213
|
-
* Watch an Object, recursive.
|
214
|
-
*/
|
215
|
-
function watchObject (obj) {
|
216
|
-
augment(obj, ObjProxy)
|
217
|
-
for (var key in obj) {
|
218
|
-
convertKey(obj, key)
|
219
|
-
}
|
220
|
-
}
|
221
|
-
|
222
|
-
/**
|
223
|
-
* Watch an Array, overload mutation methods
|
224
|
-
* and add augmentations by intercepting the prototype chain
|
225
|
-
*/
|
226
|
-
function watchArray (arr) {
|
227
|
-
augment(arr, ArrayProxy)
|
228
|
-
linkArrayElements(arr, arr)
|
229
|
-
}
|
230
|
-
|
231
|
-
/**
|
232
|
-
* Define accessors for a property on an Object
|
233
|
-
* so it emits get/set events.
|
234
|
-
* Then watch the value itself.
|
235
|
-
*/
|
236
|
-
function convertKey (obj, key, propagate) {
|
237
|
-
var keyPrefix = key.charAt(0)
|
238
|
-
if (keyPrefix === '$' || keyPrefix === '_') {
|
239
|
-
return
|
240
|
-
}
|
241
|
-
// emit set on bind
|
242
|
-
// this means when an object is observed it will emit
|
243
|
-
// a first batch of set events.
|
244
|
-
var emitter = obj.__emitter__,
|
245
|
-
values = emitter.values
|
246
|
-
|
247
|
-
init(obj[key], propagate)
|
248
|
-
|
249
|
-
oDef(obj, key, {
|
250
|
-
enumerable: true,
|
251
|
-
configurable: true,
|
252
|
-
get: function () {
|
253
|
-
var value = values[key]
|
254
|
-
// only emit get on tip values
|
255
|
-
if (pub.shouldGet) {
|
256
|
-
emitter.emit('get', key)
|
257
|
-
}
|
258
|
-
return value
|
259
|
-
},
|
260
|
-
set: function (newVal) {
|
261
|
-
var oldVal = values[key]
|
262
|
-
unobserve(oldVal, key, emitter)
|
263
|
-
copyPaths(newVal, oldVal)
|
264
|
-
// an immediate property should notify its parent
|
265
|
-
// to emit set for itself too
|
266
|
-
init(newVal, true)
|
267
|
-
}
|
268
|
-
})
|
269
|
-
|
270
|
-
function init (val, propagate) {
|
271
|
-
values[key] = val
|
272
|
-
emitter.emit('set', key, val, propagate)
|
273
|
-
if (isArray(val)) {
|
274
|
-
emitter.emit('set', key + '.length', val.length, propagate)
|
275
|
-
}
|
276
|
-
observe(val, key, emitter)
|
277
|
-
}
|
278
|
-
}
|
279
|
-
|
280
|
-
/**
|
281
|
-
* When a value that is already converted is
|
282
|
-
* observed again by another observer, we can skip
|
283
|
-
* the watch conversion and simply emit set event for
|
284
|
-
* all of its properties.
|
285
|
-
*/
|
286
|
-
function emitSet (obj) {
|
287
|
-
var emitter = obj && obj.__emitter__
|
288
|
-
if (!emitter) return
|
289
|
-
if (isArray(obj)) {
|
290
|
-
emitter.emit('set', 'length', obj.length)
|
291
|
-
} else {
|
292
|
-
var key, val
|
293
|
-
for (key in obj) {
|
294
|
-
val = obj[key]
|
295
|
-
emitter.emit('set', key, val)
|
296
|
-
emitSet(val)
|
297
|
-
}
|
298
|
-
}
|
299
|
-
}
|
300
|
-
|
301
|
-
/**
|
302
|
-
* Make sure all the paths in an old object exists
|
303
|
-
* in a new object.
|
304
|
-
* So when an object changes, all missing keys will
|
305
|
-
* emit a set event with undefined value.
|
306
|
-
*/
|
307
|
-
function copyPaths (newObj, oldObj) {
|
308
|
-
if (!isObject(newObj) || !isObject(oldObj)) {
|
309
|
-
return
|
310
|
-
}
|
311
|
-
var path, oldVal, newVal
|
312
|
-
for (path in oldObj) {
|
313
|
-
if (!(hasOwn.call(newObj, path))) {
|
314
|
-
oldVal = oldObj[path]
|
315
|
-
if (isArray(oldVal)) {
|
316
|
-
newObj[path] = []
|
317
|
-
} else if (isObject(oldVal)) {
|
318
|
-
newVal = newObj[path] = {}
|
319
|
-
copyPaths(newVal, oldVal)
|
320
|
-
} else {
|
321
|
-
newObj[path] = undefined
|
322
|
-
}
|
323
|
-
}
|
324
|
-
}
|
325
|
-
}
|
326
|
-
|
327
|
-
/**
|
328
|
-
* walk along a path and make sure it can be accessed
|
329
|
-
* and enumerated in that object
|
330
|
-
*/
|
331
|
-
function ensurePath (obj, key) {
|
332
|
-
var path = key.split('.'), sec
|
333
|
-
for (var i = 0, d = path.length - 1; i < d; i++) {
|
334
|
-
sec = path[i]
|
335
|
-
if (!obj[sec]) {
|
336
|
-
obj[sec] = {}
|
337
|
-
if (obj.__emitter__) convertKey(obj, sec)
|
338
|
-
}
|
339
|
-
obj = obj[sec]
|
340
|
-
}
|
341
|
-
if (isObject(obj)) {
|
342
|
-
sec = path[i]
|
343
|
-
if (!(hasOwn.call(obj, sec))) {
|
344
|
-
obj[sec] = undefined
|
345
|
-
if (obj.__emitter__) convertKey(obj, sec)
|
346
|
-
}
|
347
|
-
}
|
348
|
-
}
|
349
|
-
|
350
|
-
// Main API Methods -----------------------------------------------------------
|
351
|
-
|
352
|
-
/**
|
353
|
-
* Observe an object with a given path,
|
354
|
-
* and proxy get/set/mutate events to the provided observer.
|
355
|
-
*/
|
356
|
-
function observe (obj, rawPath, observer) {
|
357
|
-
|
358
|
-
if (!isWatchable(obj)) return
|
359
|
-
|
360
|
-
var path = rawPath ? rawPath + '.' : '',
|
361
|
-
alreadyConverted = convert(obj),
|
362
|
-
emitter = obj.__emitter__
|
363
|
-
|
364
|
-
// setup proxy listeners on the parent observer.
|
365
|
-
// we need to keep reference to them so that they
|
366
|
-
// can be removed when the object is un-observed.
|
367
|
-
observer.proxies = observer.proxies || {}
|
368
|
-
var proxies = observer.proxies[path] = {
|
369
|
-
get: function (key) {
|
370
|
-
observer.emit('get', path + key)
|
371
|
-
},
|
372
|
-
set: function (key, val, propagate) {
|
373
|
-
if (key) observer.emit('set', path + key, val)
|
374
|
-
// also notify observer that the object itself changed
|
375
|
-
// but only do so when it's a immediate property. this
|
376
|
-
// avoids duplicate event firing.
|
377
|
-
if (rawPath && propagate) {
|
378
|
-
observer.emit('set', rawPath, obj, true)
|
379
|
-
}
|
380
|
-
},
|
381
|
-
mutate: function (key, val, mutation) {
|
382
|
-
// if the Array is a root value
|
383
|
-
// the key will be null
|
384
|
-
var fixedPath = key ? path + key : rawPath
|
385
|
-
observer.emit('mutate', fixedPath, val, mutation)
|
386
|
-
// also emit set for Array's length when it mutates
|
387
|
-
var m = mutation.method
|
388
|
-
if (m !== 'sort' && m !== 'reverse') {
|
389
|
-
observer.emit('set', fixedPath + '.length', val.length)
|
390
|
-
}
|
391
|
-
}
|
392
|
-
}
|
393
|
-
|
394
|
-
// attach the listeners to the child observer.
|
395
|
-
// now all the events will propagate upwards.
|
396
|
-
emitter
|
397
|
-
.on('get', proxies.get)
|
398
|
-
.on('set', proxies.set)
|
399
|
-
.on('mutate', proxies.mutate)
|
400
|
-
|
401
|
-
if (alreadyConverted) {
|
402
|
-
// for objects that have already been converted,
|
403
|
-
// emit set events for everything inside
|
404
|
-
emitSet(obj)
|
405
|
-
} else {
|
406
|
-
watch(obj)
|
407
|
-
}
|
408
|
-
}
|
409
|
-
|
410
|
-
/**
|
411
|
-
* Cancel observation, turn off the listeners.
|
412
|
-
*/
|
413
|
-
function unobserve (obj, path, observer) {
|
414
|
-
|
415
|
-
if (!obj || !obj.__emitter__) return
|
416
|
-
|
417
|
-
path = path ? path + '.' : ''
|
418
|
-
var proxies = observer.proxies[path]
|
419
|
-
if (!proxies) return
|
420
|
-
|
421
|
-
// turn off listeners
|
422
|
-
obj.__emitter__
|
423
|
-
.off('get', proxies.get)
|
424
|
-
.off('set', proxies.set)
|
425
|
-
.off('mutate', proxies.mutate)
|
426
|
-
|
427
|
-
// remove reference
|
428
|
-
observer.proxies[path] = null
|
429
|
-
}
|
430
|
-
|
431
|
-
// Expose API -----------------------------------------------------------------
|
432
|
-
|
433
|
-
var pub = module.exports = {
|
434
|
-
|
435
|
-
// whether to emit get events
|
436
|
-
// only enabled during dependency parsing
|
437
|
-
shouldGet : false,
|
438
|
-
|
439
|
-
observe : observe,
|
440
|
-
unobserve : unobserve,
|
441
|
-
ensurePath : ensurePath,
|
442
|
-
copyPaths : copyPaths,
|
443
|
-
watch : watch,
|
444
|
-
convert : convert,
|
445
|
-
convertKey : convertKey
|
446
|
-
}
|