Commit 196c517b authored by Arthur Verschaeve's avatar Arthur Verschaeve

Merge pull request #1372 from tastejs/vue-classes

update `vue` example to use classes
parents cfb53cf5 7b7de89f
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
<style> [v-cloak] { display: none; } </style> <style> [v-cloak] { display: none; } </style>
</head> </head>
<body> <body>
<section id="todoapp"> <section class="todoapp">
<header id="header"> <header class="header">
<h1>todos</h1> <h1>todos</h1>
<input id="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" v-on="keyup:addTodo | key enter"> <input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" v-on="keyup:addTodo | key enter">
</header> </header>
<section id="main" v-show="todos.length" v-cloak> <section class="main" v-show="todos.length" v-cloak>
<input id="toggle-all" type="checkbox" v-model="allDone"> <input class="toggle-all" type="checkbox" v-model="allDone">
<ul id="todo-list"> <ul class="todo-list">
<li class="todo" v-repeat="todos | filterTodos" v-class="completed: completed, editing: this == editedTodo"> <li class="todo" v-repeat="todos | filterTodos" v-class="completed: completed, editing: this == editedTodo">
<div class="view"> <div class="view">
<input class="toggle" type="checkbox" v-model="completed"> <input class="toggle" type="checkbox" v-model="completed">
...@@ -26,21 +26,21 @@ ...@@ -26,21 +26,21 @@
</li> </li>
</ul> </ul>
</section> </section>
<footer id="footer" v-show="todos.length" v-cloak> <footer class="footer" v-show="todos.length" v-cloak>
<span id="todo-count"> <span class="todo-count">
<strong v-text="remaining"></strong> {{remaining | pluralize item}} left <strong v-text="remaining"></strong> {{remaining | pluralize item}} left
</span> </span>
<ul id="filters"> <ul class="filters">
<li><a href="#/all" v-class="selected: activeFilter == 'all'">All</a></li> <li><a href="#/all" v-class="selected: activeFilter == 'all'">All</a></li>
<li><a href="#/active" v-class="selected: activeFilter == 'active'">Active</a></li> <li><a href="#/active" v-class="selected: activeFilter == 'active'">Active</a></li>
<li><a href="#/completed" v-class="selected: activeFilter == 'completed'">Completed</a></li> <li><a href="#/completed" v-class="selected: activeFilter == 'completed'">Completed</a></li>
</ul> </ul>
<button id="clear-completed" v-on="click:removeCompleted" v-show="todos.length > remaining"> <button class="clear-completed" v-on="click:removeCompleted" v-show="todos.length > remaining">
Clear completed Clear completed
</button> </button>
</footer> </footer>
</section> </section>
<footer id="info"> <footer class="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p>Written by <a href="http://evanyou.me">Evan You</a></p> <p>Written by <a href="http://evanyou.me">Evan You</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
exports.app = new Vue({ exports.app = new Vue({
// the root element that will be compiled // the root element that will be compiled
el: '#todoapp', el: '.todoapp',
// app state data // app state data
data: { data: {
......
...@@ -44,7 +44,7 @@ input[type="checkbox"] { ...@@ -44,7 +44,7 @@ input[type="checkbox"] {
display: none; display: none;
} }
#todoapp { .todoapp {
background: #fff; background: #fff;
margin: 130px 0 40px 0; margin: 130px 0 40px 0;
position: relative; position: relative;
...@@ -52,25 +52,25 @@ input[type="checkbox"] { ...@@ -52,25 +52,25 @@ input[type="checkbox"] {
0 25px 50px 0 rgba(0, 0, 0, 0.1); 0 25px 50px 0 rgba(0, 0, 0, 0.1);
} }
#todoapp input::-webkit-input-placeholder { .todoapp input::-webkit-input-placeholder {
font-style: italic; font-style: italic;
font-weight: 300; font-weight: 300;
color: #e6e6e6; color: #e6e6e6;
} }
#todoapp input::-moz-placeholder { .todoapp input::-moz-placeholder {
font-style: italic; font-style: italic;
font-weight: 300; font-weight: 300;
color: #e6e6e6; color: #e6e6e6;
} }
#todoapp input::input-placeholder { .todoapp input::input-placeholder {
font-style: italic; font-style: italic;
font-weight: 300; font-weight: 300;
color: #e6e6e6; color: #e6e6e6;
} }
#todoapp h1 { .todoapp h1 {
position: absolute; position: absolute;
top: -155px; top: -155px;
width: 100%; width: 100%;
...@@ -83,7 +83,7 @@ input[type="checkbox"] { ...@@ -83,7 +83,7 @@ input[type="checkbox"] {
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
} }
#new-todo, .new-todo,
.edit { .edit {
position: relative; position: relative;
margin: 0; margin: 0;
...@@ -104,14 +104,14 @@ input[type="checkbox"] { ...@@ -104,14 +104,14 @@ input[type="checkbox"] {
font-smoothing: antialiased; font-smoothing: antialiased;
} }
#new-todo { .new-todo {
padding: 16px 16px 16px 60px; padding: 16px 16px 16px 60px;
border: none; border: none;
background: rgba(0, 0, 0, 0.003); background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
} }
#main { .main {
position: relative; position: relative;
z-index: 2; z-index: 2;
border-top: 1px solid #e6e6e6; border-top: 1px solid #e6e6e6;
...@@ -121,7 +121,7 @@ label[for='toggle-all'] { ...@@ -121,7 +121,7 @@ label[for='toggle-all'] {
display: none; display: none;
} }
#toggle-all { .toggle-all {
position: absolute; position: absolute;
top: -55px; top: -55px;
left: -12px; left: -12px;
...@@ -131,50 +131,50 @@ label[for='toggle-all'] { ...@@ -131,50 +131,50 @@ label[for='toggle-all'] {
border: none; /* Mobile Safari */ border: none; /* Mobile Safari */
} }
#toggle-all:before { .toggle-all:before {
content: '❯'; content: '❯';
font-size: 22px; font-size: 22px;
color: #e6e6e6; color: #e6e6e6;
padding: 10px 27px 10px 27px; padding: 10px 27px 10px 27px;
} }
#toggle-all:checked:before { .toggle-all:checked:before {
color: #737373; color: #737373;
} }
#todo-list { .todo-list {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
} }
#todo-list li { .todo-list li {
position: relative; position: relative;
font-size: 24px; font-size: 24px;
border-bottom: 1px solid #ededed; border-bottom: 1px solid #ededed;
} }
#todo-list li:last-child { .todo-list li:last-child {
border-bottom: none; border-bottom: none;
} }
#todo-list li.editing { .todo-list li.editing {
border-bottom: none; border-bottom: none;
padding: 0; padding: 0;
} }
#todo-list li.editing .edit { .todo-list li.editing .edit {
display: block; display: block;
width: 506px; width: 506px;
padding: 13px 17px 12px 17px; padding: 13px 17px 12px 17px;
margin: 0 0 0 43px; margin: 0 0 0 43px;
} }
#todo-list li.editing .view { .todo-list li.editing .view {
display: none; display: none;
} }
#todo-list li .toggle { .todo-list li .toggle {
text-align: center; text-align: center;
width: 40px; width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */ /* auto, since non-WebKit browsers doesn't support input styling */
...@@ -188,15 +188,15 @@ label[for='toggle-all'] { ...@@ -188,15 +188,15 @@ label[for='toggle-all'] {
appearance: none; appearance: none;
} }
#todo-list li .toggle:after { .todo-list li .toggle:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>'); content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
} }
#todo-list li .toggle:checked:after { .todo-list li .toggle:checked:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>'); content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
} }
#todo-list li label { .todo-list li label {
white-space: pre; white-space: pre;
word-break: break-word; word-break: break-word;
padding: 15px 60px 15px 15px; padding: 15px 60px 15px 15px;
...@@ -206,12 +206,12 @@ label[for='toggle-all'] { ...@@ -206,12 +206,12 @@ label[for='toggle-all'] {
transition: color 0.4s; transition: color 0.4s;
} }
#todo-list li.completed label { .todo-list li.completed label {
color: #d9d9d9; color: #d9d9d9;
text-decoration: line-through; text-decoration: line-through;
} }
#todo-list li .destroy { .todo-list li .destroy {
display: none; display: none;
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -226,27 +226,27 @@ label[for='toggle-all'] { ...@@ -226,27 +226,27 @@ label[for='toggle-all'] {
transition: color 0.2s ease-out; transition: color 0.2s ease-out;
} }
#todo-list li .destroy:hover { .todo-list li .destroy:hover {
color: #af5b5e; color: #af5b5e;
} }
#todo-list li .destroy:after { .todo-list li .destroy:after {
content: '×'; content: '×';
} }
#todo-list li:hover .destroy { .todo-list li:hover .destroy {
display: block; display: block;
} }
#todo-list li .edit { .todo-list li .edit {
display: none; display: none;
} }
#todo-list li.editing:last-child { .todo-list li.editing:last-child {
margin-bottom: -1px; margin-bottom: -1px;
} }
#footer { .footer {
color: #777; color: #777;
padding: 10px 15px; padding: 10px 15px;
height: 20px; height: 20px;
...@@ -254,7 +254,7 @@ label[for='toggle-all'] { ...@@ -254,7 +254,7 @@ label[for='toggle-all'] {
border-top: 1px solid #e6e6e6; border-top: 1px solid #e6e6e6;
} }
#footer:before { .footer:before {
content: ''; content: '';
position: absolute; position: absolute;
right: 0; right: 0;
...@@ -269,16 +269,16 @@ label[for='toggle-all'] { ...@@ -269,16 +269,16 @@ label[for='toggle-all'] {
0 17px 2px -6px rgba(0, 0, 0, 0.2); 0 17px 2px -6px rgba(0, 0, 0, 0.2);
} }
#todo-count { .todo-count {
float: left; float: left;
text-align: left; text-align: left;
} }
#todo-count strong { .todo-count strong {
font-weight: 300; font-weight: 300;
} }
#filters { .filters {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
...@@ -287,11 +287,11 @@ label[for='toggle-all'] { ...@@ -287,11 +287,11 @@ label[for='toggle-all'] {
left: 0; left: 0;
} }
#filters li { .filters li {
display: inline; display: inline;
} }
#filters li a { .filters li a {
color: inherit; color: inherit;
margin: 3px; margin: 3px;
padding: 3px 7px; padding: 3px 7px;
...@@ -300,17 +300,17 @@ label[for='toggle-all'] { ...@@ -300,17 +300,17 @@ label[for='toggle-all'] {
border-radius: 3px; border-radius: 3px;
} }
#filters li a.selected, .filters li a.selected,
#filters li a:hover { .filters li a:hover {
border-color: rgba(175, 47, 47, 0.1); border-color: rgba(175, 47, 47, 0.1);
} }
#filters li a.selected { .filters li a.selected {
border-color: rgba(175, 47, 47, 0.2); border-color: rgba(175, 47, 47, 0.2);
} }
#clear-completed, .clear-completed,
html #clear-completed:active { html .clear-completed:active {
float: right; float: right;
position: relative; position: relative;
line-height: 20px; line-height: 20px;
...@@ -319,11 +319,11 @@ html #clear-completed:active { ...@@ -319,11 +319,11 @@ html #clear-completed:active {
position: relative; position: relative;
} }
#clear-completed:hover { .clear-completed:hover {
text-decoration: underline; text-decoration: underline;
} }
#info { .info {
margin: 65px auto 0; margin: 65px auto 0;
color: #bfbfbf; color: #bfbfbf;
font-size: 10px; font-size: 10px;
...@@ -331,17 +331,17 @@ html #clear-completed:active { ...@@ -331,17 +331,17 @@ html #clear-completed:active {
text-align: center; text-align: center;
} }
#info p { .info p {
line-height: 1; line-height: 1;
} }
#info a { .info a {
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
font-weight: 400; font-weight: 400;
} }
#info a:hover { .info a:hover {
text-decoration: underline; text-decoration: underline;
} }
...@@ -350,16 +350,16 @@ html #clear-completed:active { ...@@ -350,16 +350,16 @@ html #clear-completed:active {
Can't use it globally since it destroys checkboxes in Firefox Can't use it globally since it destroys checkboxes in Firefox
*/ */
@media screen and (-webkit-min-device-pixel-ratio:0) { @media screen and (-webkit-min-device-pixel-ratio:0) {
#toggle-all, .toggle-all,
#todo-list li .toggle { .todo-list li .toggle {
background: none; background: none;
} }
#todo-list li .toggle { .todo-list li .toggle {
height: 40px; height: 40px;
} }
#toggle-all { .toggle-all {
-webkit-transform: rotate(90deg); -webkit-transform: rotate(90deg);
transform: rotate(90deg); transform: rotate(90deg);
-webkit-appearance: none; -webkit-appearance: none;
...@@ -368,11 +368,11 @@ html #clear-completed:active { ...@@ -368,11 +368,11 @@ html #clear-completed:active {
} }
@media (max-width: 430px) { @media (max-width: 430px) {
#footer { .footer {
height: 50px; height: 50px;
} }
#filters { .filters {
bottom: 10px; bottom: 10px;
} }
} }
/** /**
* Vue.js v0.11.8 * Vue.js v0.11.10
* (c) 2015 Evan You * (c) 2015 Evan You
* Released under the MIT License. * Released under the MIT License.
*/ */
...@@ -362,7 +362,16 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -362,7 +362,16 @@ return /******/ (function(modules) { // webpackBootstrap
// transcluded components that belong to the parent. // transcluded components that belong to the parent.
// need to keep track of them so that we can call // need to keep track of them so that we can call
// attached/detached hooks on them. // attached/detached hooks on them.
this._transCpnts = null this._transCpnts = []
this._host = options._host
// push self into parent / transclusion host
if (this.$parent) {
this.$parent._children.push(this)
}
if (this._host) {
this._host._transCpnts.push(this)
}
// props used in v-repeat diffing // props used in v-repeat diffing
this._new = true this._new = true
...@@ -479,7 +488,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -479,7 +488,7 @@ return /******/ (function(modules) { // webpackBootstrap
function onAttached () { function onAttached () {
this._isAttached = true this._isAttached = true
this._children.forEach(callAttach) this._children.forEach(callAttach)
if (this._transCpnts) { if (this._transCpnts.length) {
this._transCpnts.forEach(callAttach) this._transCpnts.forEach(callAttach)
} }
} }
...@@ -503,7 +512,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -503,7 +512,7 @@ return /******/ (function(modules) { // webpackBootstrap
function onDetached () { function onDetached () {
this._isAttached = false this._isAttached = false
this._children.forEach(callDetach) this._children.forEach(callDetach)
if (this._transCpnts) { if (this._transCpnts.length) {
this._transCpnts.forEach(callDetach) this._transCpnts.forEach(callDetach)
} }
} }
...@@ -662,7 +671,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -662,7 +671,7 @@ return /******/ (function(modules) { // webpackBootstrap
i = children.length i = children.length
while (i--) { while (i--) {
var child = children[i] var child = children[i]
if (!child._repeat && child.$options.inherit) { if (child.$options.inherit) {
child._digest() child._digest()
} }
} }
...@@ -779,55 +788,22 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -779,55 +788,22 @@ return /******/ (function(modules) { // webpackBootstrap
exports._compile = function (el) { exports._compile = function (el) {
var options = this.$options var options = this.$options
var parent = options._parent
if (options._linkFn) { if (options._linkFn) {
// pre-transcluded with linker, just use it
this._initElement(el) this._initElement(el)
options._linkFn(this, el) options._linkFn(this, el)
} else { } else {
var raw = el // transclude and init element
if (options._asComponent) { // transclude can potentially replace original
// separate container element and content // so we need to keep reference
var content = options._content = _.extractContent(raw) var original = el
// create two separate linekrs for container and content el = transclude(el, options)
var parentOptions = parent.$options this._initElement(el)
// compile and link the rest
// hack: we need to skip the paramAttributes for this compile(el, options)(this, el)
// child instance when compiling its parent container // finally replace original
// linker. there could be a better way to do this.
parentOptions._skipAttrs = options.paramAttributes
var containerLinkFn =
compile(raw, parentOptions, true, true)
parentOptions._skipAttrs = null
if (content) {
var ol = parent._children.length
var contentLinkFn =
compile(content, parentOptions, true)
// call content linker now, before transclusion
this._contentUnlinkFn = contentLinkFn(parent, content)
// mark all compiled nodes as transcluded, so that
// directives that do partial compilation, e.g. v-if
// and v-partial can detect them and persist them
// through re-compilations.
for (var i = 0; i < content.childNodes.length; i++) {
content.childNodes[i]._isContent = true
}
this._transCpnts = parent._children.slice(ol)
}
// tranclude, this possibly replaces original
el = transclude(el, options)
this._initElement(el)
// now call the container linker on the resolved el
this._containerUnlinkFn = containerLinkFn(parent, el)
} else {
// simply transclude
el = transclude(el, options)
this._initElement(el)
}
var linkFn = compile(el, options)
linkFn(this, el)
if (options.replace) { if (options.replace) {
_.replace(raw, el) _.replace(original, el)
} }
} }
return el return el
...@@ -843,8 +819,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -843,8 +819,7 @@ return /******/ (function(modules) { // webpackBootstrap
exports._initElement = function (el) { exports._initElement = function (el) {
if (el instanceof DocumentFragment) { if (el instanceof DocumentFragment) {
this._isBlock = true this._isBlock = true
this._blockStart = el.firstChild this.$el = this._blockStart = el.firstChild
this.$el = el.childNodes[1]
this._blockEnd = el.lastChild this._blockEnd = el.lastChild
this._blockFragment = el this._blockFragment = el
} else { } else {
...@@ -861,11 +836,12 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -861,11 +836,12 @@ return /******/ (function(modules) { // webpackBootstrap
* @param {Node} node - target node * @param {Node} node - target node
* @param {Object} desc - parsed directive descriptor * @param {Object} desc - parsed directive descriptor
* @param {Object} def - directive definition object * @param {Object} def - directive definition object
* @param {Vue|undefined} host - transclusion host component
*/ */
exports._bindDir = function (name, node, desc, def) { exports._bindDir = function (name, node, desc, def, host) {
this._directives.push( this._directives.push(
new Directive(name, node, this, desc, def) new Directive(name, node, this, desc, def, host)
) )
} }
...@@ -892,18 +868,17 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -892,18 +868,17 @@ return /******/ (function(modules) { // webpackBootstrap
i = parent._children.indexOf(this) i = parent._children.indexOf(this)
parent._children.splice(i, 1) parent._children.splice(i, 1)
} }
// same for transclusion host.
var host = this._host
if (host && !host._isBeingDestroyed) {
i = host._transCpnts.indexOf(this)
host._transCpnts.splice(i, 1)
}
// destroy all children. // destroy all children.
i = this._children.length i = this._children.length
while (i--) { while (i--) {
this._children[i].$destroy() this._children[i].$destroy()
} }
// teardown parent linkers
if (this._containerUnlinkFn) {
this._containerUnlinkFn()
}
if (this._contentUnlinkFn) {
this._contentUnlinkFn()
}
// teardown all directives. this also tearsdown all // teardown all directives. this also tearsdown all
// directive-owned watchers. intentionally check for // directive-owned watchers. intentionally check for
// directives array length on every loop since directives // directives array length on every loop since directives
...@@ -1574,7 +1549,6 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -1574,7 +1549,6 @@ return /******/ (function(modules) { // webpackBootstrap
opts._parent = parent opts._parent = parent
opts._root = parent.$root opts._root = parent.$root
var child = new ChildVue(opts) var child = new ChildVue(opts)
this._children.push(child)
return child return child
} }
...@@ -2204,40 +2178,36 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2204,40 +2178,36 @@ return /******/ (function(modules) { // webpackBootstrap
var dirParser = __webpack_require__(21) var dirParser = __webpack_require__(21)
var templateParser = __webpack_require__(20) var templateParser = __webpack_require__(20)
module.exports = compile
/** /**
* Compile a template and return a reusable composite link * Compile a template and return a reusable composite link
* function, which recursively contains more link functions * function, which recursively contains more link functions
* inside. This top level compile function should only be * inside. This top level compile function should only be
* called on instance root nodes. * called on instance root nodes.
* *
* When the `asParent` flag is true, this means we are doing
* a partial compile for a component's parent scope markup
* (See #502). This could **only** be triggered during
* compilation of `v-component`, and we need to skip v-with,
* v-ref & v-component in this situation.
*
* @param {Element|DocumentFragment} el * @param {Element|DocumentFragment} el
* @param {Object} options * @param {Object} options
* @param {Boolean} partial * @param {Boolean} partial
* @param {Boolean} asParent - compiling a component * @param {Boolean} transcluded
* container as its parent.
* @return {Function} * @return {Function}
*/ */
module.exports = function compile (el, options, partial, asParent) { function compile (el, options, partial, transcluded) {
var isBlock = el.nodeType === 11 var isBlock = el.nodeType === 11
var params = !partial && options.paramAttributes // link function for param attributes.
// if el is a fragment, this is a block instance var params = options.paramAttributes
// and paramAttributes will be stored on the first var paramsLinkFn = params && !partial && !transcluded && !isBlock
// element in the template. (excluding the _blockStart ? compileParamAttributes(el, params, options)
// comment node)
var paramsEl = isBlock ? el.childNodes[1] : el
var paramsLinkFn = params
? compileParamAttributes(paramsEl, params, options)
: null : null
// link function for the node itself.
// if this is a block instance, we return a link function
// for the attributes found on the container, if any.
// options._containerAttrs are collected during transclusion.
var nodeLinkFn = isBlock var nodeLinkFn = isBlock
? null ? compileBlockContainer(options._containerAttrs, params, options)
: compileNode(el, options, asParent) : compileNode(el, options)
// link function for the childNodes
var childLinkFn = var childLinkFn =
!(nodeLinkFn && nodeLinkFn.terminal) && !(nodeLinkFn && nodeLinkFn.terminal) &&
el.tagName !== 'SCRIPT' && el.tagName !== 'SCRIPT' &&
...@@ -2246,8 +2216,8 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2246,8 +2216,8 @@ return /******/ (function(modules) { // webpackBootstrap
: null : null
/** /**
* A linker function to be called on a already compiled * A composite linker function to be called on a already
* piece of DOM, which instantiates all directive * compiled piece of DOM, which instantiates all directive
* instances. * instances.
* *
* @param {Vue} vm * @param {Vue} vm
...@@ -2255,16 +2225,23 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2255,16 +2225,23 @@ return /******/ (function(modules) { // webpackBootstrap
* @return {Function|undefined} * @return {Function|undefined}
*/ */
return function link (vm, el) { function compositeLinkFn (vm, el) {
var originalDirCount = vm._directives.length var originalDirCount = vm._directives.length
var parentOriginalDirCount =
vm.$parent && vm.$parent._directives.length
if (paramsLinkFn) { if (paramsLinkFn) {
var paramsEl = isBlock ? el.childNodes[1] : el paramsLinkFn(vm, el)
paramsLinkFn(vm, paramsEl)
} }
// cache childNodes before linking parent, fix #657 // cache childNodes before linking parent, fix #657
var childNodes = _.toArray(el.childNodes) var childNodes = _.toArray(el.childNodes)
if (nodeLinkFn) nodeLinkFn(vm, el) // if this is a transcluded compile, linkers need to be
if (childLinkFn) childLinkFn(vm, childNodes) // called in source scope, and the host needs to be
// passed down.
var source = transcluded ? vm.$parent : vm
var host = transcluded ? vm : undefined
// link
if (nodeLinkFn) nodeLinkFn(source, el, host)
if (childLinkFn) childLinkFn(source, childNodes, host)
/** /**
* If this is a partial compile, the linker function * If this is a partial compile, the linker function
...@@ -2273,9 +2250,12 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2273,9 +2250,12 @@ return /******/ (function(modules) { // webpackBootstrap
* linking. * linking.
*/ */
if (partial) { if (partial && !transcluded) {
var dirs = vm._directives.slice(originalDirCount) var selfDirs = vm._directives.slice(originalDirCount)
return function unlink () { var parentDirs = vm.$parent &&
vm.$parent._directives.slice(parentOriginalDirCount)
var teardownDirs = function (vm, dirs) {
var i = dirs.length var i = dirs.length
while (i--) { while (i--) {
dirs[i]._teardown() dirs[i]._teardown()
...@@ -2283,8 +2263,57 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2283,8 +2263,57 @@ return /******/ (function(modules) { // webpackBootstrap
i = vm._directives.indexOf(dirs[0]) i = vm._directives.indexOf(dirs[0])
vm._directives.splice(i, dirs.length) vm._directives.splice(i, dirs.length)
} }
return function unlink () {
teardownDirs(vm, selfDirs)
if (parentDirs) {
teardownDirs(vm.$parent, parentDirs)
}
}
}
}
// transcluded linkFns are terminal, because it takes
// over the entire sub-tree.
if (transcluded) {
compositeLinkFn.terminal = true
}
return compositeLinkFn
}
/**
* Compile the attributes found on a "block container" -
* i.e. the container node in the parent tempate of a block
* instance. We are only concerned with v-with and
* paramAttributes here.
*
* @param {Object} attrs - a map of attr name/value pairs
* @param {Array} params - param attributes list
* @param {Object} options
* @return {Function}
*/
function compileBlockContainer (attrs, params, options) {
if (!attrs) return null
var paramsLinkFn = params
? compileParamAttributes(attrs, params, options)
: null
var withVal = attrs[config.prefix + 'with']
var withLinkFn = null
if (withVal) {
var descriptor = dirParser.parse(withVal)[0]
var def = options.directives['with']
withLinkFn = function (vm, el) {
vm._bindDir('with', el, descriptor, def)
} }
} }
return function blockContainerLinkFn (vm) {
// explicitly passing null to the linkers
// since v-with doesn't need a real element
if (paramsLinkFn) paramsLinkFn(vm, null)
if (withLinkFn) withLinkFn(vm, null)
}
} }
/** /**
...@@ -2293,16 +2322,17 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2293,16 +2322,17 @@ return /******/ (function(modules) { // webpackBootstrap
* *
* @param {Node} node * @param {Node} node
* @param {Object} options * @param {Object} options
* @param {Boolean} asParent * @return {Function|null}
* @return {Function|undefined}
*/ */
function compileNode (node, options, asParent) { function compileNode (node, options) {
var type = node.nodeType var type = node.nodeType
if (type === 1 && node.tagName !== 'SCRIPT') { if (type === 1 && node.tagName !== 'SCRIPT') {
return compileElement(node, options, asParent) return compileElement(node, options)
} else if (type === 3 && config.interpolate) { } else if (type === 3 && config.interpolate && node.data.trim()) {
return compileTextNode(node, options) return compileTextNode(node, options)
} else {
return null
} }
} }
...@@ -2311,14 +2341,20 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2311,14 +2341,20 @@ return /******/ (function(modules) { // webpackBootstrap
* *
* @param {Element} el * @param {Element} el
* @param {Object} options * @param {Object} options
* @param {Boolean} asParent
* @return {Function|null} * @return {Function|null}
*/ */
function compileElement (el, options, asParent) { function compileElement (el, options) {
if (checkTransclusion(el)) {
// unwrap textNode
if (el.hasAttribute('__vue__wrap')) {
el = el.firstChild
}
return compile(el, options._parent.$options, true, true)
}
var linkFn, tag, component var linkFn, tag, component
// check custom element component, but only on non-root // check custom element component, but only on non-root
if (!asParent && !el.__vue__) { if (!el.__vue__) {
tag = el.tagName.toLowerCase() tag = el.tagName.toLowerCase()
component = component =
tag.indexOf('-') > 0 && tag.indexOf('-') > 0 &&
...@@ -2329,14 +2365,12 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2329,14 +2365,12 @@ return /******/ (function(modules) { // webpackBootstrap
} }
if (component || el.hasAttributes()) { if (component || el.hasAttributes()) {
// check terminal direcitves // check terminal direcitves
if (!asParent) { linkFn = checkTerminalDirectives(el, options)
linkFn = checkTerminalDirectives(el, options)
}
// if not terminal, build normal link function // if not terminal, build normal link function
if (!linkFn) { if (!linkFn) {
var dirs = collectDirectives(el, options, asParent) var dirs = collectDirectives(el, options)
linkFn = dirs.length linkFn = dirs.length
? makeDirectivesLinkFn(dirs) ? makeNodeLinkFn(dirs)
: null : null
} }
} }
...@@ -2354,27 +2388,32 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2354,27 +2388,32 @@ return /******/ (function(modules) { // webpackBootstrap
} }
/** /**
* Build a multi-directive link function. * Build a link function for all directives on a single node.
* *
* @param {Array} directives * @param {Array} directives
* @return {Function} directivesLinkFn * @return {Function} directivesLinkFn
*/ */
function makeDirectivesLinkFn (directives) { function makeNodeLinkFn (directives) {
return function directivesLinkFn (vm, el) { return function nodeLinkFn (vm, el, host) {
// reverse apply because it's sorted low to high // reverse apply because it's sorted low to high
var i = directives.length var i = directives.length
var dir, j, k var dir, j, k, target
while (i--) { while (i--) {
dir = directives[i] dir = directives[i]
// a directive can be transcluded if it's written
// on a component's container in its parent tempalte.
target = dir.transcluded
? vm.$parent
: vm
if (dir._link) { if (dir._link) {
// custom link fn // custom link fn
dir._link(vm, el) dir._link(target, el)
} else { } else {
k = dir.descriptors.length k = dir.descriptors.length
for (j = 0; j < k; j++) { for (j = 0; j < k; j++) {
vm._bindDir(dir.name, el, target._bindDir(dir.name, el,
dir.descriptors[j], dir.def) dir.descriptors[j], dir.def, host)
} }
} }
} }
...@@ -2390,7 +2429,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2390,7 +2429,7 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
function compileTextNode (node, options) { function compileTextNode (node, options) {
var tokens = textParser.parse(node.nodeValue) var tokens = textParser.parse(node.data)
if (!tokens) { if (!tokens) {
return null return null
} }
...@@ -2463,7 +2502,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2463,7 +2502,7 @@ return /******/ (function(modules) { // webpackBootstrap
if (token.html) { if (token.html) {
_.replace(node, templateParser.parse(value, true)) _.replace(node, templateParser.parse(value, true))
} else { } else {
node.nodeValue = value node.data = value
} }
} else { } else {
vm._bindDir(token.type, node, vm._bindDir(token.type, node,
...@@ -2510,7 +2549,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2510,7 +2549,7 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
function makeChildLinkFn (linkFns) { function makeChildLinkFn (linkFns) {
return function childLinkFn (vm, nodes) { return function childLinkFn (vm, nodes, host) {
var node, nodeLinkFn, childrenLinkFn var node, nodeLinkFn, childrenLinkFn
for (var i = 0, n = 0, l = linkFns.length; i < l; n++) { for (var i = 0, n = 0, l = linkFns.length; i < l; n++) {
node = nodes[n] node = nodes[n]
...@@ -2519,10 +2558,10 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2519,10 +2558,10 @@ return /******/ (function(modules) { // webpackBootstrap
// cache childNodes before linking parent, fix #657 // cache childNodes before linking parent, fix #657
var childNodes = _.toArray(node.childNodes) var childNodes = _.toArray(node.childNodes)
if (nodeLinkFn) { if (nodeLinkFn) {
nodeLinkFn(vm, node) nodeLinkFn(vm, node, host)
} }
if (childrenLinkFn) { if (childrenLinkFn) {
childrenLinkFn(vm, childNodes) childrenLinkFn(vm, childNodes, host)
} }
} }
} }
...@@ -2532,7 +2571,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2532,7 +2571,7 @@ return /******/ (function(modules) { // webpackBootstrap
* Compile param attributes on a root element and return * Compile param attributes on a root element and return
* a paramAttributes link function. * a paramAttributes link function.
* *
* @param {Element} el * @param {Element|Object} el
* @param {Array} attrs * @param {Array} attrs
* @param {Object} options * @param {Object} options
* @return {Function} paramsLinkFn * @return {Function} paramsLinkFn
...@@ -2540,6 +2579,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2540,6 +2579,7 @@ return /******/ (function(modules) { // webpackBootstrap
function compileParamAttributes (el, attrs, options) { function compileParamAttributes (el, attrs, options) {
var params = [] var params = []
var isEl = el.nodeType
var i = attrs.length var i = attrs.length
var name, value, param var name, value, param
while (i--) { while (i--) {
...@@ -2553,7 +2593,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2553,7 +2593,7 @@ return /******/ (function(modules) { // webpackBootstrap
'http://vuejs.org/api/options.html#paramAttributes' 'http://vuejs.org/api/options.html#paramAttributes'
) )
} }
value = el.getAttribute(name) value = isEl ? el.getAttribute(name) : el[name]
if (value !== null) { if (value !== null) {
param = { param = {
name: name, name: name,
...@@ -2561,7 +2601,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2561,7 +2601,7 @@ return /******/ (function(modules) { // webpackBootstrap
} }
var tokens = textParser.parse(value) var tokens = textParser.parse(value)
if (tokens) { if (tokens) {
el.removeAttribute(name) if (isEl) el.removeAttribute(name)
if (tokens.length > 1) { if (tokens.length > 1) {
_.warn( _.warn(
'Invalid param attribute binding: "' + 'Invalid param attribute binding: "' +
...@@ -2646,13 +2686,16 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2646,13 +2686,16 @@ return /******/ (function(modules) { // webpackBootstrap
for (var i = 0; i < 3; i++) { for (var i = 0; i < 3; i++) {
dirName = terminalDirectives[i] dirName = terminalDirectives[i]
if (value = _.attr(el, dirName)) { if (value = _.attr(el, dirName)) {
return makeTeriminalLinkFn(el, dirName, value, options) return makeTerminalNodeLinkFn(el, dirName, value, options)
} }
} }
} }
/** /**
* Build a link function for a terminal directive. * Build a node link function for a terminal directive.
* A terminal link function terminates the current
* compilation recursion and handles compilation of the
* subtree in the directive.
* *
* @param {Element} el * @param {Element} el
* @param {String} dirName * @param {String} dirName
...@@ -2661,14 +2704,14 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2661,14 +2704,14 @@ return /******/ (function(modules) { // webpackBootstrap
* @return {Function} terminalLinkFn * @return {Function} terminalLinkFn
*/ */
function makeTeriminalLinkFn (el, dirName, value, options) { function makeTerminalNodeLinkFn (el, dirName, value, options) {
var descriptor = dirParser.parse(value)[0] var descriptor = dirParser.parse(value)[0]
var def = options.directives[dirName] var def = options.directives[dirName]
var terminalLinkFn = function (vm, el) { var fn = function terminalNodeLinkFn (vm, el, host) {
vm._bindDir(dirName, el, descriptor, def) vm._bindDir(dirName, el, descriptor, def, host)
} }
terminalLinkFn.terminal = true fn.terminal = true
return terminalLinkFn return fn
} }
/** /**
...@@ -2676,38 +2719,37 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2676,38 +2719,37 @@ return /******/ (function(modules) { // webpackBootstrap
* *
* @param {Element} el * @param {Element} el
* @param {Object} options * @param {Object} options
* @param {Boolean} asParent
* @return {Array} * @return {Array}
*/ */
function collectDirectives (el, options, asParent) { function collectDirectives (el, options) {
var attrs = _.toArray(el.attributes) var attrs = _.toArray(el.attributes)
var i = attrs.length var i = attrs.length
var dirs = [] var dirs = []
var attr, attrName, dir, dirName, dirDef var attr, attrName, dir, dirName, dirDef, transcluded
while (i--) { while (i--) {
attr = attrs[i] attr = attrs[i]
attrName = attr.name attrName = attr.name
transcluded =
options._transcludedAttrs &&
options._transcludedAttrs[attrName]
if (attrName.indexOf(config.prefix) === 0) { if (attrName.indexOf(config.prefix) === 0) {
dirName = attrName.slice(config.prefix.length) dirName = attrName.slice(config.prefix.length)
if (asParent &&
(dirName === 'with' ||
dirName === 'component')) {
continue
}
dirDef = options.directives[dirName] dirDef = options.directives[dirName]
_.assertAsset(dirDef, 'directive', dirName) _.assertAsset(dirDef, 'directive', dirName)
if (dirDef) { if (dirDef) {
dirs.push({ dirs.push({
name: dirName, name: dirName,
descriptors: dirParser.parse(attr.value), descriptors: dirParser.parse(attr.value),
def: dirDef def: dirDef,
transcluded: transcluded
}) })
} }
} else if (config.interpolate) { } else if (config.interpolate) {
dir = collectAttrDirective(el, attrName, attr.value, dir = collectAttrDirective(el, attrName, attr.value,
options) options)
if (dir) { if (dir) {
dir.transcluded = transcluded
dirs.push(dir) dirs.push(dir)
} }
} }
...@@ -2729,10 +2771,6 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2729,10 +2771,6 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
function collectAttrDirective (el, name, value, options) { function collectAttrDirective (el, name, value, options) {
if (options._skipAttrs &&
options._skipAttrs.indexOf(name) > -1) {
return
}
var tokens = textParser.parse(value) var tokens = textParser.parse(value)
if (tokens) { if (tokens) {
var def = options.directives.attr var def = options.directives.attr
...@@ -2772,12 +2810,29 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2772,12 +2810,29 @@ return /******/ (function(modules) { // webpackBootstrap
return a > b ? 1 : -1 return a > b ? 1 : -1
} }
/**
* Check whether an element is transcluded
*
* @param {Element} el
* @return {Boolean}
*/
var transcludedFlagAttr = '__vue__transcluded'
function checkTransclusion (el) {
if (el.nodeType === 1 && el.hasAttribute(transcludedFlagAttr)) {
el.removeAttribute(transcludedFlagAttr)
return true
}
}
/***/ }, /***/ },
/* 17 */ /* 17 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
var _ = __webpack_require__(11) var _ = __webpack_require__(11)
var config = __webpack_require__(15)
var templateParser = __webpack_require__(20) var templateParser = __webpack_require__(20)
var transcludedFlagAttr = '__vue__transcluded'
/** /**
* Process an element or a DocumentFragment based on a * Process an element or a DocumentFragment based on a
...@@ -2792,6 +2847,29 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2792,6 +2847,29 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
module.exports = function transclude (el, options) { module.exports = function transclude (el, options) {
if (options && options._asComponent) {
// mutating the options object here assuming the same
// object will be used for compile right after this
options._transcludedAttrs = extractAttrs(el.attributes)
// Mark content nodes and attrs so that the compiler
// knows they should be compiled in parent scope.
var i = el.childNodes.length
while (i--) {
var node = el.childNodes[i]
if (node.nodeType === 1) {
node.setAttribute(transcludedFlagAttr, '')
} else if (node.nodeType === 3 && node.data.trim()) {
// wrap transcluded textNodes in spans, because
// raw textNodes can't be persisted through clones
// by attaching attributes.
var wrapper = document.createElement('span')
wrapper.textContent = node.data
wrapper.setAttribute('__vue__wrap', '')
wrapper.setAttribute(transcludedFlagAttr, '')
el.replaceChild(wrapper, node)
}
}
}
// for template tags, what we want is its content as // for template tags, what we want is its content as
// a documentFragment (for block instances) // a documentFragment (for block instances)
if (el.tagName === 'TEMPLATE') { if (el.tagName === 'TEMPLATE') {
...@@ -2825,8 +2903,20 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2825,8 +2903,20 @@ return /******/ (function(modules) { // webpackBootstrap
var rawContent = options._content || _.extractContent(el) var rawContent = options._content || _.extractContent(el)
if (options.replace) { if (options.replace) {
if (frag.childNodes.length > 1) { if (frag.childNodes.length > 1) {
// this is a block instance which has no root node.
// however, the container in the parent template
// (which is replaced here) may contain v-with and
// paramAttributes that still need to be compiled
// for the child. we store all the container
// attributes on the options object and pass it down
// to the compiler.
var containerAttrs = options._containerAttrs = {}
var i = el.attributes.length
while (i--) {
var attr = el.attributes[i]
containerAttrs[attr.name] = attr.value
}
transcludeContent(frag, rawContent) transcludeContent(frag, rawContent)
_.copyAttributes(el, frag.firstChild)
return frag return frag
} else { } else {
var replacer = frag.firstChild var replacer = frag.firstChild
...@@ -2933,6 +3023,27 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -2933,6 +3023,27 @@ return /******/ (function(modules) { // webpackBootstrap
parent.removeChild(outlet) parent.removeChild(outlet)
} }
/**
* Helper to extract a component container's attribute names
* into a map, and filtering out `v-with` in the process.
* The resulting map will be used in compiler/compile to
* determine whether an attribute is transcluded.
*
* @param {NameNodeMap} attrs
*/
function extractAttrs (attrs) {
if (!attrs) return null
var res = {}
var vwith = config.prefix + 'with'
var i = attrs.length
while (i--) {
var name = attrs[i].name
if (name !== vwith) res[name] = true
}
return res
}
/***/ }, /***/ },
/* 18 */ /* 18 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
...@@ -3857,24 +3968,29 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -3857,24 +3968,29 @@ return /******/ (function(modules) { // webpackBootstrap
var Cache = __webpack_require__(52) var Cache = __webpack_require__(52)
var expressionCache = new Cache(1000) var expressionCache = new Cache(1000)
var keywords = var allowedKeywords =
'Math,Date,break,case,catch,continue,debugger,default,' + 'Math,Date,this,true,false,null,undefined,Infinity,NaN,' +
'delete,do,else,false,finally,for,function,if,in,' + 'isNaN,isFinite,decodeURI,decodeURIComponent,encodeURI,' +
'instanceof,new,null,return,switch,this,throw,true,try,' + 'encodeURIComponent,parseInt,parseFloat'
'typeof,var,void,while,with,undefined,abstract,boolean,' + var allowedKeywordsRE =
'byte,char,class,const,double,enum,export,extends,' + new RegExp('^(' + allowedKeywords.replace(/,/g, '\\b|') + '\\b)')
'final,float,goto,implements,import,int,interface,long,' +
'native,package,private,protected,public,short,static,' + // keywords that don't make sense inside expressions
'super,synchronized,throws,transient,volatile,' + var improperKeywords =
'arguments,let,yield' 'break,case,class,catch,const,continue,debugger,default,' +
'delete,do,else,export,extends,finally,for,function,if,' +
'import,in,instanceof,let,return,super,switch,throw,try,' +
'var,while,with,yield,enum,await,implements,package,' +
'proctected,static,interface,private,public'
var improperKeywordsRE =
new RegExp('^(' + improperKeywords.replace(/,/g, '\\b|') + '\\b)')
var wsRE = /\s/g var wsRE = /\s/g
var newlineRE = /\n/g var newlineRE = /\n/g
var saveRE = /[\{,]\s*[\w\$_]+\s*:|('[^']*'|"[^"]*")|new /g var saveRE = /[\{,]\s*[\w\$_]+\s*:|('[^']*'|"[^"]*")|new |typeof |void /g
var restoreRE = /"(\d+)"/g var restoreRE = /"(\d+)"/g
var pathTestRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\])*$/ var pathTestRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\])*$/
var pathReplaceRE = /[^\w$\.]([A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\])*)/g var pathReplaceRE = /[^\w$\.]([A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\])*)/g
var keywordsRE = new RegExp('^(' + keywords.replace(/,/g, '\\b|') + '\\b)')
var booleanLiteralRE = /^(true|false)$/ var booleanLiteralRE = /^(true|false)$/
/** /**
...@@ -3922,7 +4038,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -3922,7 +4038,7 @@ return /******/ (function(modules) { // webpackBootstrap
function rewrite (raw) { function rewrite (raw) {
var c = raw.charAt(0) var c = raw.charAt(0)
var path = raw.slice(1) var path = raw.slice(1)
if (keywordsRE.test(path)) { if (allowedKeywordsRE.test(path)) {
return raw return raw
} else { } else {
path = path.indexOf('"') > -1 path = path.indexOf('"') > -1
...@@ -3954,6 +4070,12 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -3954,6 +4070,12 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
function compileExpFns (exp, needSet) { function compileExpFns (exp, needSet) {
if (improperKeywordsRE.test(exp)) {
_.warn(
'Avoid using reserved keywords in expression: '
+ exp
)
}
// reset state // reset state
saved.length = 0 saved.length = 0
// save strings and object literal keys // save strings and object literal keys
...@@ -4084,7 +4206,9 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -4084,7 +4206,9 @@ return /******/ (function(modules) { // webpackBootstrap
// global "Math" // global "Math"
var res = var res =
pathTestRE.test(exp) && pathTestRE.test(exp) &&
// don't treat true/false as paths
!booleanLiteralRE.test(exp) && !booleanLiteralRE.test(exp) &&
// Math constants e.g. Math.PI, Math.E etc.
exp.slice(0, 5) !== 'Math.' exp.slice(0, 5) !== 'Math.'
? compilePathFns(exp) ? compilePathFns(exp)
: compileExpFns(exp, needSet) : compileExpFns(exp, needSet)
...@@ -4177,10 +4301,11 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -4177,10 +4301,11 @@ return /******/ (function(modules) { // webpackBootstrap
* - {String} [arg] * - {String} [arg]
* - {Array<Object>} [filters] * - {Array<Object>} [filters]
* @param {Object} def - directive definition object * @param {Object} def - directive definition object
* @param {Vue|undefined} host - transclusion host target
* @constructor * @constructor
*/ */
function Directive (name, el, vm, descriptor, def) { function Directive (name, el, vm, descriptor, def, host) {
// public // public
this.name = name this.name = name
this.el = el this.el = el
...@@ -4191,6 +4316,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -4191,6 +4316,7 @@ return /******/ (function(modules) { // webpackBootstrap
this.arg = descriptor.arg this.arg = descriptor.arg
this.filters = _.resolveFilters(vm, descriptor.filters) this.filters = _.resolveFilters(vm, descriptor.filters)
// private // private
this._host = host
this._locked = false this._locked = false
this._bound = false this._bound = false
// init // init
...@@ -4208,7 +4334,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -4208,7 +4334,7 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
p._bind = function (def) { p._bind = function (def) {
if (this.name !== 'cloak' && this.el.removeAttribute) { if (this.name !== 'cloak' && this.el && this.el.removeAttribute) {
this.el.removeAttribute(config.prefix + this.name) this.el.removeAttribute(config.prefix + this.name)
} }
if (typeof def === 'function') { if (typeof def === 'function') {
...@@ -4608,7 +4734,10 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -4608,7 +4734,10 @@ return /******/ (function(modules) { // webpackBootstrap
// which can improve teardown performance. // which can improve teardown performance.
if (!this.vm._isBeingDestroyed) { if (!this.vm._isBeingDestroyed) {
var list = this.vm._watcherList var list = this.vm._watcherList
list.splice(list.indexOf(this)) var i = list.indexOf(this)
if (i > -1) {
list.splice(i, 1)
}
} }
for (var id in this.deps) { for (var id in this.deps) {
this.deps[id].removeSub(this) this.deps[id].removeSub(this)
...@@ -5310,15 +5439,8 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -5310,15 +5439,8 @@ return /******/ (function(modules) { // webpackBootstrap
* @param {String} msg * @param {String} msg
*/ */
var warned = false
exports.warn = function (msg) { exports.warn = function (msg) {
if (hasConsole && (!config.silent || config.debug)) { if (hasConsole && (!config.silent || config.debug)) {
if (!config.debug && !warned) {
warned = true
console.log(
'Set `Vue.config.debug = true` to enable debug mode.'
)
}
console.warn('[Vue warn]: ' + msg) console.warn('[Vue warn]: ' + msg)
/* istanbul ignore if */ /* istanbul ignore if */
if (config.debug) { if (config.debug) {
...@@ -5658,6 +5780,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -5658,6 +5780,7 @@ return /******/ (function(modules) { // webpackBootstrap
// same logic reuse from v-if // same logic reuse from v-if
compile: vIf.compile, compile: vIf.compile,
teardown: vIf.teardown, teardown: vIf.teardown,
getContainedComponents: vIf.getContainedComponents,
unbind: vIf.unbind, unbind: vIf.unbind,
bind: function () { bind: function () {
...@@ -5687,6 +5810,10 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -5687,6 +5810,10 @@ return /******/ (function(modules) { // webpackBootstrap
var partial = this.vm.$options.partials[id] var partial = this.vm.$options.partials[id]
_.assertAsset(partial, 'partial', id) _.assertAsset(partial, 'partial', id)
if (partial) { if (partial) {
var filters = this.filters && this.filters.read
if (filters) {
partial = _.applyFilters(partial, filters, this.vm)
}
this.compile(templateParser.parse(partial, true)) this.compile(templateParser.parse(partial, true))
} }
} }
...@@ -5703,10 +5830,20 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -5703,10 +5830,20 @@ return /******/ (function(modules) { // webpackBootstrap
isLiteral: true, isLiteral: true,
bind: function () { bind: function () {
if (!this._isDynamicLiteral) {
this.update(this.expression)
}
},
update: function (id) {
var vm = this.el.__vue__ || this.vm
this.el.__v_trans = { this.el.__v_trans = {
id: this.expression, id: id,
// resolve the custom transition functions now // resolve the custom transition functions now
fns: this.vm.$options.transitions[this.expression] // so the transition module knows this is a
// javascript transition without having to check
// computed CSS.
fns: vm.$options.transitions[id]
} }
} }
...@@ -5869,7 +6006,8 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -5869,7 +6006,8 @@ return /******/ (function(modules) { // webpackBootstrap
var child = vm.$addChild({ var child = vm.$addChild({
el: el, el: el,
template: this.template, template: this.template,
_asComponent: true _asComponent: true,
_host: this._host
}, this.Ctor) }, this.Ctor)
if (this.keepAlive) { if (this.keepAlive) {
this.cache[this.ctorId] = child this.cache[this.ctorId] = child
...@@ -6123,21 +6261,18 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6123,21 +6261,18 @@ return /******/ (function(modules) { // webpackBootstrap
if (!tokens) { // static component if (!tokens) { // static component
var Ctor = this.Ctor = options.components[id] var Ctor = this.Ctor = options.components[id]
_.assertAsset(Ctor, 'component', id) _.assertAsset(Ctor, 'component', id)
// If there's no parent scope directives and no var merged = mergeOptions(Ctor.options, {}, {
// content to be transcluded, we can optimize the $parent: this.vm
// rendering by pre-transcluding + compiling here })
// and provide a link function to every instance. merged.template = this.inlineTempalte || merged.template
if (!this.el.hasChildNodes() && merged._asComponent = true
!this.el.hasAttributes()) { merged._parent = this.vm
// merge an empty object with owner vm as parent this.template = transclude(this.template, merged)
// so child vms can access parent assets. // Important: mark the template as a root node so that
var merged = mergeOptions(Ctor.options, {}, { // custom element components don't get compiled twice.
$parent: this.vm // fixes #822
}) this.template.__vue__ = true
merged.template = this.inlineTempalte || merged.template this._linkFn = compile(this.template, merged)
this.template = transclude(this.template, merged)
this._linkFn = compile(this.template, merged, false, true)
}
} else { } else {
// to be resolved later // to be resolved later
var ctorExp = textParser.tokensToExp(tokens) var ctorExp = textParser.tokensToExp(tokens)
...@@ -6262,9 +6397,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6262,9 +6397,7 @@ return /******/ (function(modules) { // webpackBootstrap
vm.$before(ref) vm.$before(ref)
} }
} else { } else {
// make sure to insert before the comment node if var nextEl = targetNext.$el
// the vms are block instances
var nextEl = targetNext._blockStart || targetNext.$el
if (vm._reused) { if (vm._reused) {
// this is the vm we are actually in front of // this is the vm we are actually in front of
currentNext = findNextVm(vm, ref) currentNext = findNextVm(vm, ref)
...@@ -6293,26 +6426,29 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6293,26 +6426,29 @@ return /******/ (function(modules) { // webpackBootstrap
*/ */
build: function (data, index, needCache) { build: function (data, index, needCache) {
var original = data
var meta = { $index: index } var meta = { $index: index }
if (this.converted) { if (this.converted) {
meta.$key = original.$key meta.$key = data.$key
} }
var raw = this.converted ? data.$value : data var raw = this.converted ? data.$value : data
var alias = this.arg var alias = this.arg
var hasAlias = !isObject(raw) || !isPlainObject(data) || alias
// wrap the raw data with alias
data = hasAlias ? {} : raw
if (alias) { if (alias) {
data = {}
data[alias] = raw data[alias] = raw
} else if (hasAlias) { } else if (!isPlainObject(raw)) {
// non-object values
data = {}
meta.$value = raw meta.$value = raw
} else {
// default
data = raw
} }
// resolve constructor // resolve constructor
var Ctor = this.Ctor || this.resolveCtor(data, meta) var Ctor = this.Ctor || this.resolveCtor(data, meta)
var vm = this.vm.$addChild({ var vm = this.vm.$addChild({
el: templateParser.clone(this.template), el: templateParser.clone(this.template),
_asComponent: this.asComponent, _asComponent: this.asComponent,
_host: this._host,
_linkFn: this._linkFn, _linkFn: this._linkFn,
_meta: meta, _meta: meta,
data: data, data: data,
...@@ -6572,15 +6708,11 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6572,15 +6708,11 @@ return /******/ (function(modules) { // webpackBootstrap
this.end = document.createComment('v-if-end') this.end = document.createComment('v-if-end')
_.replace(el, this.end) _.replace(el, this.end)
_.before(this.start, this.end) _.before(this.start, this.end)
// Note: content transclusion is not available for
// <template> blocks
if (el.tagName === 'TEMPLATE') { if (el.tagName === 'TEMPLATE') {
this.template = templateParser.parse(el, true) this.template = templateParser.parse(el, true)
} else { } else {
this.template = document.createDocumentFragment() this.template = document.createDocumentFragment()
this.template.appendChild(templateParser.clone(el)) this.template.appendChild(templateParser.clone(el))
this.checkContent()
} }
// compile the nested partial // compile the nested partial
this.linker = compile( this.linker = compile(
...@@ -6597,32 +6729,6 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6597,32 +6729,6 @@ return /******/ (function(modules) { // webpackBootstrap
} }
}, },
// check if there are any content nodes from parent.
// these nodes are compiled by the parent and should
// not be cloned during a re-compilation - otherwise the
// parent directives bound to them will no longer work.
// (see #736)
checkContent: function () {
var el = this.el
for (var i = 0; i < el.childNodes.length; i++) {
var node = el.childNodes[i]
// _isContent is a flag set in instance/compile
// after the raw content has been compiled by parent
if (node._isContent) {
;(this.contentNodes = this.contentNodes || []).push(node)
;(this.contentPositions = this.contentPositions || []).push(i)
}
}
// keep track of any transcluded components contained within
// the conditional block. we need to call attach/detach hooks
// for them.
this.transCpnts =
this.vm._transCpnts &&
this.vm._transCpnts.filter(function (c) {
return el.contains(c.$el)
})
},
update: function (value) { update: function (value) {
if (this.invalid) return if (this.invalid) return
if (value) { if (value) {
...@@ -6630,15 +6736,6 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6630,15 +6736,6 @@ return /******/ (function(modules) { // webpackBootstrap
// called with different truthy values // called with different truthy values
if (!this.unlink) { if (!this.unlink) {
var frag = templateParser.clone(this.template) var frag = templateParser.clone(this.template)
// persist content nodes from parent.
if (this.contentNodes) {
var el = frag.childNodes[0]
for (var i = 0, l = this.contentNodes.length; i < l; i++) {
var node = this.contentNodes[i]
var j = this.contentPositions[i]
el.replaceChild(node, el.childNodes[j])
}
}
this.compile(frag) this.compile(frag)
} }
} else { } else {
...@@ -6649,37 +6746,66 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6649,37 +6746,66 @@ return /******/ (function(modules) { // webpackBootstrap
// NOTE: this function is shared in v-partial // NOTE: this function is shared in v-partial
compile: function (frag) { compile: function (frag) {
var vm = this.vm var vm = this.vm
var originalChildLength = vm._children.length // the linker is not guaranteed to be present because
// this function might get called by v-partial
this.unlink = this.linker this.unlink = this.linker
? this.linker(vm, frag) ? this.linker(vm, frag)
: vm.$compile(frag) : vm.$compile(frag)
transition.blockAppend(frag, this.end, vm) transition.blockAppend(frag, this.end, vm)
this.children = vm._children.slice(originalChildLength) // call attached for all the child components created
if (this.transCpnts) { // during the compilation
this.children = this.children.concat(this.transCpnts) if (_.inDoc(vm.$el)) {
} var children = this.getContainedComponents()
if (this.children.length && _.inDoc(vm.$el)) { if (children) children.forEach(callAttach)
this.children.forEach(function (child) {
child._callHook('attached')
})
} }
}, },
// NOTE: this function is shared in v-partial // NOTE: this function is shared in v-partial
teardown: function () { teardown: function () {
if (!this.unlink) return if (!this.unlink) return
transition.blockRemove(this.start, this.end, this.vm) // collect children beforehand
if (this.children && _.inDoc(this.vm.$el)) { var children
this.children.forEach(function (child) { if (_.inDoc(this.vm.$el)) {
if (!child._isDestroyed) { children = this.getContainedComponents()
child._callHook('detached')
}
})
} }
transition.blockRemove(this.start, this.end, this.vm)
if (children) children.forEach(callDetach)
this.unlink() this.unlink()
this.unlink = null this.unlink = null
}, },
// NOTE: this function is shared in v-partial
getContainedComponents: function () {
var vm = this.vm
var start = this.start.nextSibling
var end = this.end
var selfCompoents =
vm._children.length &&
vm._children.filter(contains)
var transComponents =
vm._transCpnts &&
vm._transCpnts.filter(contains)
function contains (c) {
var cur = start
var next
while (next !== end) {
next = cur.nextSibling
if (cur.contains(c.$el)) {
return true
}
cur = next
}
return false
}
return selfCompoents
? transComponents
? selfCompoents.concat(transComponents)
: selfCompoents
: transComponents
},
// NOTE: this function is shared in v-partial // NOTE: this function is shared in v-partial
unbind: function () { unbind: function () {
if (this.unlink) this.unlink() if (this.unlink) this.unlink()
...@@ -6687,12 +6813,26 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6687,12 +6813,26 @@ return /******/ (function(modules) { // webpackBootstrap
} }
function callAttach (child) {
if (!child._isAttached) {
child._callHook('attached')
}
}
function callDetach (child) {
if (child._isAttached) {
child._callHook('detached')
}
}
/***/ }, /***/ },
/* 46 */ /* 46 */
/***/ function(module, exports, __webpack_require__) { /***/ function(module, exports, __webpack_require__) {
var _ = __webpack_require__(11) var _ = __webpack_require__(11)
var Watcher = __webpack_require__(25) var Watcher = __webpack_require__(25)
var expParser = __webpack_require__(22)
var literalRE = /^(true|false|\s?('[^']*'|"[^"]")\s?)$/
module.exports = { module.exports = {
...@@ -6705,7 +6845,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6705,7 +6845,7 @@ return /******/ (function(modules) { // webpackBootstrap
var childKey = this.arg || '$data' var childKey = this.arg || '$data'
var parentKey = this.expression var parentKey = this.expression
if (this.el !== child.$el) { if (this.el && this.el !== child.$el) {
_.warn( _.warn(
'v-with can only be used on instance root elements.' 'v-with can only be used on instance root elements.'
) )
...@@ -6713,6 +6853,17 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6713,6 +6853,17 @@ return /******/ (function(modules) { // webpackBootstrap
_.warn( _.warn(
'v-with must be used on an instance with a parent.' 'v-with must be used on an instance with a parent.'
) )
} else if (literalRE.test(parentKey)) {
// no need to setup watchers for literal bindings
if (!this.arg) {
_.warn(
'v-with cannot bind literal value as $data: ' +
parentKey
)
} else {
var value = expParser.parse(parentKey).get()
child.$set(childKey, value)
}
} else { } else {
// simple lock to avoid circular updates. // simple lock to avoid circular updates.
...@@ -6771,7 +6922,9 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6771,7 +6922,9 @@ return /******/ (function(modules) { // webpackBootstrap
var _ = __webpack_require__(11) var _ = __webpack_require__(11)
module.exports = { module.exports = {
acceptStatement: true,
bind: function () { bind: function () {
var child = this.el.__vue__ var child = this.el.__vue__
...@@ -6782,14 +6935,21 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -6782,14 +6935,21 @@ return /******/ (function(modules) { // webpackBootstrap
) )
return return
} }
var method = this.vm[this.expression] },
if (!method) {
update: function (handler, oldHandler) {
if (typeof handler !== 'function') {
_.warn( _.warn(
'`v-events` cannot find method "' + this.expression + 'Directive "v-events:' + this.expression + '" ' +
'" on the parent instance.' 'expects a function value.'
) )
return
} }
child.$on(this.arg, method) var child = this.el.__vue__
if (oldHandler) {
child.$off(this.arg, oldHandler)
}
child.$on(this.arg, handler)
} }
// when child is destroyed, all events are turned off, // when child is destroyed, all events are turned off,
...@@ -7137,6 +7297,7 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -7137,6 +7297,7 @@ return /******/ (function(modules) { // webpackBootstrap
var _ = __webpack_require__(11) var _ = __webpack_require__(11)
var applyCSSTransition = __webpack_require__(56) var applyCSSTransition = __webpack_require__(56)
var applyJSTransition = __webpack_require__(57) var applyJSTransition = __webpack_require__(57)
var doc = typeof document === 'undefined' ? null : document
/** /**
* Append with transition. * Append with transition.
...@@ -7270,7 +7431,15 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -7270,7 +7431,15 @@ return /******/ (function(modules) { // webpackBootstrap
vm, vm,
cb cb
) )
} else if (_.transitionEndEvent) { } else if (
_.transitionEndEvent &&
// skip CSS transitions if page is not visible -
// this solves the issue of transitionend events not
// firing until the page is visible again.
// pageVisibility API is supported in IE10+, same as
// CSS transitions.
!(doc && doc.hidden)
) {
// css // css
applyCSSTransition( applyCSSTransition(
el, el,
...@@ -7698,6 +7867,24 @@ return /******/ (function(modules) { // webpackBootstrap ...@@ -7698,6 +7867,24 @@ return /******/ (function(modules) { // webpackBootstrap
} }
) )
/**
* Set a property on an observed object, calling add to
* ensure the property is observed.
*
* @param {String} key
* @param {*} val
* @public
*/
_.define(
objProto,
'$set',
function $set (key, val) {
this.$add(key, val)
this[key] = val
}
)
/** /**
* Deletes a property from an observed object * Deletes a property from an observed object
* and emits corresponding event * and emits corresponding event
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
"director": "^1.2.0", "director": "^1.2.0",
"vue": "^0.11.5", "vue": "^0.11.5",
"todomvc-common": "^1.0.1", "todomvc-common": "^1.0.1",
"todomvc-app-css": "^1.0.1" "todomvc-app-css": "^2.0.0"
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment