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,129 +1,22 @@
|
|
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
|
-
* Binding HTML attributes
|
28
|
-
*/
|
29
|
-
directives.attr = {
|
30
|
-
bind: function () {
|
31
|
-
var params = this.vm.$options.paramAttributes
|
32
|
-
this.isParam = params && params.indexOf(this.arg) > -1
|
33
|
-
},
|
34
|
-
update: function (value) {
|
35
|
-
if (value || value === 0) {
|
36
|
-
this.el.setAttribute(this.arg, value)
|
37
|
-
} else {
|
38
|
-
this.el.removeAttribute(this.arg)
|
39
|
-
}
|
40
|
-
if (this.isParam) {
|
41
|
-
this.vm[this.arg] = utils.checkNumber(value)
|
42
|
-
}
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
/**
|
47
|
-
* Binding textContent
|
48
|
-
*/
|
49
|
-
directives.text = {
|
50
|
-
bind: function () {
|
51
|
-
this.attr = this.el.nodeType === 3
|
52
|
-
? 'nodeValue'
|
53
|
-
: 'textContent'
|
54
|
-
},
|
55
|
-
update: function (value) {
|
56
|
-
this.el[this.attr] = utils.guard(value)
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
|
-
/**
|
61
|
-
* Binding CSS display property
|
62
|
-
*/
|
63
|
-
directives.show = function (value) {
|
64
|
-
var el = this.el,
|
65
|
-
target = value ? '' : 'none',
|
66
|
-
change = function () {
|
67
|
-
el.style.display = target
|
68
|
-
}
|
69
|
-
transition(el, value ? 1 : -1, change, this.compiler)
|
70
|
-
}
|
71
|
-
|
72
|
-
/**
|
73
|
-
* Binding CSS classes
|
74
|
-
*/
|
75
|
-
directives['class'] = function (value) {
|
76
|
-
if (this.arg) {
|
77
|
-
utils[value ? 'addClass' : 'removeClass'](this.el, this.arg)
|
78
|
-
} else {
|
79
|
-
if (this.lastVal) {
|
80
|
-
utils.removeClass(this.el, this.lastVal)
|
81
|
-
}
|
82
|
-
if (value) {
|
83
|
-
utils.addClass(this.el, value)
|
84
|
-
this.lastVal = value
|
85
|
-
}
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
/**
|
90
|
-
* Only removed after the owner VM is ready
|
91
|
-
*/
|
92
|
-
directives.cloak = {
|
93
|
-
isEmpty: true,
|
94
|
-
bind: function () {
|
95
|
-
var el = this.el
|
96
|
-
this.compiler.observer.once('hook:ready', function () {
|
97
|
-
el.removeAttribute(config.prefix + '-cloak')
|
98
|
-
})
|
99
|
-
}
|
100
|
-
}
|
101
|
-
|
102
|
-
/**
|
103
|
-
* Store a reference to self in parent VM's $
|
104
|
-
*/
|
105
|
-
directives.ref = {
|
106
|
-
isLiteral: true,
|
107
|
-
bind: function () {
|
108
|
-
var id = this.expression
|
109
|
-
if (id) {
|
110
|
-
this.vm.$parent.$[id] = this.vm
|
111
|
-
}
|
112
|
-
},
|
113
|
-
unbind: function () {
|
114
|
-
var id = this.expression
|
115
|
-
if (id) {
|
116
|
-
delete this.vm.$parent.$[id]
|
117
|
-
}
|
118
|
-
}
|
119
|
-
}
|
120
|
-
|
121
|
-
directives.on = require('./on')
|
122
|
-
directives.repeat = require('./repeat')
|
123
|
-
directives.model = require('./model')
|
124
|
-
directives['if'] = require('./if')
|
125
|
-
directives['with'] = require('./with')
|
126
|
-
directives.html = require('./html')
|
127
|
-
directives.style = require('./style')
|
128
|
-
directives.partial = require('./partial')
|
129
|
-
directives.view = require('./view')
|
1
|
+
// manipulation directives
|
2
|
+
exports.text = require('./text')
|
3
|
+
exports.html = require('./html')
|
4
|
+
exports.attr = require('./attr')
|
5
|
+
exports.show = require('./show')
|
6
|
+
exports['class'] = require('./class')
|
7
|
+
exports.el = require('./el')
|
8
|
+
exports.ref = require('./ref')
|
9
|
+
exports.cloak = require('./cloak')
|
10
|
+
exports.style = require('./style')
|
11
|
+
exports.partial = require('./partial')
|
12
|
+
exports.transition = require('./transition')
|
13
|
+
|
14
|
+
// event listener directives
|
15
|
+
exports.on = require('./on')
|
16
|
+
exports.model = require('./model')
|
17
|
+
|
18
|
+
// child vm directives
|
19
|
+
exports.component = require('./component')
|
20
|
+
exports.repeat = require('./repeat')
|
21
|
+
exports['if'] = require('./if')
|
22
|
+
exports['with'] = require('./with')
|
@@ -0,0 +1,25 @@
|
|
1
|
+
var _ = require('../../util')
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
|
5
|
+
bind: function () {
|
6
|
+
var self = this
|
7
|
+
var el = this.el
|
8
|
+
this.listener = function () {
|
9
|
+
self.set(el.checked, true)
|
10
|
+
}
|
11
|
+
_.on(el, 'change', this.listener)
|
12
|
+
if (el.checked) {
|
13
|
+
this._initValue = el.checked
|
14
|
+
}
|
15
|
+
},
|
16
|
+
|
17
|
+
update: function (value) {
|
18
|
+
this.el.checked = !!value
|
19
|
+
},
|
20
|
+
|
21
|
+
unbind: function () {
|
22
|
+
_.off(this.el, 'change', this.listener)
|
23
|
+
}
|
24
|
+
|
25
|
+
}
|
@@ -0,0 +1,123 @@
|
|
1
|
+
var _ = require('../../util')
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
|
5
|
+
bind: function () {
|
6
|
+
var self = this
|
7
|
+
var el = this.el
|
8
|
+
|
9
|
+
// check params
|
10
|
+
// - lazy: update model on "change" instead of "input"
|
11
|
+
var lazy = this._checkParam('lazy') != null
|
12
|
+
// - number: cast value into number when updating model.
|
13
|
+
var number = this._checkParam('number') != null
|
14
|
+
|
15
|
+
// handle composition events.
|
16
|
+
// http://blog.evanyou.me/2014/01/03/composition-event/
|
17
|
+
var cpLocked = false
|
18
|
+
this.cpLock = function () {
|
19
|
+
cpLocked = true
|
20
|
+
}
|
21
|
+
this.cpUnlock = function () {
|
22
|
+
cpLocked = false
|
23
|
+
// in IE11 the "compositionend" event fires AFTER
|
24
|
+
// the "input" event, so the input handler is blocked
|
25
|
+
// at the end... have to call it here.
|
26
|
+
set()
|
27
|
+
}
|
28
|
+
_.on(el,'compositionstart', this.cpLock)
|
29
|
+
_.on(el,'compositionend', this.cpUnlock)
|
30
|
+
|
31
|
+
// shared setter
|
32
|
+
function set () {
|
33
|
+
self.set(
|
34
|
+
number ? _.toNumber(el.value) : el.value,
|
35
|
+
true
|
36
|
+
)
|
37
|
+
}
|
38
|
+
|
39
|
+
// if the directive has filters, we need to
|
40
|
+
// record cursor position and restore it after updating
|
41
|
+
// the input with the filtered value.
|
42
|
+
// also force update for type="range" inputs to enable
|
43
|
+
// "lock in range" (see #506)
|
44
|
+
this.listener = this.filters || el.type === 'range'
|
45
|
+
? function textInputListener () {
|
46
|
+
if (cpLocked) return
|
47
|
+
var charsOffset
|
48
|
+
// some HTML5 input types throw error here
|
49
|
+
try {
|
50
|
+
// record how many chars from the end of input
|
51
|
+
// the cursor was at
|
52
|
+
charsOffset = el.value.length - el.selectionStart
|
53
|
+
} catch (e) {}
|
54
|
+
// Fix IE10/11 infinite update cycle
|
55
|
+
// https://github.com/yyx990803/vue/issues/592
|
56
|
+
/* istanbul ignore if */
|
57
|
+
if (charsOffset < 0) {
|
58
|
+
return
|
59
|
+
}
|
60
|
+
set()
|
61
|
+
_.nextTick(function () {
|
62
|
+
// force a value update, because in
|
63
|
+
// certain cases the write filters output the
|
64
|
+
// same result for different input values, and
|
65
|
+
// the Observer set events won't be triggered.
|
66
|
+
var newVal = self._watcher.value
|
67
|
+
self.update(newVal)
|
68
|
+
if (charsOffset != null) {
|
69
|
+
var cursorPos =
|
70
|
+
_.toString(newVal).length - charsOffset
|
71
|
+
el.setSelectionRange(cursorPos, cursorPos)
|
72
|
+
}
|
73
|
+
})
|
74
|
+
}
|
75
|
+
: function textInputListener () {
|
76
|
+
if (cpLocked) return
|
77
|
+
set()
|
78
|
+
}
|
79
|
+
|
80
|
+
this.event = lazy ? 'change' : 'input'
|
81
|
+
_.on(el, this.event, this.listener)
|
82
|
+
|
83
|
+
// IE9 doesn't fire input event on backspace/del/cut
|
84
|
+
if (!lazy && _.isIE9) {
|
85
|
+
this.onCut = function () {
|
86
|
+
_.nextTick(self.listener)
|
87
|
+
}
|
88
|
+
this.onDel = function (e) {
|
89
|
+
if (e.keyCode === 46 || e.keyCode === 8) {
|
90
|
+
self.listener()
|
91
|
+
}
|
92
|
+
}
|
93
|
+
_.on(el, 'cut', this.onCut)
|
94
|
+
_.on(el, 'keyup', this.onDel)
|
95
|
+
}
|
96
|
+
|
97
|
+
// set initial value if present
|
98
|
+
if (
|
99
|
+
el.hasAttribute('value') ||
|
100
|
+
(el.tagName === 'TEXTAREA' && el.value.trim())
|
101
|
+
) {
|
102
|
+
this._initValue = number
|
103
|
+
? _.toNumber(el.value)
|
104
|
+
: el.value
|
105
|
+
}
|
106
|
+
},
|
107
|
+
|
108
|
+
update: function (value) {
|
109
|
+
this.el.value = _.toString(value)
|
110
|
+
},
|
111
|
+
|
112
|
+
unbind: function () {
|
113
|
+
var el = this.el
|
114
|
+
_.off(el, this.event, this.listener)
|
115
|
+
_.off(el,'compositionstart', this.cpLock)
|
116
|
+
_.off(el,'compositionend', this.cpUnlock)
|
117
|
+
if (this.onCut) {
|
118
|
+
_.off(el,'cut', this.onCut)
|
119
|
+
_.off(el,'keyup', this.onDel)
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
var _ = require('../../util')
|
2
|
+
|
3
|
+
var handlers = {
|
4
|
+
_default: require('./default'),
|
5
|
+
radio: require('./radio'),
|
6
|
+
select: require('./select'),
|
7
|
+
checkbox: require('./checkbox')
|
8
|
+
}
|
9
|
+
|
10
|
+
module.exports = {
|
11
|
+
|
12
|
+
priority: 800,
|
13
|
+
twoWay: true,
|
14
|
+
handlers: handlers,
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Possible elements:
|
18
|
+
* <select>
|
19
|
+
* <textarea>
|
20
|
+
* <input type="*">
|
21
|
+
* - text
|
22
|
+
* - checkbox
|
23
|
+
* - radio
|
24
|
+
* - number
|
25
|
+
* - TODO: more types may be supplied as a plugin
|
26
|
+
*/
|
27
|
+
|
28
|
+
bind: function () {
|
29
|
+
// friendly warning...
|
30
|
+
var filters = this.filters
|
31
|
+
if (filters && filters.read && !filters.write) {
|
32
|
+
_.warn(
|
33
|
+
'It seems you are using a read-only filter with ' +
|
34
|
+
'v-model. You might want to use a two-way filter ' +
|
35
|
+
'to ensure correct behavior.'
|
36
|
+
)
|
37
|
+
}
|
38
|
+
var el = this.el
|
39
|
+
var tag = el.tagName
|
40
|
+
var handler
|
41
|
+
if (tag === 'INPUT') {
|
42
|
+
handler = handlers[el.type] || handlers._default
|
43
|
+
} else if (tag === 'SELECT') {
|
44
|
+
handler = handlers.select
|
45
|
+
} else if (tag === 'TEXTAREA') {
|
46
|
+
handler = handlers._default
|
47
|
+
} else {
|
48
|
+
_.warn("v-model doesn't support element type: " + tag)
|
49
|
+
return
|
50
|
+
}
|
51
|
+
handler.bind.call(this)
|
52
|
+
this.update = handler.update
|
53
|
+
this.unbind = handler.unbind
|
54
|
+
}
|
55
|
+
|
56
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
var _ = require('../../util')
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
|
5
|
+
bind: function () {
|
6
|
+
var self = this
|
7
|
+
var el = this.el
|
8
|
+
this.listener = function () {
|
9
|
+
self.set(el.value, true)
|
10
|
+
}
|
11
|
+
_.on(el, 'change', this.listener)
|
12
|
+
if (el.checked) {
|
13
|
+
this._initValue = el.value
|
14
|
+
}
|
15
|
+
},
|
16
|
+
|
17
|
+
update: function (value) {
|
18
|
+
/* jshint eqeqeq: false */
|
19
|
+
this.el.checked = value == this.el.value
|
20
|
+
},
|
21
|
+
|
22
|
+
unbind: function () {
|
23
|
+
_.off(this.el, 'change', this.listener)
|
24
|
+
}
|
25
|
+
|
26
|
+
}
|
@@ -0,0 +1,166 @@
|
|
1
|
+
var _ = require('../../util')
|
2
|
+
var Watcher = require('../../watcher')
|
3
|
+
|
4
|
+
module.exports = {
|
5
|
+
|
6
|
+
bind: function () {
|
7
|
+
var self = this
|
8
|
+
var el = this.el
|
9
|
+
// check options param
|
10
|
+
var optionsParam = this._checkParam('options')
|
11
|
+
if (optionsParam) {
|
12
|
+
initOptions.call(this, optionsParam)
|
13
|
+
}
|
14
|
+
this.multiple = el.hasAttribute('multiple')
|
15
|
+
this.listener = function () {
|
16
|
+
var value = self.multiple
|
17
|
+
? getMultiValue(el)
|
18
|
+
: el.value
|
19
|
+
self.set(value, true)
|
20
|
+
}
|
21
|
+
_.on(el, 'change', this.listener)
|
22
|
+
checkInitialValue.call(this)
|
23
|
+
},
|
24
|
+
|
25
|
+
update: function (value) {
|
26
|
+
/* jshint eqeqeq: false */
|
27
|
+
var el = this.el
|
28
|
+
el.selectedIndex = -1
|
29
|
+
var multi = this.multiple && _.isArray(value)
|
30
|
+
var options = el.options
|
31
|
+
var i = options.length
|
32
|
+
var option
|
33
|
+
while (i--) {
|
34
|
+
option = options[i]
|
35
|
+
option.selected = multi
|
36
|
+
? indexOf(value, option.value) > -1
|
37
|
+
: value == option.value
|
38
|
+
}
|
39
|
+
},
|
40
|
+
|
41
|
+
unbind: function () {
|
42
|
+
_.off(this.el, 'change', this.listener)
|
43
|
+
if (this.optionWatcher) {
|
44
|
+
this.optionWatcher.teardown()
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Initialize the option list from the param.
|
52
|
+
*
|
53
|
+
* @param {String} expression
|
54
|
+
*/
|
55
|
+
|
56
|
+
function initOptions (expression) {
|
57
|
+
var self = this
|
58
|
+
function optionUpdateWatcher (value) {
|
59
|
+
if (_.isArray(value)) {
|
60
|
+
self.el.innerHTML = ''
|
61
|
+
buildOptions(self.el, value)
|
62
|
+
if (self._watcher) {
|
63
|
+
self.update(self._watcher.value)
|
64
|
+
}
|
65
|
+
} else {
|
66
|
+
_.warn('Invalid options value for v-model: ' + value)
|
67
|
+
}
|
68
|
+
}
|
69
|
+
this.optionWatcher = new Watcher(
|
70
|
+
this.vm,
|
71
|
+
expression,
|
72
|
+
optionUpdateWatcher
|
73
|
+
)
|
74
|
+
// update with initial value
|
75
|
+
optionUpdateWatcher(this.optionWatcher.value)
|
76
|
+
}
|
77
|
+
|
78
|
+
/**
|
79
|
+
* Build up option elements. IE9 doesn't create options
|
80
|
+
* when setting innerHTML on <select> elements, so we have
|
81
|
+
* to use DOM API here.
|
82
|
+
*
|
83
|
+
* @param {Element} parent - a <select> or an <optgroup>
|
84
|
+
* @param {Array} options
|
85
|
+
*/
|
86
|
+
|
87
|
+
function buildOptions (parent, options) {
|
88
|
+
var op, el
|
89
|
+
for (var i = 0, l = options.length; i < l; i++) {
|
90
|
+
op = options[i]
|
91
|
+
if (!op.options) {
|
92
|
+
el = document.createElement('option')
|
93
|
+
if (typeof op === 'string') {
|
94
|
+
el.text = el.value = op
|
95
|
+
} else {
|
96
|
+
el.text = op.text
|
97
|
+
el.value = op.value
|
98
|
+
}
|
99
|
+
} else {
|
100
|
+
el = document.createElement('optgroup')
|
101
|
+
el.label = op.label
|
102
|
+
buildOptions(el, op.options)
|
103
|
+
}
|
104
|
+
parent.appendChild(el)
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Check the initial value for selected options.
|
110
|
+
*/
|
111
|
+
|
112
|
+
function checkInitialValue () {
|
113
|
+
var initValue
|
114
|
+
var options = this.el.options
|
115
|
+
for (var i = 0, l = options.length; i < l; i++) {
|
116
|
+
if (options[i].hasAttribute('selected')) {
|
117
|
+
if (this.multiple) {
|
118
|
+
(initValue || (initValue = []))
|
119
|
+
.push(options[i].value)
|
120
|
+
} else {
|
121
|
+
initValue = options[i].value
|
122
|
+
}
|
123
|
+
}
|
124
|
+
}
|
125
|
+
if (initValue) {
|
126
|
+
this._initValue = initValue
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
/**
|
131
|
+
* Helper to extract a value array for select[multiple]
|
132
|
+
*
|
133
|
+
* @param {SelectElement} el
|
134
|
+
* @return {Array}
|
135
|
+
*/
|
136
|
+
|
137
|
+
function getMultiValue (el) {
|
138
|
+
return Array.prototype.filter
|
139
|
+
.call(el.options, filterSelected)
|
140
|
+
.map(getOptionValue)
|
141
|
+
}
|
142
|
+
|
143
|
+
function filterSelected (op) {
|
144
|
+
return op.selected
|
145
|
+
}
|
146
|
+
|
147
|
+
function getOptionValue (op) {
|
148
|
+
return op.value || op.text
|
149
|
+
}
|
150
|
+
|
151
|
+
/**
|
152
|
+
* Native Array.indexOf uses strict equal, but in this
|
153
|
+
* case we need to match string/numbers with soft equal.
|
154
|
+
*
|
155
|
+
* @param {Array} arr
|
156
|
+
* @param {*} val
|
157
|
+
*/
|
158
|
+
|
159
|
+
function indexOf (arr, val) {
|
160
|
+
/* jshint eqeqeq: false */
|
161
|
+
var i = arr.length
|
162
|
+
while (i--) {
|
163
|
+
if (arr[i] == val) return i
|
164
|
+
}
|
165
|
+
return -1
|
166
|
+
}
|