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.

Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +9 -0
  3. data/Gemfile +1 -0
  4. data/Gemfile.lock +4 -1
  5. data/app/assets/javascripts/vue/fluent_log.js +4 -4
  6. data/app/assets/javascripts/vue/in_tail_format.js +43 -49
  7. data/app/assets/javascripts/{alert.js → vue/notification.js} +21 -7
  8. data/app/assets/javascripts/vue/settings.js +121 -0
  9. data/app/assets/javascripts/vue/treeview.js +3 -3
  10. data/app/assets/stylesheets/common.css.scss +7 -1
  11. data/app/controllers/api/settings_controller.rb +55 -0
  12. data/app/controllers/api_controller.rb +6 -2
  13. data/app/controllers/concerns/setting_concern.rb +2 -2
  14. data/app/controllers/fluentd/settings_controller.rb +17 -2
  15. data/app/models/fluentd/setting/config.rb +39 -0
  16. data/app/views/api/settings/_element.json.jbuilder +6 -0
  17. data/app/views/api/settings/index.json.jbuilder +3 -0
  18. data/app/views/api/settings/show.json.jbuilder +1 -0
  19. data/app/views/fluentd/settings/edit.html.haml +3 -0
  20. data/app/views/fluentd/settings/source_and_output.html.haml +19 -2
  21. data/app/views/layouts/application.html.erb +1 -30
  22. data/app/views/shared/vue/_in_tail_format.html.erb +11 -36
  23. data/app/views/shared/vue/_notification.html.erb +31 -0
  24. data/app/views/shared/vue/_setting.html.erb +23 -0
  25. data/app/views/shared/vue/_treeview.html.erb +2 -2
  26. data/bower.json +1 -1
  27. data/config/application.rb +1 -0
  28. data/config/locales/translation_en.yml +11 -7
  29. data/config/locales/translation_ja.yml +4 -0
  30. data/config/routes.rb +2 -0
  31. data/lib/fluentd-ui/version.rb +1 -1
  32. data/spec/features/fluentd/setting/source_and_output_spec.rb +157 -0
  33. data/spec/spec_helper.rb +1 -0
  34. data/spec/support/javascript_macro.rb +21 -0
  35. data/vendor/assets/javascripts/bower/vue/.bower.json +7 -7
  36. data/vendor/assets/javascripts/bower/vue/LICENSE +1 -1
  37. data/vendor/assets/javascripts/bower/vue/dist/vue.js +7822 -4768
  38. data/vendor/assets/javascripts/bower/vue/dist/vue.min.js +7 -7
  39. data/vendor/assets/javascripts/bower/vue/src/api/child.js +53 -0
  40. data/vendor/assets/javascripts/bower/vue/src/api/data.js +161 -0
  41. data/vendor/assets/javascripts/bower/vue/src/api/dom.js +211 -0
  42. data/vendor/assets/javascripts/bower/vue/src/api/events.js +176 -0
  43. data/vendor/assets/javascripts/bower/vue/src/api/global.js +146 -0
  44. data/vendor/assets/javascripts/bower/vue/src/api/lifecycle.js +144 -0
  45. data/vendor/assets/javascripts/bower/vue/src/batcher.js +52 -32
  46. data/vendor/assets/javascripts/bower/vue/src/cache.js +112 -0
  47. data/vendor/assets/javascripts/bower/vue/src/compiler/compile.js +549 -0
  48. data/vendor/assets/javascripts/bower/vue/src/compiler/transclude.js +163 -0
  49. data/vendor/assets/javascripts/bower/vue/src/config.js +74 -14
  50. data/vendor/assets/javascripts/bower/vue/src/directive.js +179 -219
  51. data/vendor/assets/javascripts/bower/vue/src/directives/attr.js +32 -0
  52. data/vendor/assets/javascripts/bower/vue/src/directives/class.js +18 -0
  53. data/vendor/assets/javascripts/bower/vue/src/directives/cloak.js +12 -0
  54. data/vendor/assets/javascripts/bower/vue/src/directives/component.js +214 -0
  55. data/vendor/assets/javascripts/bower/vue/src/directives/el.js +13 -0
  56. data/vendor/assets/javascripts/bower/vue/src/directives/html.js +30 -34
  57. data/vendor/assets/javascripts/bower/vue/src/directives/if.js +77 -46
  58. data/vendor/assets/javascripts/bower/vue/src/directives/index.js +22 -129
  59. data/vendor/assets/javascripts/bower/vue/src/directives/model/checkbox.js +25 -0
  60. data/vendor/assets/javascripts/bower/vue/src/directives/model/default.js +123 -0
  61. data/vendor/assets/javascripts/bower/vue/src/directives/model/index.js +56 -0
  62. data/vendor/assets/javascripts/bower/vue/src/directives/model/radio.js +26 -0
  63. data/vendor/assets/javascripts/bower/vue/src/directives/model/select.js +166 -0
  64. data/vendor/assets/javascripts/bower/vue/src/directives/on.js +51 -50
  65. data/vendor/assets/javascripts/bower/vue/src/directives/partial.js +36 -42
  66. data/vendor/assets/javascripts/bower/vue/src/directives/ref.js +24 -0
  67. data/vendor/assets/javascripts/bower/vue/src/directives/repeat.js +477 -226
  68. data/vendor/assets/javascripts/bower/vue/src/directives/show.js +8 -0
  69. data/vendor/assets/javascripts/bower/vue/src/directives/style.js +49 -37
  70. data/vendor/assets/javascripts/bower/vue/src/directives/text.js +15 -0
  71. data/vendor/assets/javascripts/bower/vue/src/directives/transition.js +12 -0
  72. data/vendor/assets/javascripts/bower/vue/src/directives/with.js +38 -41
  73. data/vendor/assets/javascripts/bower/vue/src/filters/array-filters.js +87 -0
  74. data/vendor/assets/javascripts/bower/vue/src/filters/index.js +135 -0
  75. data/vendor/assets/javascripts/bower/vue/src/instance/compile.js +71 -0
  76. data/vendor/assets/javascripts/bower/vue/src/instance/events.js +122 -0
  77. data/vendor/assets/javascripts/bower/vue/src/instance/init.js +76 -0
  78. data/vendor/assets/javascripts/bower/vue/src/instance/scope.js +217 -0
  79. data/vendor/assets/javascripts/bower/vue/src/observer/array.js +90 -0
  80. data/vendor/assets/javascripts/bower/vue/src/observer/dep.js +50 -0
  81. data/vendor/assets/javascripts/bower/vue/src/observer/index.js +235 -0
  82. data/vendor/assets/javascripts/bower/vue/src/observer/object.js +75 -0
  83. data/vendor/assets/javascripts/bower/vue/src/parsers/directive.js +159 -0
  84. data/vendor/assets/javascripts/bower/vue/src/parsers/expression.js +226 -0
  85. data/vendor/assets/javascripts/bower/vue/src/parsers/path.js +300 -0
  86. data/vendor/assets/javascripts/bower/vue/src/parsers/template.js +246 -0
  87. data/vendor/assets/javascripts/bower/vue/src/parsers/text.js +178 -0
  88. data/vendor/assets/javascripts/bower/vue/src/transition/css.js +189 -0
  89. data/vendor/assets/javascripts/bower/vue/src/transition/index.js +151 -0
  90. data/vendor/assets/javascripts/bower/vue/src/transition/js.js +43 -0
  91. data/vendor/assets/javascripts/bower/vue/src/util/debug.js +50 -0
  92. data/vendor/assets/javascripts/bower/vue/src/util/dom.js +176 -0
  93. data/vendor/assets/javascripts/bower/vue/src/util/env.js +74 -0
  94. data/vendor/assets/javascripts/bower/vue/src/util/filter.js +72 -0
  95. data/vendor/assets/javascripts/bower/vue/src/util/index.js +8 -0
  96. data/vendor/assets/javascripts/bower/vue/src/util/lang.js +175 -0
  97. data/vendor/assets/javascripts/bower/vue/src/util/merge-option.js +258 -0
  98. data/vendor/assets/javascripts/bower/vue/src/vue.js +84 -0
  99. data/vendor/assets/javascripts/bower/vue/src/watcher.js +240 -0
  100. metadata +65 -20
  101. data/app/assets/javascripts/setting_format.js +0 -15
  102. data/vendor/assets/javascripts/bower/vue/src/binding.js +0 -103
  103. data/vendor/assets/javascripts/bower/vue/src/compiler.js +0 -1037
  104. data/vendor/assets/javascripts/bower/vue/src/deps-parser.js +0 -65
  105. data/vendor/assets/javascripts/bower/vue/src/directives/model.js +0 -174
  106. data/vendor/assets/javascripts/bower/vue/src/directives/view.js +0 -56
  107. data/vendor/assets/javascripts/bower/vue/src/emitter.js +0 -97
  108. data/vendor/assets/javascripts/bower/vue/src/exp-parser.js +0 -190
  109. data/vendor/assets/javascripts/bower/vue/src/filters.js +0 -191
  110. data/vendor/assets/javascripts/bower/vue/src/fragment.js +0 -67
  111. data/vendor/assets/javascripts/bower/vue/src/main.js +0 -188
  112. data/vendor/assets/javascripts/bower/vue/src/observer.js +0 -446
  113. data/vendor/assets/javascripts/bower/vue/src/template-parser.js +0 -46
  114. data/vendor/assets/javascripts/bower/vue/src/text-parser.js +0 -96
  115. data/vendor/assets/javascripts/bower/vue/src/transition.js +0 -228
  116. data/vendor/assets/javascripts/bower/vue/src/utils.js +0 -326
  117. data/vendor/assets/javascripts/bower/vue/src/viewmodel.js +0 -190
