mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Backed out body-slot support and significant code size reductions
This commit is contained in:
parent
306e19b88e
commit
74d802b074
@ -14,13 +14,13 @@
|
||||
};
|
||||
</script>
|
||||
div
|
||||
h1 - Hello ${state.name}!
|
||||
h1 -- Hello ${state.name}!
|
||||
div.colors
|
||||
ul if(state.colors.length)
|
||||
for(color in state.colors)
|
||||
li.color style="background-color: ${color}"
|
||||
- ${color}
|
||||
-- ${color}
|
||||
div else
|
||||
- No colors!
|
||||
-- No colors!
|
||||
button type="button" onClick('handleButtonClick')
|
||||
- You clicked the button ${state.clickCount} time(s)
|
||||
-- You clicked the button ${state.clickCount} time(s)
|
||||
@ -34,31 +34,23 @@ var proto = RenderResult.prototype = {
|
||||
return rerenderWidget;
|
||||
}
|
||||
|
||||
return getWidgetDefs(this)[0].widget;
|
||||
return getWidgetDefs(this)[0].$__widget;
|
||||
},
|
||||
getWidgets: function(selector) {
|
||||
checkAddedToDOM(this, 'getWidgets');
|
||||
|
||||
var widgetDefs = getWidgetDefs(this);
|
||||
|
||||
var widgets;
|
||||
var widgets = [];
|
||||
var i;
|
||||
if (selector) {
|
||||
// use the selector to find the widgets that the caller wants
|
||||
widgets = [];
|
||||
for (i = 0; i < widgetDefs.length; i++) {
|
||||
var widget = widgetDefs[i].widget;
|
||||
if (selector(widget)) {
|
||||
widgets.push(widget);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// return all widgets
|
||||
widgets = new Array(widgetDefs.length);
|
||||
for (i = 0; i < widgetDefs.length; i++) {
|
||||
widgets[i] = widgetDefs[i].widget;
|
||||
|
||||
for (i = 0; i < widgetDefs.length; i++) {
|
||||
var widget = widgetDefs[i].$__widget;
|
||||
if (!selector || selector(widget)) {
|
||||
widgets.push(widget);
|
||||
}
|
||||
}
|
||||
|
||||
return widgets;
|
||||
},
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ var proto = AsyncVDOMBuilder.prototype = {
|
||||
n: function(node) {
|
||||
// NOTE: We do a shallow clone since we assume the node is being reused
|
||||
// and a node can only have one parent node.
|
||||
return this.node(node.cloneNode());
|
||||
return this.node(node.$__cloneNode());
|
||||
},
|
||||
|
||||
node: function(node) {
|
||||
@ -185,8 +185,7 @@ var proto = AsyncVDOMBuilder.prototype = {
|
||||
},
|
||||
|
||||
getResult: function() {
|
||||
this.$__result = this.$__result || new RenderResult(this);
|
||||
return this.$__result;
|
||||
return this.$__result || (this.$__result = new RenderResult(this));
|
||||
},
|
||||
|
||||
on: function(event, callback) {
|
||||
|
||||
@ -13,7 +13,7 @@ Comment.prototype = {
|
||||
return document.createComment(this.nodeValue);
|
||||
},
|
||||
|
||||
cloneNode: function() {
|
||||
$__cloneNode: function() {
|
||||
return new Comment(this.nodeValue);
|
||||
}
|
||||
};
|
||||
|
||||
@ -18,7 +18,7 @@ DocumentFragment.prototype = {
|
||||
|
||||
$__nsAware: true,
|
||||
|
||||
cloneNode: function() {
|
||||
$__cloneNode: function() {
|
||||
return new DocumentFragmentClone(this);
|
||||
},
|
||||
|
||||
|
||||
@ -187,7 +187,7 @@ HTMLElement.prototype = {
|
||||
targetNode._vattrs = attrs;
|
||||
},
|
||||
|
||||
cloneNode: function() {
|
||||
$__cloneNode: function() {
|
||||
return new HTMLElementClone(this);
|
||||
},
|
||||
|
||||
@ -247,7 +247,7 @@ HTMLElement.prototype = {
|
||||
* @param {String} value The value for the new Comment node
|
||||
*/
|
||||
n: function(node) {
|
||||
this.$__appendChild(node.cloneNode());
|
||||
this.$__appendChild(node.$__cloneNode());
|
||||
return this.$__finishChild();
|
||||
},
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ Text.prototype = {
|
||||
return document.createTextNode(this.nodeValue);
|
||||
},
|
||||
|
||||
cloneNode: function() {
|
||||
$__cloneNode: function() {
|
||||
return new Text(this.nodeValue);
|
||||
}
|
||||
};
|
||||
|
||||
@ -16,9 +16,6 @@ function virtualize(node) {
|
||||
var attributes = node.attributes;
|
||||
var attrCount = attributes.length;
|
||||
|
||||
var childNodes = node.childNodes;
|
||||
var childCount = childNodes.length;
|
||||
|
||||
var attrs;
|
||||
|
||||
if (attrCount) {
|
||||
@ -38,7 +35,7 @@ function virtualize(node) {
|
||||
}
|
||||
}
|
||||
|
||||
var vdomEL = new HTMLElement(node.nodeName, attrs, childCount);
|
||||
var vdomEL = new HTMLElement(node.nodeName, attrs);
|
||||
|
||||
if (vdomEL.$__isTextArea) {
|
||||
vdomEL.value = node.value;
|
||||
|
||||
20
taglibs/cache/cached-fragment-tag.js
vendored
20
taglibs/cache/cached-fragment-tag.js
vendored
@ -1,19 +1,3 @@
|
||||
/*
|
||||
* Copyright 2011 eBay Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
module.exports = {
|
||||
render: function (input, out) {
|
||||
@ -50,10 +34,10 @@ module.exports = {
|
||||
return asyncOut.error(err);
|
||||
}
|
||||
|
||||
if (result.cloneNode) {
|
||||
if (result.$__cloneNode) {
|
||||
var curChild = result.firstChild;
|
||||
while(curChild) {
|
||||
asyncOut.node(curChild.cloneNode());
|
||||
asyncOut.node(curChild.$__cloneNode());
|
||||
curChild = curChild.nextSibling;
|
||||
}
|
||||
asyncOut.end();
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
module.exports = function codeGenerator(elNode, generator) {
|
||||
var context = generator.context;
|
||||
var builder = generator.builder;
|
||||
var includeNode = context.createNodeForEl('include');
|
||||
includeNode.addProp(
|
||||
'_target',
|
||||
builder.memberExpression(
|
||||
builder.identifier('data'),
|
||||
builder.identifier('renderBody')));
|
||||
return includeNode;
|
||||
};
|
||||
@ -170,24 +170,6 @@ var coreAttrHandlers = [
|
||||
context.addError(el, 'The include attribute must have an argument. For example: include("./target.marko") or include(data.renderBody)');
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'body-slot', function(attr, node, el) {
|
||||
var context = this.context;
|
||||
|
||||
if (attr.argument) {
|
||||
context.addError(el, 'The body-slot attribute should not have an argument.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (attr.value) {
|
||||
context.addError(el, 'The body-slot attribute should not have a value.');
|
||||
return;
|
||||
}
|
||||
|
||||
var bodySlot = context.createNodeForEl('body-slot');
|
||||
node.appendChild(bodySlot);
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@ -9,17 +9,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"<body-slot>": {
|
||||
"code-generator": "./body-slot-tag",
|
||||
"attributes": {},
|
||||
"autocomplete": [
|
||||
{
|
||||
"displayText": "body-slot",
|
||||
"snippet": "body-slot",
|
||||
"openTagOnly": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"<else>": {
|
||||
"node-factory": "./else-tag",
|
||||
"attributes": {},
|
||||
|
||||
@ -1 +0,0 @@
|
||||
<div><h1>Test</h1><div class="body"><strong>This is the body</strong></div></div>
|
||||
@ -1,3 +0,0 @@
|
||||
<div body-slot(invalid)>
|
||||
|
||||
</div>
|
||||
@ -1,8 +0,0 @@
|
||||
var expect = require('chai').expect;
|
||||
|
||||
exports.templateData = {};
|
||||
|
||||
exports.checkError = function(e) {
|
||||
var message = e.toString();
|
||||
expect(message).to.contain('The body-slot attribute should not have an argument');
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
<div><h1>Test</h1><div class="body"><strong>This is the body</strong></div></div>
|
||||
@ -1,3 +0,0 @@
|
||||
<div body-slot='invalid'>
|
||||
|
||||
</div>
|
||||
@ -1,8 +0,0 @@
|
||||
var expect = require('chai').expect;
|
||||
|
||||
exports.templateData = {};
|
||||
|
||||
exports.checkError = function(e) {
|
||||
var message = e.toString();
|
||||
expect(message).to.contain('The body-slot attribute should not have a value');
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
<div><h1>Test</h1><div class="body"><strong>This is the body</strong></div></div>
|
||||
@ -1,4 +0,0 @@
|
||||
<div>
|
||||
<h1>Test</h1>
|
||||
<div.body body-slot/>
|
||||
</div>
|
||||
@ -1,3 +0,0 @@
|
||||
<include('./include-target.marko')>
|
||||
<strong>This is the body</strong>
|
||||
</include>
|
||||
@ -1 +0,0 @@
|
||||
exports.templateData = {};
|
||||
@ -1 +0,0 @@
|
||||
<div><h1>Test</h1><div class="body"><strong>This is the body</strong></div></div>
|
||||
@ -1,6 +0,0 @@
|
||||
<div>
|
||||
<h1>Test</h1>
|
||||
<div.body>
|
||||
<body-slot/>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,3 +0,0 @@
|
||||
<include('./include-target.marko')>
|
||||
<strong>This is the body</strong>
|
||||
</include>
|
||||
@ -1 +0,0 @@
|
||||
exports.templateData = {};
|
||||
@ -18,7 +18,6 @@
|
||||
"ref",
|
||||
"w-for",
|
||||
"w-id",
|
||||
"body-slot",
|
||||
"w-body",
|
||||
"w-preserve",
|
||||
"w-preserve-body",
|
||||
|
||||
@ -11,7 +11,6 @@
|
||||
"lasso-resource",
|
||||
"browser-refresh",
|
||||
"assign",
|
||||
"body-slot",
|
||||
"else",
|
||||
"else-if",
|
||||
"for",
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
"await-timeout",
|
||||
"bar",
|
||||
"body",
|
||||
"body-slot",
|
||||
"browser-refresh",
|
||||
"cached-fragment",
|
||||
"else",
|
||||
|
||||
@ -2,7 +2,7 @@ var expect = require('chai').expect;
|
||||
|
||||
module.exports = function(helpers) {
|
||||
var comment = helpers.vdom.createComment('This is a comment');
|
||||
var commentClone = comment.cloneNode();
|
||||
var commentClone = comment.$__cloneNode();
|
||||
expect(commentClone).to.not.equal(comment);
|
||||
expect(comment.nodeValue).to.equal('This is a comment');
|
||||
expect(commentClone.nodeValue).to.equal('This is a comment');
|
||||
|
||||
@ -7,7 +7,7 @@ module.exports = function(helpers) {
|
||||
svg.$__appendChild(docFragment);
|
||||
|
||||
expect(docFragment.namespaceURI).to.equal('http://www.w3.org/2000/svg');
|
||||
var docFragmentClone = docFragment.cloneNode();
|
||||
var docFragmentClone = docFragment.$__cloneNode();
|
||||
expect(docFragmentClone.namespaceURI).to.equal('http://www.w3.org/2000/svg');
|
||||
expect(docFragmentClone.nextSibling).to.equal(undefined);
|
||||
expect(docFragmentClone.parentNode).to.equal(undefined);
|
||||
|
||||
@ -2,7 +2,7 @@ var expect = require('chai').expect;
|
||||
|
||||
module.exports = function(helpers) {
|
||||
var text = helpers.vdom.createText('Hello World');
|
||||
var textClone = text.cloneNode();
|
||||
var textClone = text.$__cloneNode();
|
||||
expect(textClone).to.not.equal(text);
|
||||
expect(text.nodeValue).to.equal('Hello World');
|
||||
expect(textClone.nodeValue).to.equal('Hello World');
|
||||
|
||||
@ -19,7 +19,7 @@ module.exports = function(helpers) {
|
||||
'xlink:href': 'http://ebay.com/'
|
||||
}, 0);
|
||||
|
||||
var clone = el.cloneNode();
|
||||
var clone = el.$__cloneNode();
|
||||
expect(clone).to.not.equal(el);
|
||||
expect(clone.nodeName).to.equal('div');
|
||||
expect(clone.hasAttributeNS(null, 'class')).to.equal(true);
|
||||
|
||||
@ -4,7 +4,7 @@ module.exports = function(helpers) {
|
||||
var div = helpers.vdom.createElement('div', null, 0 /* childCount */, 'abc123' /* key */);
|
||||
var span = helpers.vdom.createElement('span', null, 0 /* childCount */);
|
||||
|
||||
var divClone = div.cloneNode();
|
||||
var divClone = div.$__cloneNode();
|
||||
expect(div.isSameNode(divClone)).to.equal(true);
|
||||
expect(divClone.isSameNode(div)).to.equal(true);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<div class=data.className role="alert" w-bind>
|
||||
<div>
|
||||
<h1>ALERT! ${data.type} ${Date.now()}</h1>
|
||||
<h1>ALERT! ${data.type}</h1>
|
||||
<div w-body/>
|
||||
</div>
|
||||
</div>
|
||||
@ -3,14 +3,11 @@ module.exports = {
|
||||
return {
|
||||
size: input.size || 'normal',
|
||||
variant: input.variant || 'primary',
|
||||
className: input['class']
|
||||
className: input['class'],
|
||||
body: input.label || input.renderBody
|
||||
};
|
||||
},
|
||||
|
||||
getInitialBody: function(input) {
|
||||
return input.label || input.renderBody;
|
||||
},
|
||||
|
||||
handleClick: function(event) {
|
||||
// Every Widget instance is also an EventEmitter instance.
|
||||
// We will emit a custom "click" event when a DOM click event
|
||||
|
||||
@ -4,5 +4,7 @@
|
||||
'app-button-' + state.variant,
|
||||
'app-button-' + state.size
|
||||
] onClick("handleClick")>
|
||||
<span body-slot/>
|
||||
<span>
|
||||
<include(state.body)/>
|
||||
</span>
|
||||
</button>
|
||||
@ -3,12 +3,10 @@ module.exports = {
|
||||
this.state = {
|
||||
checked: input.checked === true,
|
||||
className: input['class'],
|
||||
data: input.data
|
||||
data: input.data,
|
||||
body: input.label || input.renderBody
|
||||
};
|
||||
},
|
||||
getInitialBody: function(input) {
|
||||
return input.label || input.renderBody;
|
||||
},
|
||||
|
||||
isChecked: function() {
|
||||
return this.state.checked === true;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<app-button ref="button" class=state.className onClick('handleClick')>
|
||||
<span class="app-checkbox-icon"/>
|
||||
<span ref="checkboxLabel">
|
||||
<body-slot/>
|
||||
<include(state.body)/>
|
||||
</span>
|
||||
</app-button>
|
||||
@ -2,7 +2,8 @@
|
||||
module.exports = {
|
||||
onInput: function(input) {
|
||||
this.state = {
|
||||
name: input.name
|
||||
name: input.name,
|
||||
body: input.renderBody
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -10,5 +11,7 @@
|
||||
|
||||
<div.foo>
|
||||
<span>Hello ${state.name}!</span>
|
||||
<div.body><body-slot/></div>
|
||||
<div.body>
|
||||
<include(state.body)/>
|
||||
</div>
|
||||
</div>
|
||||
@ -3,9 +3,9 @@ module.exports = {
|
||||
onInput: function(input) {
|
||||
this.state = {
|
||||
size: input.size || 'normal',
|
||||
variant: input.variant || 'primary'
|
||||
variant: input.variant || 'primary',
|
||||
body: input.renderBody
|
||||
};
|
||||
this.body = input.renderBody;
|
||||
},
|
||||
|
||||
// Add any other methods here
|
||||
@ -27,5 +27,7 @@ var variantClassName=(state.variant !== 'primary' && 'app-button-' + state.varia
|
||||
var sizeClassName=(state.size !== 'normal' && 'app-button-' + state.size)
|
||||
|
||||
<button class=['app-button', variantClassName, sizeClassName]>
|
||||
<span body-slot/>
|
||||
<span>
|
||||
<include(state.body)/>
|
||||
</span>
|
||||
</button>
|
||||
@ -3,7 +3,8 @@ module.exports = {
|
||||
onInput: function(input) {
|
||||
this.state = {
|
||||
size: input.size || 'normal',
|
||||
variant: input.variant || 'primary'
|
||||
variant: input.variant || 'primary',
|
||||
body: input.renderBody
|
||||
};
|
||||
},
|
||||
|
||||
@ -27,6 +28,6 @@ var sizeClassName=(state.size !== 'normal' && 'app-button-' + state.size)
|
||||
|
||||
<button class=['app-button', variantClassName, sizeClassName]>
|
||||
<span>
|
||||
<body-slot/>
|
||||
<include(state.body)/>
|
||||
</span>
|
||||
</button>
|
||||
@ -3,9 +3,9 @@ module.exports = {
|
||||
onInput: function(input) {
|
||||
this.state = {
|
||||
size: input.size || 'normal',
|
||||
variant: input.variant || 'primary'
|
||||
variant: input.variant || 'primary',
|
||||
body: input.renderBody
|
||||
};
|
||||
this.body = input.renderBody;
|
||||
},
|
||||
|
||||
// Add any other methods here
|
||||
@ -28,6 +28,6 @@ var sizeClassName=(state.size !== 'normal' && 'app-button-' + state.size)
|
||||
|
||||
<button class=['app-button', variantClassName, sizeClassName]>
|
||||
<span>
|
||||
<body-slot/>
|
||||
<include(state.body)/>
|
||||
</span>
|
||||
</button>
|
||||
@ -9,15 +9,13 @@ module.exports = function(helpers) {
|
||||
expect(buttonWidget.el.innerHTML).to.contain('Frank');
|
||||
expect(buttonWidget.el.className).to.equal('app-button app-button-small');
|
||||
|
||||
// Button widget will not rerender since it's state did not change and that means that the
|
||||
// button content will remain as 'John' instead of 'Frank'
|
||||
widget.setProps({ name: 'John '});
|
||||
widget.update();
|
||||
|
||||
expect(buttonWidget.el.innerHTML).to.contain('Frank');
|
||||
expect(buttonWidget.el.innerHTML).to.contain('John');
|
||||
|
||||
buttonWidget.setSize('large');
|
||||
buttonWidget.update();
|
||||
expect(buttonWidget.el.innerHTML).to.contain('Frank');
|
||||
expect(buttonWidget.el.innerHTML).to.contain('John');
|
||||
expect(buttonWidget.el.className).to.equal('app-button app-button-large');
|
||||
};
|
||||
@ -4,9 +4,9 @@ module.exports = {
|
||||
size: input.size || 'normal',
|
||||
variant: input.variant || 'primary',
|
||||
className: input['class'],
|
||||
attrs: input['*']
|
||||
attrs: input['*'],
|
||||
body: input.label || input.renderBody
|
||||
};
|
||||
this.body = input.label || input.renderBody;
|
||||
},
|
||||
getTemplateData: function(state, input) {
|
||||
var rootAttrs = {};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
onClick("handleClick")>
|
||||
<body-slot/>
|
||||
<include(state.body)/>
|
||||
</button>
|
||||
@ -4,13 +4,10 @@ module.exports = {
|
||||
size: input.size || 'normal',
|
||||
variant: input.variant || 'primary',
|
||||
className: input['class'],
|
||||
attrs: input['*']
|
||||
attrs: input['*'],
|
||||
body: input.label || input.renderBody
|
||||
};
|
||||
},
|
||||
|
||||
getInitialBody: function(input) {
|
||||
return input.label || input.renderBody;
|
||||
},
|
||||
getTemplateData: function(state, input) {
|
||||
var rootAttrs = {};
|
||||
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<button ${data.rootAttrs} onClick("handleClick")>
|
||||
<body-slot/>
|
||||
<include(state.body)/>
|
||||
</button>
|
||||
@ -4,13 +4,10 @@ module.exports = {
|
||||
size: input.size || 'normal',
|
||||
variant: input.variant || 'primary',
|
||||
className: input['class'],
|
||||
attrs: input['*']
|
||||
attrs: input['*'],
|
||||
body: input.label || input.renderBody
|
||||
};
|
||||
},
|
||||
|
||||
getInitialBody: function(input) {
|
||||
return input.label || input.renderBody;
|
||||
},
|
||||
getTemplateData: function(state, input) {
|
||||
var rootAttrs = {};
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
onClick("handleClick")>
|
||||
<body-slot/>
|
||||
<include(state.body)/>
|
||||
</button>
|
||||
@ -1,17 +1,12 @@
|
||||
module.exports = {
|
||||
|
||||
onInput: function(input) {
|
||||
var type = input.type || 'success';
|
||||
|
||||
this.state = {
|
||||
type: type
|
||||
type: input.type || 'success',
|
||||
body: input.message || input.renderBody
|
||||
};
|
||||
},
|
||||
|
||||
getInitialBody: function(input) {
|
||||
return input.message || input.renderBody;
|
||||
},
|
||||
|
||||
setType: function(newType) {
|
||||
this.setState('type', newType);
|
||||
}
|
||||
|
||||
@ -3,9 +3,9 @@ var className=('alert alert-'+type)
|
||||
|
||||
<div class=className role="alert">
|
||||
<div>
|
||||
<h1>ALERT! ${type} ${Date.now()}</h1>
|
||||
<h1>ALERT! ${type}</h1>
|
||||
<div>
|
||||
<body-slot/>
|
||||
<include(state.body)/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<button ${data.rootAttrs}
|
||||
onClick("handleClick")>
|
||||
<body-slot/>
|
||||
<include(data.body)/>
|
||||
</button>
|
||||
@ -1,7 +1,4 @@
|
||||
module.exports = {
|
||||
getInitialBody: function(input) {
|
||||
return input.label || input.renderBody;
|
||||
},
|
||||
getTemplateData: function(state, input) {
|
||||
var rootAttrs = {};
|
||||
|
||||
@ -37,7 +34,8 @@ module.exports = {
|
||||
|
||||
return {
|
||||
type: type,
|
||||
rootAttrs: rootAttrs
|
||||
rootAttrs: rootAttrs,
|
||||
body: input.label || input.renderBody
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -11,29 +11,31 @@ var SubscriptionTracker = require('listener-tracker');
|
||||
var inherit = require('raptor-util/inherit');
|
||||
var updateManager = require('./update-manager');
|
||||
var morphdom = require('morphdom');
|
||||
var widgetLookup = require('./lookup').widgets;
|
||||
var widgetLookup = require('./lookup').$__widgets;
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
var MORPHDOM_SKIP = false;
|
||||
|
||||
var WIDGET_SUBSCRIBE_TO_OPTIONS = null;
|
||||
var WIDGET_SUBSCRIBE_TO_OPTIONS;
|
||||
var NON_WIDGET_SUBSCRIBE_TO_OPTIONS = {
|
||||
addDestroyListener: false
|
||||
};
|
||||
|
||||
var emit = EventEmitter.prototype.emit;
|
||||
|
||||
var lifecycleEventMethods = {
|
||||
'beforeDestroy': 'onBeforeDestroy',
|
||||
'destroy': 'onDestroy',
|
||||
'beforeUpdate': 'onBeforeUpdate',
|
||||
'update': 'onUpdate',
|
||||
'mount': 'onMount',
|
||||
'render': 'onRender',
|
||||
'beforeInit': 'onBeforeInit',
|
||||
'afterInit': 'onAfterInit'
|
||||
};
|
||||
var lifecycleEventMethods = {};
|
||||
|
||||
['beforeDestroy',
|
||||
'destroy',
|
||||
'beforeUpdate',
|
||||
'update',
|
||||
'mount',
|
||||
'render',
|
||||
'beforeInit',
|
||||
'afterInit'].forEach(function(eventName) {
|
||||
lifecycleEventMethods[eventName] = 'on' + eventName.charAt(0).toUpperCase() + eventName.substring(1);
|
||||
});
|
||||
|
||||
function removeListener(eventListenerHandle) {
|
||||
eventListenerHandle();
|
||||
@ -72,10 +74,10 @@ function removeDOMEventListeners(widget) {
|
||||
}
|
||||
|
||||
function destroyWidgetForEl(el) {
|
||||
var widgetToDestroy = el.__widget;
|
||||
var widgetToDestroy = el._w;
|
||||
if (widgetToDestroy) {
|
||||
destroyWidgetHelper(widgetToDestroy);
|
||||
el.__widget = null;
|
||||
el._w = null;
|
||||
|
||||
while ((widgetToDestroy = widgetToDestroy.$__rootFor)) {
|
||||
widgetToDestroy.$__rootFor = null;
|
||||
@ -95,12 +97,12 @@ function destroyElRecursive(el) {
|
||||
}
|
||||
|
||||
function destroyWidgetHelper(widget) {
|
||||
if (widget.isDestroyed()) {
|
||||
if (widget.$__destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
emitLifecycleEvent(widget, 'beforeDestroy');
|
||||
widget.$__lifecycleState = 'destroyed';
|
||||
widget.$__destroyed = true;
|
||||
|
||||
widget.els = null;
|
||||
widget.el = null;
|
||||
@ -236,7 +238,7 @@ function Widget(id, document) {
|
||||
this.$__roots = null;
|
||||
this.$__subscriptions = null;
|
||||
this.$__domEventListenerHandles = null;
|
||||
this.$__lifecycleState = null;
|
||||
this.$__destroyed = false;
|
||||
this.$__customEvents = null;
|
||||
this.$__scope = null;
|
||||
this.$__updateQueued = false;
|
||||
@ -303,14 +305,13 @@ Widget.prototype = widgetProto = {
|
||||
return els;
|
||||
},
|
||||
getWidget: function(id, index) {
|
||||
var targetWidgetId = getElIdHelper(this, id, index);
|
||||
return widgetLookup[targetWidgetId];
|
||||
return widgetLookup[getElIdHelper(this, id, index)];
|
||||
},
|
||||
getWidgets: function(id) {
|
||||
var widgets = [];
|
||||
var i=0;
|
||||
while(true) {
|
||||
var widget = this.getWidget(id, i);
|
||||
var widget = widgetLookup[getElIdHelper(this, id, i)];
|
||||
if (!widget) {
|
||||
break;
|
||||
}
|
||||
@ -320,7 +321,7 @@ Widget.prototype = widgetProto = {
|
||||
return widgets;
|
||||
},
|
||||
destroy: function () {
|
||||
if (this.isDestroyed()) {
|
||||
if (this.$__destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -348,43 +349,47 @@ Widget.prototype = widgetProto = {
|
||||
destroyWidgetHelper(this);
|
||||
},
|
||||
isDestroyed: function () {
|
||||
return this.$__lifecycleState === 'destroyed';
|
||||
return this.$__destroyed;
|
||||
},
|
||||
get state() {
|
||||
return this.$__state;
|
||||
},
|
||||
set state(value) {
|
||||
if(!this.$__state && value) {
|
||||
this.$__state = new this.State(this, value);
|
||||
this.$__state = new this.$__State(this, value);
|
||||
} else {
|
||||
this.$__state.$__replace(value);
|
||||
}
|
||||
},
|
||||
setState: function(name, value) {
|
||||
var state = this.$__state;
|
||||
|
||||
if (typeof name === 'object') {
|
||||
// Merge in the new state with the old state
|
||||
var newState = name;
|
||||
for (var k in newState) {
|
||||
if (newState.hasOwnProperty(k)) {
|
||||
this.state.$__set(k, newState[k], true /* ensure:true */);
|
||||
state.$__set(k, newState[k], true /* ensure:true */);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.state.$__set(name, value, true /* ensure:true */);
|
||||
state.$__set(name, value, true /* ensure:true */);
|
||||
},
|
||||
|
||||
setStateDirty: function(name, value) {
|
||||
var state = this.$__state;
|
||||
|
||||
if (arguments.length === 1) {
|
||||
value = this.state[name];
|
||||
value = state[name];
|
||||
}
|
||||
|
||||
this.state.$__set(name, value, true /* ensure:true */, true /* forceDirty:true */);
|
||||
state.$__set(name, value, true /* ensure:true */, true /* forceDirty:true */);
|
||||
},
|
||||
|
||||
replaceState: function(newState) {
|
||||
this.state.$__replace(newState);
|
||||
this.$__state.$__replace(newState);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -418,13 +423,15 @@ Widget.prototype = widgetProto = {
|
||||
},
|
||||
|
||||
update: function() {
|
||||
if (this.isDestroyed()) {
|
||||
return;
|
||||
if (this.$__destroyed) {
|
||||
return;
|
||||
}
|
||||
|
||||
var newProps = this.$__newProps;
|
||||
|
||||
if (this.shouldUpdate(newProps, this.state) === false) {
|
||||
var state = this.$__state;
|
||||
|
||||
if (this.shouldUpdate(newProps, state) === false) {
|
||||
resetWidget(this);
|
||||
return;
|
||||
}
|
||||
@ -435,7 +442,7 @@ Widget.prototype = widgetProto = {
|
||||
return;
|
||||
}
|
||||
|
||||
var state = this.$__state;
|
||||
|
||||
|
||||
if (!state.$__dirty) {
|
||||
// Don't even bother trying to update this widget since it is
|
||||
@ -471,7 +478,7 @@ Widget.prototype = widgetProto = {
|
||||
return this.$__state.$__dirty;
|
||||
},
|
||||
|
||||
_reset: function(shouldRemoveDOMEventListeners) {
|
||||
$__reset: function(shouldRemoveDOMEventListeners) {
|
||||
resetWidget(this);
|
||||
|
||||
if (shouldRemoveDOMEventListeners) {
|
||||
@ -499,7 +506,6 @@ Widget.prototype = widgetProto = {
|
||||
}
|
||||
|
||||
var renderer = self.renderer;
|
||||
self.$__lifecycleState = 'rerender';
|
||||
|
||||
var state = self.$__state;
|
||||
|
||||
@ -547,15 +553,6 @@ Widget.prototype = widgetProto = {
|
||||
var preserved = widgetsContext.$__preserved[id];
|
||||
|
||||
if (preserved && !preserved.$__bodyOnly) {
|
||||
if (preserved.$__bodyEl) {
|
||||
morphdom(preserved.$__bodyEl, toEl, {
|
||||
childrenOnly: true,
|
||||
onNodeDiscarded: onNodeDiscarded,
|
||||
onBeforeElUpdated: onBeforeElUpdated,
|
||||
onBeforeElChildrenUpdated: onBeforeElChildrenUpdated
|
||||
});
|
||||
}
|
||||
|
||||
// Don't morph elements that are associated with widgets that are being
|
||||
// reused or elements that are being preserved. For widgets being reused,
|
||||
// the morphing will take place when the reused widget updates.
|
||||
@ -607,8 +604,6 @@ Widget.prototype = widgetProto = {
|
||||
|
||||
result.afterInsert(doc);
|
||||
|
||||
self.$__lifecycleState = null;
|
||||
|
||||
if (!props) {
|
||||
// We have re-rendered with the new state so our state
|
||||
// is no longer dirty. Before updating a widget
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
var repeatedId = require('./repeated-id');
|
||||
var nextRepeatedId = require('./nextRepeatedId');
|
||||
var repeatedRegExp = /\[\]$/;
|
||||
var uniqueId = require('./uniqueId');
|
||||
|
||||
@ -19,13 +19,12 @@ function WidgetDef(id, out, widgetStack, widgetStackLen) {
|
||||
this.$__state = // Widget state object (may be null)
|
||||
this.$__scope = // The ID of the widget that this widget is scoped within
|
||||
this.$__customEvents = // An array containing information about custom events
|
||||
this.$__bodyElId = // The ID for the default body element (if any any)
|
||||
this.$__roots = // IDs of root elements if there are multiple root elements
|
||||
this.b =
|
||||
this.$__existingWidget =
|
||||
this.$__children = // An array of nested WidgetDef instances
|
||||
this.$__domEvents = // An array of DOM events that need to be added (in sets of three)
|
||||
this.widget = // This is used by RenderResult to reference the associated widget instance after creation
|
||||
this.$__widget = // This is used by RenderResult to reference the associated widget instance after creation
|
||||
null;
|
||||
|
||||
this.$__nextIdIndex = 0; // The unique integer to use for the next scoped ID
|
||||
@ -70,7 +69,7 @@ WidgetDef.prototype = {
|
||||
return this.id;
|
||||
} else {
|
||||
if (typeof nestedId === 'string' && repeatedRegExp.test(nestedId)) {
|
||||
return repeatedId.$__nextId(this.$__out, this.id, nestedId);
|
||||
return nextRepeatedId(this.$__out, this.id, nestedId);
|
||||
} else {
|
||||
return this.id + '-' + nestedId;
|
||||
}
|
||||
@ -112,7 +111,6 @@ WidgetDef.prototype = {
|
||||
p: customEvents && this.$__scope, // Only serialize scope if we need to attach custom events
|
||||
e: this.$__domEvents,
|
||||
ce: this.$__customEvents,
|
||||
b: this.$__bodyElId,
|
||||
c: this.$__config
|
||||
};
|
||||
|
||||
@ -139,7 +137,6 @@ WidgetDef.$__deserialize = function(o, types) {
|
||||
$__scope: extra.p,
|
||||
$__domEvents: extra.e,
|
||||
$__customEvents: extra.ce,
|
||||
$__bodyElId: extra.b,
|
||||
$__config: extra.c
|
||||
};
|
||||
};
|
||||
|
||||
@ -52,12 +52,12 @@ WidgetsContext.prototype = {
|
||||
var parent = widgetStack[widgetStack.length - 1];
|
||||
return parent.$__nextId();
|
||||
},
|
||||
$__preserveDOMNode: function(existingEl, bodyOnly, bodyEl) {
|
||||
$__preserveDOMNode: function(elId, bodyOnly) {
|
||||
var preserved = this.$__preserved ;
|
||||
if (preserved === EMPTY_OBJECT) {
|
||||
preserved = this.$__preserved = {};
|
||||
}
|
||||
preserved[existingEl.id] = { $__bodyOnly: bodyOnly, $__bodyEl: bodyEl };
|
||||
preserved[elId] = { $__bodyOnly: bodyOnly };
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ module.exports = function defineWidget(def, renderer) {
|
||||
// we he have set up the prototype chain using the inherit function
|
||||
proto = Widget.prototype = WidgetClass.prototype;
|
||||
|
||||
proto.initWidget = WidgetClass;
|
||||
proto.$__initWidget = WidgetClass;
|
||||
|
||||
proto.constructor = def.constructor = Widget;
|
||||
|
||||
@ -51,9 +51,10 @@ module.exports = function defineWidget(def, renderer) {
|
||||
// a widget so that we can short-circuit this work later
|
||||
Widget.$__isWidget = true;
|
||||
|
||||
// Set widget state constructor
|
||||
proto.State = function State() { BaseState.apply(this, arguments); };
|
||||
inherit(proto.State, BaseState);
|
||||
function State() { BaseState.apply(this, arguments); }
|
||||
inherit(State, BaseState);
|
||||
proto.$__State = State;
|
||||
|
||||
|
||||
if (!renderer) {
|
||||
renderer = WidgetClass.renderer || WidgetClass.prototype.renderer;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
var updateManager = require('./update-manager');
|
||||
var widgetLookup = require('./lookup').widgets;
|
||||
var widgetLookup = require('./lookup').$__widgets;
|
||||
var warp10Parse = require('warp10/parse');
|
||||
|
||||
function getObjectAttribute(el, attrName) {
|
||||
|
||||
@ -8,7 +8,7 @@ function getWidgetForEl(el, doc) {
|
||||
if (el) {
|
||||
var node = typeof el === 'string' ? (doc || window.document).getElementById(el) : el;
|
||||
if (node) {
|
||||
var widget = node.__widget;
|
||||
var widget = node._w;
|
||||
|
||||
while(widget) {
|
||||
var rootFor = widget.$__rootFor;
|
||||
|
||||
@ -4,8 +4,9 @@ var eventDelegation = require('./event-delegation');
|
||||
var win = window;
|
||||
var defaultDocument = document;
|
||||
var events = require('../runtime/events');
|
||||
var widgetLookup = require('./lookup').widgets;
|
||||
var widgetLookup = require('./lookup').$__widgets;
|
||||
var WidgetDef = require('./WidgetDef');
|
||||
var extend = require('raptor-util/extend');
|
||||
|
||||
var registry; // We initialize this later to avoid issues with circular dependencies
|
||||
|
||||
@ -37,24 +38,6 @@ function addDOMEventListeners(widget, el, eventType, targetMethodName, extraArgs
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
function getNestedEl(widget, nestedId, document) {
|
||||
if (nestedId == null) {
|
||||
return null;
|
||||
|
||||
}
|
||||
if (nestedId === '') {
|
||||
return widget.getEl();
|
||||
}
|
||||
|
||||
if (typeof nestedId === 'string') {
|
||||
if (nestedId.charAt(0) === '#') {
|
||||
return document.getElementById(nestedId.substring(1));
|
||||
}
|
||||
}
|
||||
|
||||
return widget.getEl(nestedId);
|
||||
}
|
||||
|
||||
function initWidget(widgetDef, doc) {
|
||||
var type = widgetDef.$__type;
|
||||
var id = widgetDef.id;
|
||||
@ -63,7 +46,6 @@ function initWidget(widgetDef, doc) {
|
||||
var scope = widgetDef.$__scope;
|
||||
var domEvents = widgetDef.$__domEvents;
|
||||
var customEvents = widgetDef.$__customEvents;
|
||||
var bodyElId = widgetDef.$__bodyElId;
|
||||
var existingWidget = widgetDef.$__existingWidget;
|
||||
|
||||
var el;
|
||||
@ -83,10 +65,10 @@ function initWidget(widgetDef, doc) {
|
||||
}
|
||||
|
||||
if (existingWidget) {
|
||||
existingWidget._reset(true /* shouldRemoveDOMEventListeners */);
|
||||
existingWidget.$__reset(true /* shouldRemoveDOMEventListeners */);
|
||||
widget = existingWidget;
|
||||
} else {
|
||||
widget = registry.createWidget(type, id, doc);
|
||||
widget = registry.$__createWidget(type, id, doc);
|
||||
}
|
||||
|
||||
var els;
|
||||
@ -110,7 +92,7 @@ function initWidget(widgetDef, doc) {
|
||||
} else {
|
||||
var rootEl = doc.getElementById(nestedId);
|
||||
if (rootEl) {
|
||||
rootEl.__widget = widget;
|
||||
rootEl._w = widget;
|
||||
els.push(rootEl);
|
||||
}
|
||||
}
|
||||
@ -119,7 +101,7 @@ function initWidget(widgetDef, doc) {
|
||||
el = els[0];
|
||||
} else {
|
||||
el = doc.getElementById(id);
|
||||
el.__widget = widget;
|
||||
el._w = widget;
|
||||
els = [el];
|
||||
}
|
||||
|
||||
@ -135,7 +117,6 @@ function initWidget(widgetDef, doc) {
|
||||
widget.el = el;
|
||||
widget.els = els;
|
||||
widget.$__rootWidgets = rootWidgets;
|
||||
widget.$__bodyEl = getNestedEl(widget, bodyElId, doc);
|
||||
|
||||
if (domEvents) {
|
||||
var eventListenerHandles = [];
|
||||
@ -187,8 +168,8 @@ function initWidget(widgetDef, doc) {
|
||||
events.emit('initWidget', initEventArgs);
|
||||
|
||||
widget.$__emitLifecycleEvent('beforeInit', initEventArgs);
|
||||
copyConfigToWidget(widget, config);
|
||||
widget.initWidget(config);
|
||||
extend(widget, config);
|
||||
widget.$__initWidget(config);
|
||||
widget.$__emitLifecycleEvent('afterInit', initEventArgs);
|
||||
|
||||
widget.$__emitLifecycleEvent('render', { firstRender: true });
|
||||
@ -199,12 +180,6 @@ function initWidget(widgetDef, doc) {
|
||||
return widget;
|
||||
}
|
||||
|
||||
function copyConfigToWidget(widget, config) {
|
||||
for(var key in config) {
|
||||
widget[key] = config[key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to initialized widgets associated with UI components
|
||||
* rendered in the browser. While rendering UI components a "widgets context"
|
||||
@ -234,7 +209,7 @@ function initClientRendered(widgetDefs, doc) {
|
||||
widgetDef,
|
||||
doc);
|
||||
|
||||
widgetDef.widget = widget;
|
||||
widgetDef.$__widget = widget;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
'use strict';
|
||||
module.exports = function load(typeName) {
|
||||
throw new Error('Unable to load: ' + typeName);
|
||||
throw new Error('Not found: ' + typeName);
|
||||
};
|
||||
@ -1,3 +1,3 @@
|
||||
var widgets = {};
|
||||
|
||||
exports.widgets = widgets;
|
||||
exports.$__widgets = widgets;
|
||||
15
widgets/nextRepeatedId.js
Normal file
15
widgets/nextRepeatedId.js
Normal file
@ -0,0 +1,15 @@
|
||||
var REPEATED_ID_KEY = '$rep';
|
||||
|
||||
module.exports = function nextRepeatedId(out, parentId, id) {
|
||||
var nextIdLookup = out.global[REPEATED_ID_KEY] || (out.global[REPEATED_ID_KEY] = {});
|
||||
|
||||
var indexLookupKey = parentId + '-' + id;
|
||||
var currentIndex = nextIdLookup[indexLookupKey];
|
||||
if (currentIndex == null) {
|
||||
currentIndex = nextIdLookup[indexLookupKey] = 0;
|
||||
} else {
|
||||
currentIndex = ++nextIdLookup[indexLookupKey];
|
||||
}
|
||||
|
||||
return indexLookupKey.slice(0, -2) + '[' + currentIndex + ']';
|
||||
};
|
||||
@ -86,8 +86,7 @@ function createWidget(typeName, id, document) {
|
||||
}
|
||||
|
||||
exports.$__register = register;
|
||||
exports.createWidget = createWidget;
|
||||
exports.load = load;
|
||||
exports.$__createWidget = createWidget;
|
||||
|
||||
defineWidget = require('./defineWidget');
|
||||
defineRenderer = require('./defineRenderer');
|
||||
@ -1,6 +1,5 @@
|
||||
var widgetLookup = require('./lookup').widgets;
|
||||
var includeTag = require('./taglib/include-tag');
|
||||
var repeatedId = require('./repeated-id');
|
||||
var widgetLookup = require('./lookup').$__widgets;
|
||||
var nextRepeatedId = require('./nextRepeatedId');
|
||||
var getRootEls = require('./getRootEls');
|
||||
var repeatedRegExp = /\[\]$/;
|
||||
var WidgetsContext = require('./WidgetsContext');
|
||||
@ -17,7 +16,7 @@ function resolveWidgetRef(out, ref, scope) {
|
||||
var resolvedId;
|
||||
|
||||
if (repeatedRegExp.test(ref)) {
|
||||
resolvedId = repeatedId.$__nextId(out, scope, ref);
|
||||
resolvedId = nextRepeatedId(out, scope, ref);
|
||||
} else {
|
||||
resolvedId = scope + '-' + ref;
|
||||
}
|
||||
@ -26,46 +25,23 @@ function resolveWidgetRef(out, ref, scope) {
|
||||
}
|
||||
}
|
||||
|
||||
function preserveWidgetEls(existingWidget, out, widgetsContext, widgetBody) {
|
||||
function preserveWidgetEls(existingWidget, out, widgetsContext) {
|
||||
var rootEls = getRootEls(existingWidget, {});
|
||||
var rootElIds = Object.keys(rootEls);
|
||||
|
||||
var bodyEl;
|
||||
|
||||
if (widgetBody && (bodyEl = existingWidget.$__bodyEl)) {
|
||||
if (rootElIds.length > 1) {
|
||||
// If there are multiple roots then we don't know which root el
|
||||
// contains the body element so we will just need to rerender the
|
||||
// UI component
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (var elId in rootEls) {
|
||||
var el = rootEls[elId];
|
||||
var tagName = el.tagName;
|
||||
|
||||
// We put a placeholder element in the output stream to ensure that the existing
|
||||
// DOM node is matched up correctly when using morphdom.
|
||||
out.element(el.tagName, { id: elId });
|
||||
|
||||
out.beginElement(tagName, { id: elId });
|
||||
|
||||
if (bodyEl) {
|
||||
includeTag({
|
||||
_target: widgetBody
|
||||
}, out);
|
||||
}
|
||||
|
||||
out.endElement();
|
||||
|
||||
widgetsContext.$__preserveDOMNode(el, false, bodyEl); // Mark the element as being preserved (for morphdom)
|
||||
widgetsContext.$__preserveDOMNode(elId); // Mark the element as being preserved (for morphdom)
|
||||
}
|
||||
|
||||
existingWidget._reset(); // The widget is no longer dirty so reset internal flags
|
||||
existingWidget.$__reset(); // The widget is no longer dirty so reset internal flags
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function handleBeginAsync(event) {
|
||||
var parentOut = event.parentOut;
|
||||
var asyncOut = event.out;
|
||||
@ -109,7 +85,6 @@ module.exports = function createRendererFunc(templateRenderFunc, widgetProps, re
|
||||
}
|
||||
|
||||
var typeName = widgetProps.type;
|
||||
var bodyElId = widgetProps.body;
|
||||
var roots = widgetProps.roots;
|
||||
var assignedId = widgetProps.id;
|
||||
|
||||
@ -159,10 +134,8 @@ module.exports = function createRendererFunc(templateRenderFunc, widgetProps, re
|
||||
var lightweightWidget = Object.create(renderingLogic);
|
||||
lightweightWidget.onInput(input);
|
||||
widgetState = lightweightWidget.state;
|
||||
widgetBody = lightweightWidget.body;
|
||||
widgetConfig = lightweightWidget;
|
||||
delete widgetConfig.state;
|
||||
delete widgetConfig.body;
|
||||
} else {
|
||||
if (getWidgetConfig) {
|
||||
// If getWidgetConfig() was implemented then use that to
|
||||
@ -256,22 +229,14 @@ module.exports = function createRendererFunc(templateRenderFunc, widgetProps, re
|
||||
// rerender the widget if that is not necessary. If the widget is a stateful
|
||||
// widget then we update the existing widget with the new state.
|
||||
if (widgetState) {
|
||||
if (existingWidget.$__replaceState(widgetState)) {
|
||||
// If _processUpdateHandlers() returns true then that means
|
||||
// that the widget is now up-to-date and we can skip rerendering it, but only if we
|
||||
// are able to preserve the existing widget els
|
||||
if (preserveWidgetEls(existingWidget, out, widgetsContext, widgetBody)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
existingWidget.$__replaceState(widgetState);
|
||||
}
|
||||
|
||||
// If the widget is not dirty (no state changes) and shouldUpdate() returns false
|
||||
// then skip rerendering the widget.
|
||||
if (!existingWidget.$__dirty && !existingWidget.shouldUpdate(input, widgetState)) {
|
||||
if (preserveWidgetEls(existingWidget, out, widgetsContext, widgetBody)) {
|
||||
return;
|
||||
}
|
||||
if (!widgetBody && (!existingWidget.$__isDirty || !existingWidget.shouldUpdate(input, widgetState))) {
|
||||
preserveWidgetEls(existingWidget, out, widgetsContext);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,7 +258,6 @@ module.exports = function createRendererFunc(templateRenderFunc, widgetProps, re
|
||||
widgetDef.$__customEvents = customEvents;
|
||||
widgetDef.$__scope = scope;
|
||||
widgetDef.$__existingWidget = existingWidget;
|
||||
widgetDef.$__bodyElId = bodyElId;
|
||||
widgetDef.$__roots = roots;
|
||||
widgetDef.b = widgetBody;
|
||||
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
var REPEATED_ID_KEY = '$rep';
|
||||
|
||||
function RepeatedId() {
|
||||
this.$__nextIdLookup = {};
|
||||
}
|
||||
|
||||
RepeatedId.prototype = {
|
||||
$__nextId: function(parentId, id) {
|
||||
var indexLookupKey = parentId + '-' + id;
|
||||
var currentIndex = this.$__nextIdLookup[indexLookupKey];
|
||||
if (currentIndex == null) {
|
||||
currentIndex = this.$__nextIdLookup[indexLookupKey] = 0;
|
||||
} else {
|
||||
currentIndex = ++this.$__nextIdLookup[indexLookupKey];
|
||||
}
|
||||
|
||||
return indexLookupKey.slice(0, -2) + '[' + currentIndex + ']';
|
||||
}
|
||||
};
|
||||
|
||||
exports.$__nextId = function(out, parentId, id) {
|
||||
var repeatedId = out.global[REPEATED_ID_KEY];
|
||||
if (repeatedId == null) {
|
||||
repeatedId = out.global[REPEATED_ID_KEY] = new RepeatedId();
|
||||
}
|
||||
|
||||
return repeatedId.$__nextId(parentId, id);
|
||||
};
|
||||
@ -1,41 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var includeTagForWidgets = require.resolve('../include-tag');
|
||||
|
||||
module.exports = function(bodySlotNode) {
|
||||
if (!this.hasBoundWidgetForTemplate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var context = this.context;
|
||||
var builder = this.builder;
|
||||
|
||||
var parentNode = bodySlotNode.parentNode;
|
||||
|
||||
parentNode._normalizeChildTextNodes(context);
|
||||
|
||||
if (parentNode.childCount !== 1) {
|
||||
throw new Error('TBD');
|
||||
}
|
||||
|
||||
let parentTransformHelper = this.getTransformHelper(parentNode);
|
||||
|
||||
let includeNode = context.createNodeForEl('include');
|
||||
includeNode.data.bodySlot = true;
|
||||
includeNode.addProp('_target', builder.memberExpression(builder.identifier('widget'), builder.identifier('b')));
|
||||
includeNode.addProp('_elId', parentTransformHelper.getIdExpression());
|
||||
includeNode.addProp('_arg', builder.identifier('widget'));
|
||||
|
||||
parentTransformHelper.assignWidgetId(false /* not repeated */);
|
||||
var widgetProps = this.getWidgetProps();
|
||||
widgetProps.body = parentTransformHelper.getNestedIdExpression();
|
||||
|
||||
includeNode.setRendererPath(includeTagForWidgets);
|
||||
|
||||
// includeNode.onBeforeGenerateCode(function() {
|
||||
// includeNode.addProp('_elId', parentTransformHelper.getIdExpression());
|
||||
// includeNode.addProp('_arg', builder.identifier('widget'));
|
||||
// });
|
||||
|
||||
bodySlotNode.replaceWith(includeNode);
|
||||
};
|
||||
@ -142,7 +142,6 @@ class TransformHelper {
|
||||
}
|
||||
|
||||
TransformHelper.prototype.assignWidgetId = require('./assignWidgetId');
|
||||
TransformHelper.prototype.handleBodySlotNode = require('./handleBodySlotNode');
|
||||
TransformHelper.prototype.handleRootNodes = require('./handleRootNodes');
|
||||
TransformHelper.prototype.handleIncludeNode = require('./handleIncludeNode');
|
||||
TransformHelper.prototype.handleWidgetEvents = require('./handleWidgetEvents');
|
||||
|
||||
@ -17,7 +17,7 @@ module.exports = function include(input, out) {
|
||||
var existingEl = document.getElementById(elId);
|
||||
if (existingEl) {
|
||||
var widgetsContext = WidgetsContext.$__getWidgetsContext(out);
|
||||
widgetsContext.$__preserveDOMNode(existingEl, true /* body only */);
|
||||
widgetsContext.$__preserveDOMNode(elId, true /* body only */);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -96,9 +96,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"@body-slot": {
|
||||
"preserve-name": true
|
||||
},
|
||||
"@w-body": {
|
||||
"preserve-name": true,
|
||||
"autocomplete": []
|
||||
|
||||
@ -27,11 +27,10 @@ module.exports = function render(input, out) {
|
||||
// then that means that we have need to render a placeholder to
|
||||
// mark the target location. We can then replace the placeholder
|
||||
// node with the existing DOM node
|
||||
out.beginElement(tagName, { id: id });
|
||||
out.endElement();
|
||||
out.element(tagName, { id: id });
|
||||
}
|
||||
|
||||
widgetsContext.$__preserveDOMNode(existingEl, bodyOnly);
|
||||
widgetsContext.$__preserveDOMNode(id, bodyOnly);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,23 +10,22 @@ module.exports = function transform(el, context) {
|
||||
}
|
||||
|
||||
if (el.hasAttribute('w-body')) {
|
||||
let builder = context.builder;
|
||||
let bodyValue = el.getAttributeValue('w-body');
|
||||
el.removeAttribute('w-body');
|
||||
|
||||
if (bodyValue) {
|
||||
let includeNode = context.createNodeForEl('include');
|
||||
includeNode.addProp('_target', bodyValue);
|
||||
el.appendChild(includeNode);
|
||||
} else {
|
||||
el.setAttributeValue('body-slot', null);
|
||||
let includeNode = context.createNodeForEl('include');
|
||||
|
||||
if (!bodyValue) {
|
||||
bodyValue = builder.memberExpression(
|
||||
builder.identifier('widget'),
|
||||
builder.identifier('b'));
|
||||
|
||||
includeNode.data.bodySlot = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (el.hasAttribute('body-slot')) {
|
||||
el.removeAttribute('body-slot');
|
||||
|
||||
let bodySlotNode = context.createNodeForEl('body-slot');
|
||||
el.appendChild(bodySlotNode);
|
||||
includeNode.addProp('_target', bodyValue);
|
||||
el.appendChild(includeNode);
|
||||
}
|
||||
|
||||
if (el.tagName === 'widget-types') {
|
||||
@ -35,9 +34,6 @@ module.exports = function transform(el, context) {
|
||||
transformHelper.handleIncludeNode(el);
|
||||
transformHelper.getWidgetArgs().compile(transformHelper);
|
||||
return;
|
||||
} else if (el.tagName === 'body-slot') {
|
||||
transformHelper.handleBodySlotNode(el);
|
||||
return;
|
||||
}
|
||||
|
||||
if (el.hasAttribute('w-el-id')) {
|
||||
|
||||
@ -1,20 +1,15 @@
|
||||
function IdProvider(out) {
|
||||
var global = this.global = out.global;
|
||||
this.$__prefix = global.widgetIdPrefix || 'w';
|
||||
var KEY = Symbol();
|
||||
|
||||
if (global._nextWidgetId == null) {
|
||||
global._nextWidgetId = 0;
|
||||
}
|
||||
function UniqueId(out) {
|
||||
this.prefix = out.global.widgetIdPrefix || 'w';
|
||||
this.nextId = 0;
|
||||
}
|
||||
|
||||
IdProvider.prototype.$__nextId = function() {
|
||||
return this.$__prefix + (this.global._nextWidgetId++);
|
||||
};
|
||||
|
||||
module.exports = function (out) {
|
||||
var global = out.global;
|
||||
var idProvider = global._widgetIdProvider ||
|
||||
(global._widgetIdProvider = new IdProvider(out));
|
||||
|
||||
return idProvider.$__nextId();
|
||||
var idProvider = global[KEY] ||
|
||||
(global[KEY] = new UniqueId(out));
|
||||
|
||||
return idProvider.prefix + (idProvider.nextId++);
|
||||
};
|
||||
@ -32,7 +32,6 @@ if (!setImmediate) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function notifyAfterUpdateListeners() {
|
||||
var len = queuedListeners.length;
|
||||
if (len) {
|
||||
@ -102,7 +101,7 @@ function batchUpdate(func) {
|
||||
var isOuter = batchStack.length === 0;
|
||||
|
||||
var batch = {
|
||||
queue: null
|
||||
$__queue: null
|
||||
};
|
||||
|
||||
batchStack.push(batch);
|
||||
@ -113,8 +112,8 @@ function batchUpdate(func) {
|
||||
try {
|
||||
// Update all of the widgets that where queued up
|
||||
// in this batch (if any)
|
||||
if (batch.queue) {
|
||||
updateWidgets(batch.queue);
|
||||
if (batch.$__queue) {
|
||||
updateWidgets(batch.$__queue);
|
||||
}
|
||||
} finally {
|
||||
// Now that we have completed the update of all the widgets
|
||||
@ -154,10 +153,10 @@ function queueWidgetUpdate(widget) {
|
||||
// We default the batch queue to null to avoid creating an Array instance
|
||||
// unnecessarily. If it is null then we create a new Array, otherwise
|
||||
// we push it onto the existing Array queue
|
||||
if (batch.queue) {
|
||||
batch.queue.push(widget);
|
||||
if (batch.$__queue) {
|
||||
batch.$__queue.push(widget);
|
||||
} else {
|
||||
batch.queue = [widget];
|
||||
batch.$__queue = [widget];
|
||||
}
|
||||
} else {
|
||||
// We are not within a batched update. We need to schedule a batch update
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user