@@ -0,0 +1,163 @@
1
+ var _ = require('../util')
2
+ var templateParser = require('../parsers/template')
3
+
4
+ /**
5
+ * Process an element or a DocumentFragment based on a
6
+ * instance option object. This allows us to transclude
7
+ * a template node/fragment before the instance is created,
8
+ * so the processed fragment can then be cloned and reused
9
+ * in v-repeat.
10
+ *
11
+ * @param {Element} el
12
+ * @param {Object} options
13
+ * @return {Element|DocumentFragment}
14
+ */
15
+
16
+ module.exports = function transclude (el, options) {
17
+ // for template tags, what we want is its content as
18
+ // a documentFragment (for block instances)
19
+ if (el.tagName === 'TEMPLATE') {
20
+ el = templateParser.parse(el)
21
+ }
22
+ if (options && options.template) {
23
+ el = transcludeTemplate(el, options)
24
+ }
25
+ if (el instanceof DocumentFragment) {
26
+ _.prepend(document.createComment('v-start'), el)
27
+ el.appendChild(document.createComment('v-end'))
28
+ }
29
+ return el
30
+ }
31
+
32
+ /**
33
+ * Process the template option.
34
+ * If the replace option is true this will swap the $el.
35
+ *
36
+ * @param {Element} el
37
+ * @param {Object} options
38
+ * @return {Element|DocumentFragment}
39
+ */
40
+
41
+ function transcludeTemplate (el, options) {
42
+ var template = options.template
43
+ var frag = templateParser.parse(template, true)
44
+ if (!frag) {
45
+ _.warn('Invalid template option: ' + template)
46
+ } else {
47
+ collectRawContent(el)
48
+ if (options.replace) {
49
+ if (frag.childNodes.length > 1) {
50
+ transcludeContent(frag)
51
+ return frag
52
+ } else {
53
+ var replacer = frag.firstChild
54
+ _.copyAttributes(el, replacer)
55
+ transcludeContent(replacer)
56
+ return replacer
57
+ }
58
+ } else {
59
+ el.appendChild(frag)
60
+ transcludeContent(el)
61
+ return el
62
+ }
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Collect raw content inside $el before they are
68
+ * replaced by template content.
69
+ */
70
+
71
+ var rawContent
72
+ function collectRawContent (el) {
73
+ var child
74
+ rawContent = null
75
+ if (el.hasChildNodes()) {
76
+ rawContent = document.createElement('div')
77
+ /* jshint boss:true */
78
+ while (child = el.firstChild) {
79
+ rawContent.appendChild(child)
80
+ }
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Resolve <content> insertion points mimicking the behavior
86
+ * of the Shadow DOM spec:
87
+ *
88
+ * http://w3c.github.io/webcomponents/spec/shadow/#insertion-points
89
+ *
90
+ * @param {Element|DocumentFragment} el
91
+ */
92
+
93
+ function transcludeContent (el) {
94
+ var outlets = getOutlets(el)
95
+ var i = outlets.length
96
+ if (!i) return
97
+ var outlet, select, selected, j, main
98
+ // first pass, collect corresponding content
99
+ // for each outlet.
100
+ while (i--) {
101
+ outlet = outlets[i]
102
+ if (rawContent) {
103
+ select = outlet.getAttribute('select')
104
+ if (select) { // select content
105
+ selected = rawContent.querySelectorAll(select)
106
+ outlet.content = _.toArray(
107
+ selected.length
108
+ ? selected
109
+ : outlet.childNodes
110
+ )
111
+ } else { // default content
112
+ main = outlet
113
+ }
114
+ } else { // fallback content
115
+ outlet.content = _.toArray(outlet.childNodes)
116
+ }
117
+ }
118
+ // second pass, actually insert the contents
119
+ for (i = 0, j = outlets.length; i < j; i++) {
120
+ outlet = outlets[i]
121
+ if (outlet !== main) {
122
+ insertContentAt(outlet, outlet.content)
123
+ }
124
+ }
125
+ // finally insert the main content
126
+ if (main) {
127
+ insertContentAt(main, _.toArray(rawContent.childNodes))
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Get <content> outlets from the element/list
133
+ *
134
+ * @param {Element|Array} el
135
+ * @return {Array}
136
+ */
137
+
138
+ var concat = [].concat
139
+ function getOutlets (el) {
140
+ return _.isArray(el)
141
+ ? concat.apply([], el.map(getOutlets))
142
+ : el.querySelectorAll
143
+ ? _.toArray(el.querySelectorAll('content'))
144
+ : []
145
+ }
146
+
147
+ /**
148
+ * Insert an array of nodes at outlet,
149
+ * then remove the outlet.
150
+ *
151
+ * @param {Element} outlet
152
+ * @param {Array} contents
153
+ */
154
+
155
+ function insertContentAt (outlet, contents) {
156
+ // not using util DOM methods here because
157
+ // parentNode can be cached
158
+ var parent = outlet.parentNode
159
+ for (var i = 0, j = contents.length; i < j; i++) {
160
+ parent.insertBefore(contents[i], outlet)
161
+ }
162
+ parent.removeChild(outlet)
163
+ }
@@ -1,19 +1,79 @@
1
- var TextParser = require('./text-parser')
2
-
3
1
  module.exports = {
4
- prefix : 'v',
5
- debug : false,
6
- silent : false,
7
- enterClass : 'v-enter',
8
- leaveClass : 'v-leave',
9
- interpolate : true
2
+
3
+ /**
4
+ * The prefix to look for when parsing directives.
5
+ *
6
+ * @type {String}
7
+ */
8
+
9
+ prefix: 'v-',
10
+
11
+ /**
12
+ * Whether to print debug messages.
13
+ * Also enables stack trace for warnings.
14
+ *
15
+ * @type {Boolean}
16
+ */
17
+
18
+ debug: false,
19
+
20
+ /**
21
+ * Whether to suppress warnings.
22
+ *
23
+ * @type {Boolean}
24
+ */
25
+
26
+ silent: false,
27
+
28
+ /**
29
+ * Whether allow observer to alter data objects'
30
+ * __proto__.
31
+ *
32
+ * @type {Boolean}
33
+ */
34
+
35
+ proto: true,
36
+
37
+ /**
38
+ * Whether to parse mustache tags in templates.
39
+ *
40
+ * @type {Boolean}
41
+ */
42
+
43
+ interpolate: true,
44
+
45
+ /**
46
+ * Whether to use async rendering.
47
+ */
48
+
49
+ async: true,
50
+
51
+ /**
52
+ * Internal flag to indicate the delimiters have been
53
+ * changed.
54
+ *
55
+ * @type {Boolean}
56
+ */
57
+
58
+ _delimitersChanged: true
59
+
10
60
  }
11
61
 
62
+ /**
63
+ * Interpolation delimiters.
64
+ * We need to mark the changed flag so that the text parser
65
+ * knows it needs to recompile the regex.
66
+ *
67
+ * @type {Array<String>}
68
+ */
69
+
70
+ var delimiters = ['{{', '}}']
12
71
  Object.defineProperty(module.exports, 'delimiters', {
13
- get: function () {
14
- return TextParser.delimiters
15
- },
16
- set: function (delimiters) {
17
- TextParser.setDelimiters(delimiters)
18
- }
72
+ get: function () {
73
+ return delimiters
74
+ },
75
+ set: function (val) {
76
+ delimiters = val
77
+ this._delimitersChanged = true
78
+ }
19
79
  })
@@ -1,258 +1,218 @@
1
- var dirId = 1,
2
- ARG_RE = /^[\w\$-]+$/,
3
- FILTER_TOKEN_RE = /[^\s'"]+|'[^']+'|"[^"]+"/g,
4
- NESTING_RE = /^\$(parent|root)\./,
5
- SINGLE_VAR_RE = /^[\w\.$]+$/,
6
- QUOTE_RE = /"/g,
7
- TextParser = require('./text-parser')
1
+ var _ = require('./util')
2
+ var config = require('./config')
3
+ var Watcher = require('./watcher')
4
+ var textParser = require('./parsers/text')
5
+ var expParser = require('./parsers/expression')
8
6
 
9
7
  /**
10
- * Directive class
11
- * represents a single directive instance in the DOM
8
+ * A directive links a DOM element with a piece of data,
9
+ * which is the result of evaluating an expression.
10
+ * It registers a watcher with the expression and calls
11
+ * the DOM update function when a change is triggered.
12
+ *
13
+ * @param {String} name
14
+ * @param {Node} el
15
+ * @param {Vue} vm
16
+ * @param {Object} descriptor
17
+ * - {String} expression
18
+ * - {String} [arg]
19
+ * - {Array<Object>} [filters]
20
+ * @param {Object} def - directive definition object
21
+ * @param {Function} [linker] - pre-compiled linker function
22
+ * @constructor
12
23
  */
13
- function Directive (name, ast, definition, compiler, el) {
14
24
 
15
- this.id = dirId++
16
- this.name = name
17
- this.compiler = compiler
18
- this.vm = compiler.vm
19
- this.el = el
20
- this.computeFilters = false
21
- this.key = ast.key
22
- this.arg = ast.arg
23
- this.expression = ast.expression
25
+ function Directive (name, el, vm, descriptor, def, linker) {
26
+ // public
27
+ this.name = name
28
+ this.el = el
29
+ this.vm = vm
30
+ // copy descriptor props
31
+ this.raw = descriptor.raw
32
+ this.expression = descriptor.expression
33
+ this.arg = descriptor.arg
34
+ this.filters = _.resolveFilters(vm, descriptor.filters)
35
+ // private
36
+ this._linker = linker
37
+ this._locked = false
38
+ this._bound = false
39
+ // init
40
+ this._bind(def)
41
+ }
24
42
 
25
- var isEmpty = this.expression === ''
43
+ var p = Directive.prototype
26
44
 
27
- // mix in properties from the directive definition
28
- if (typeof definition === 'function') {
29
- this[isEmpty ? 'bind' : 'update'] = definition
30
- } else {
31
- for (var prop in definition) {
32
- this[prop] = definition[prop]
33
- }
34
- }
35
-
36
- // empty expression, we're done.
37
- if (isEmpty || this.isEmpty) {
38
- this.isEmpty = true
39
- return
40
- }
41
-
42
- if (TextParser.Regex.test(this.key)) {
43
- this.key = compiler.eval(this.key)
44
- if (this.isLiteral) {
45
- this.expression = this.key
46
- }
47
- }
45
+ /**
46
+ * Initialize the directive, mixin definition properties,
47
+ * setup the watcher, call definition bind() and update()
48
+ * if present.
49
+ *
50
+ * @param {Object} def
51
+ */
48
52
 
49
- var filters = ast.filters,
50
- filter, fn, i, l, computed
51
- if (filters) {
52
- this.filters = []
53
- for (i = 0, l = filters.length; i < l; i++) {
54
- filter = filters[i]
55
- fn = this.compiler.getOption('filters', filter.name)
56
- if (fn) {
57
- filter.apply = fn
58
- this.filters.push(filter)
59
- if (fn.computed) {
60
- computed = true
61
- }
62
- }
63
- }
53
+ p._bind = function (def) {
54
+ if (this.name !== 'cloak' && this.el.removeAttribute) {
55
+ this.el.removeAttribute(config.prefix + this.name)
56
+ }
57
+ if (typeof def === 'function') {
58
+ this.update = def
59
+ } else {
60
+ _.extend(this, def)
61
+ }
62
+ this._watcherExp = this.expression
63
+ this._checkDynamicLiteral()
64
+ if (this.bind) {
65
+ this.bind()
66
+ }
67
+ if (
68
+ this.update && this._watcherExp &&
69
+ (!this.isLiteral || this._isDynamicLiteral) &&
70
+ !this._checkStatement()
71
+ ) {
72
+ // use raw expression as identifier because filters
73
+ // make them different watchers
74
+ var watcher = this.vm._watchers[this.raw]
75
+ // wrapped updater for context
76
+ var dir = this
77
+ var update = this._update = function (val, oldVal) {
78
+ if (!dir._locked) {
79
+ dir.update(val, oldVal)
80
+ }
64
81
  }
65
-
66
- if (!this.filters || !this.filters.length) {
67
- this.filters = null
82
+ if (!watcher) {
83
+ watcher = this.vm._watchers[this.raw] = new Watcher(
84
+ this.vm,
85
+ this._watcherExp,
86
+ update, // callback
87
+ this.filters,
88
+ this.twoWay, // need setter,
89
+ this.deep
90
+ )
91
+ } else {
92
+ watcher.addCb(update)
68
93
  }
69
-
70
- if (computed) {
71
- this.computedKey = Directive.inlineFilters(this.key, this.filters)
72
- this.filters = null
94
+ this._watcher = watcher
95
+ if (this._initValue != null) {
96
+ watcher.set(this._initValue)
97
+ } else {
98
+ this.update(watcher.value)
73
99
  }
74
-
75
- this.isExp =
76
- computed ||
77
- !SINGLE_VAR_RE.test(this.key) ||
78
- NESTING_RE.test(this.key)
79
-
100
+ }
101
+ this._bound = true
80
102
  }
81
103
 
82
- var DirProto = Directive.prototype
83
-
84
104
  /**
85
- * called when a new value is set
86
- * for computed properties, this will only be called once
87
- * during initialization.
105
+ * check if this is a dynamic literal binding.
106
+ *
107
+ * e.g. v-component="{{currentView}}"
88
108
  */
89
- DirProto.$update = function (value, init) {
90
- if (this.$lock) return
91
- if (init || value !== this.value || (value && typeof value === 'object')) {
92
- this.value = value
93
- if (this.update) {
94
- this.update(
95
- this.filters && !this.computeFilters
96
- ? this.$applyFilters(value)
97
- : value,
98
- init
99
- )
100
- }
109
+
110
+ p._checkDynamicLiteral = function () {
111
+ var expression = this.expression
112
+ if (expression && this.isLiteral) {
113
+ var tokens = textParser.parse(expression)
114
+ if (tokens) {
115
+ var exp = textParser.tokensToExp(tokens)
116
+ this.expression = this.vm.$get(exp)
117
+ this._watcherExp = exp
118
+ this._isDynamicLiteral = true
101
119
  }
120
+ }
102
121
  }
103
122
 
104
123
  /**
105
- * pipe the value through filters
124
+ * Check if the directive is a function caller
125
+ * and if the expression is a callable one. If both true,
126
+ * we wrap up the expression and use it as the event
127
+ * handler.
128
+ *
129
+ * e.g. v-on="click: a++"
130
+ *
131
+ * @return {Boolean}
106
132
  */
107
- DirProto.$applyFilters = function (value) {
108
- var filtered = value, filter
109
- for (var i = 0, l = this.filters.length; i < l; i++) {
110
- filter = this.filters[i]
111
- filtered = filter.apply.apply(this.vm, [filtered].concat(filter.args))
133
+
134
+ p._checkStatement = function () {
135
+ var expression = this.expression
136
+ if (
137
+ expression && this.acceptStatement &&
138
+ !expParser.pathTestRE.test(expression)
139
+ ) {
140
+ var fn = expParser.parse(expression).get
141
+ var vm = this.vm
142
+ var handler = function () {
143
+ fn.call(vm, vm)
144
+ }
145
+ if (this.filters) {
146
+ handler = _.applyFilters(
147
+ handler,
148
+ this.filters.read,
149
+ vm
150
+ )
112
151
  }
113
- return filtered
152
+ this.update(handler)
153
+ return true
154
+ }
114
155
  }
115
156
 
116
157
  /**
117
- * Unbind diretive
158
+ * Check for an attribute directive param, e.g. lazy
159
+ *
160
+ * @param {String} name
161
+ * @return {String}
118
162
  */
119
- DirProto.$unbind = function () {
120
- // this can be called before the el is even assigned...
121
- if (!this.el || !this.vm) return
122
- if (this.unbind) this.unbind()
123
- this.vm = this.el = this.binding = this.compiler = null
124
- }
125
163
 
126
- // Exposed static methods -----------------------------------------------------
164
+ p._checkParam = function (name) {
165
+ var param = this.el.getAttribute(name)
166
+ if (param !== null) {
167
+ this.el.removeAttribute(name)
168
+ }
169
+ return param
170
+ }
127
171
 
128
172
  /**
129
- * Parse a directive string into an Array of
130
- * AST-like objects representing directives
173
+ * Teardown the watcher and call unbind.
131
174
  */
132
- Directive.parse = function (str) {
133
-
134
- var inSingle = false,
135
- inDouble = false,
136
- curly = 0,
137
- square = 0,
138
- paren = 0,
139
- begin = 0,
140
- argIndex = 0,
141
- dirs = [],
142
- dir = {},
143
- lastFilterIndex = 0,
144
- arg
145
-
146
- for (var c, i = 0, l = str.length; i < l; i++) {
147
- c = str.charAt(i)
148
- if (inSingle) {
149
- // check single quote
150
- if (c === "'") inSingle = !inSingle
151
- } else if (inDouble) {
152
- // check double quote
153
- if (c === '"') inDouble = !inDouble
154
- } else if (c === ',' && !paren && !curly && !square) {
155
- // reached the end of a directive
156
- pushDir()
157
- // reset & skip the comma
158
- dir = {}
159
- begin = argIndex = lastFilterIndex = i + 1
160
- } else if (c === ':' && !dir.key && !dir.arg) {
161
- // argument
162
- arg = str.slice(begin, i).trim()
163
- if (ARG_RE.test(arg)) {
164
- argIndex = i + 1
165
- dir.arg = arg
166
- }
167
- } else if (c === '|' && str.charAt(i + 1) !== '|' && str.charAt(i - 1) !== '|') {
168
- if (dir.key === undefined) {
169
- // first filter, end of key
170
- lastFilterIndex = i + 1
171
- dir.key = str.slice(argIndex, i).trim()
172
- } else {
173
- // already has filter
174
- pushFilter()
175
- }
176
- } else if (c === '"') {
177
- inDouble = true
178
- } else if (c === "'") {
179
- inSingle = true
180
- } else if (c === '(') {
181
- paren++
182
- } else if (c === ')') {
183
- paren--
184
- } else if (c === '[') {
185
- square++
186
- } else if (c === ']') {
187
- square--
188
- } else if (c === '{') {
189
- curly++
190
- } else if (c === '}') {
191
- curly--
192
- }
193
- }
194
- if (i === 0 || begin !== i) {
195
- pushDir()
196
- }
197
175
 
198
- function pushDir () {
199
- dir.expression = str.slice(begin, i).trim()
200
- if (dir.key === undefined) {
201
- dir.key = str.slice(argIndex, i).trim()
202
- } else if (lastFilterIndex !== begin) {
203
- pushFilter()
204
- }
205
- if (i === 0 || dir.key) {
206
- dirs.push(dir)
207
- }
176
+ p._teardown = function () {
177
+ if (this._bound) {
178
+ if (this.unbind) {
179
+ this.unbind()
208
180
  }
209
-
210
- function pushFilter () {
211
- var exp = str.slice(lastFilterIndex, i).trim(),
212
- filter
213
- if (exp) {
214
- filter = {}
215
- var tokens = exp.match(FILTER_TOKEN_RE)
216
- filter.name = tokens[0]
217
- filter.args = tokens.length > 1 ? tokens.slice(1) : null
218
- }
219
- if (filter) {
220
- (dir.filters = dir.filters || []).push(filter)
221
- }
222
- lastFilterIndex = i + 1
181
+ var watcher = this._watcher
182
+ if (watcher && watcher.active) {
183
+ watcher.removeCb(this._update)
184
+ if (!watcher.active) {
185
+ this.vm._watchers[this.raw] = null
186
+ }
223
187
  }
224
-
225
- return dirs
188
+ this._bound = false
189
+ this.vm = this.el = this._watcher = null
190
+ }
226
191
  }
227
192
 
228
193
  /**
229
- * Inline computed filters so they become part
230
- * of the expression
194
+ * Set the corresponding value with the setter.
195
+ * This should only be used in two-way directives
196
+ * e.g. v-model.
197
+ *
198
+ * @param {*} value
199
+ * @param {Boolean} lock - prevent wrtie triggering update.
200
+ * @public
231
201
  */
232
- Directive.inlineFilters = function (key, filters) {
233
- var args, filter
234
- for (var i = 0, l = filters.length; i < l; i++) {
235
- filter = filters[i]
236
- args = filter.args
237
- ? ',"' + filter.args.map(escapeQuote).join('","') + '"'
238
- : ''
239
- key = 'this.$compiler.getOption("filters", "' +
240
- filter.name +
241
- '").call(this,' +
242
- key + args +
243
- ')'
244
- }
245
- return key
246
- }
247
202
 
248
- /**
249
- * Convert double quotes to single quotes
250
- * so they don't mess up the generated function body
251
- */
252
- function escapeQuote (v) {
253
- return v.indexOf('"') > -1
254
- ? v.replace(QUOTE_RE, '\'')
255
- : v
203
+ p.set = function (value, lock) {
204
+ if (this.twoWay) {
205
+ if (lock) {
206
+ this._locked = true
207
+ }
208
+ this._watcher.set(value)
209
+ if (lock) {
210
+ var self = this
211
+ _.nextTick(function () {
212
+ self._locked = false
213
+ })
214
+ }
215
+ }
256
216
  }
257
217
 
258
218
  module.exports = Directive