mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] owl: update to v1.0.5
This commit is contained in:
@@ -213,8 +213,13 @@
|
|||||||
function handleEvent(event, vnode) {
|
function handleEvent(event, vnode) {
|
||||||
var name = event.type, on = vnode.data.on;
|
var name = event.type, on = vnode.data.on;
|
||||||
// call event handler(s) if exists
|
// call event handler(s) if exists
|
||||||
if (on && on[name]) {
|
if (on) {
|
||||||
invokeHandler(on[name], vnode, event);
|
if (on[name]) {
|
||||||
|
invokeHandler(on[name], vnode, event);
|
||||||
|
}
|
||||||
|
else if (on["!" + name]) {
|
||||||
|
invokeHandler(on["!" + name], vnode, event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function createListener() {
|
function createListener() {
|
||||||
@@ -234,14 +239,18 @@
|
|||||||
if (!on) {
|
if (!on) {
|
||||||
for (name in oldOn) {
|
for (name in oldOn) {
|
||||||
// remove listener if element was changed or existing listeners removed
|
// remove listener if element was changed or existing listeners removed
|
||||||
oldElm.removeEventListener(name, oldListener, false);
|
const capture = name.charAt(0) === "!";
|
||||||
|
name = capture ? name.slice(1) : name;
|
||||||
|
oldElm.removeEventListener(name, oldListener, capture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (name in oldOn) {
|
for (name in oldOn) {
|
||||||
// remove listener if existing listener removed
|
// remove listener if existing listener removed
|
||||||
if (!on[name]) {
|
if (!on[name]) {
|
||||||
oldElm.removeEventListener(name, oldListener, false);
|
const capture = name.charAt(0) === "!";
|
||||||
|
name = capture ? name.slice(1) : name;
|
||||||
|
oldElm.removeEventListener(name, oldListener, capture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,14 +265,18 @@
|
|||||||
if (!oldOn) {
|
if (!oldOn) {
|
||||||
for (name in on) {
|
for (name in on) {
|
||||||
// add listener if element was changed or new listeners added
|
// add listener if element was changed or new listeners added
|
||||||
elm.addEventListener(name, listener, false);
|
const capture = name.charAt(0) === "!";
|
||||||
|
name = capture ? name.slice(1) : name;
|
||||||
|
elm.addEventListener(name, listener, capture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (name in on) {
|
for (name in on) {
|
||||||
// add listener if new listener added
|
// add listener if new listener added
|
||||||
if (!oldOn[name]) {
|
if (!oldOn[name]) {
|
||||||
elm.addEventListener(name, listener, false);
|
const capture = name.charAt(0) === "!";
|
||||||
|
name = capture ? name.slice(1) : name;
|
||||||
|
elm.addEventListener(name, listener, capture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1428,6 +1441,9 @@
|
|||||||
}
|
}
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
function escapeQuotes(str) {
|
||||||
|
return str.replace(/\'/g, "\\'");
|
||||||
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// QWeb rendering engine
|
// QWeb rendering engine
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -1543,10 +1559,11 @@
|
|||||||
}) > 1) {
|
}) > 1) {
|
||||||
throw new Error("Only one conditional branching directive is allowed per node");
|
throw new Error("Only one conditional branching directive is allowed per node");
|
||||||
}
|
}
|
||||||
// All text nodes between branch nodes are removed
|
// All text (with only spaces) and comment nodes (nodeType 8) between
|
||||||
|
// branch nodes are removed
|
||||||
let textNode;
|
let textNode;
|
||||||
while ((textNode = node.previousSibling) !== prevElem) {
|
while ((textNode = node.previousSibling) !== prevElem) {
|
||||||
if (textNode.nodeValue.trim().length) {
|
if (textNode.nodeValue.trim().length && textNode.nodeType !== 8) {
|
||||||
throw new Error("text is not allowed between branching directives");
|
throw new Error("text is not allowed between branching directives");
|
||||||
}
|
}
|
||||||
textNode.remove();
|
textNode.remove();
|
||||||
@@ -1870,14 +1887,14 @@
|
|||||||
if ((value = value.trim())) {
|
if ((value = value.trim())) {
|
||||||
let classDef = value
|
let classDef = value
|
||||||
.split(/\s+/)
|
.split(/\s+/)
|
||||||
.map(a => `'${a}':true`)
|
.map(a => `'${escapeQuotes(a)}':true`)
|
||||||
.join(",");
|
.join(",");
|
||||||
classObj = `_${ctx.generateID()}`;
|
classObj = `_${ctx.generateID()}`;
|
||||||
ctx.addLine(`let ${classObj} = {${classDef}};`);
|
ctx.addLine(`let ${classObj} = {${classDef}};`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ctx.addLine(`let _${attID} = '${value}';`);
|
ctx.addLine(`let _${attID} = '${escapeQuotes(value)}';`);
|
||||||
if (!name.match(/^[a-zA-Z]+$/)) {
|
if (!name.match(/^[a-zA-Z]+$/)) {
|
||||||
// attribute contains 'non letters' => we want to quote it
|
// attribute contains 'non letters' => we want to quote it
|
||||||
name = '"' + name + '"';
|
name = '"' + name + '"';
|
||||||
@@ -2406,7 +2423,10 @@
|
|||||||
};
|
};
|
||||||
const FNAMEREGEXP = /^[$A-Z_][0-9A-Z_$]*$/i;
|
const FNAMEREGEXP = /^[$A-Z_][0-9A-Z_$]*$/i;
|
||||||
function makeHandlerCode(ctx, fullName, value, putInCache, modcodes = MODS_CODE) {
|
function makeHandlerCode(ctx, fullName, value, putInCache, modcodes = MODS_CODE) {
|
||||||
const [event, ...mods] = fullName.slice(5).split(".");
|
let [event, ...mods] = fullName.slice(5).split(".");
|
||||||
|
if (mods.includes("capture")) {
|
||||||
|
event = "!" + event;
|
||||||
|
}
|
||||||
if (!event) {
|
if (!event) {
|
||||||
throw new Error("Missing event name with t-on directive");
|
throw new Error("Missing event name with t-on directive");
|
||||||
}
|
}
|
||||||
@@ -2533,6 +2553,12 @@
|
|||||||
return Number(s.slice(0, -1).replace(",", ".")) * 1000;
|
return Number(s.slice(0, -1).replace(",", ".")) * 1000;
|
||||||
}
|
}
|
||||||
function whenTransitionEnd(elm, cb) {
|
function whenTransitionEnd(elm, cb) {
|
||||||
|
if (!elm.parentNode) {
|
||||||
|
// if we get here, this means that the element was removed for some other
|
||||||
|
// reasons, and in that case, we don't want to work on animation since nothing
|
||||||
|
// will be displayed anyway.
|
||||||
|
return;
|
||||||
|
}
|
||||||
const styles = window.getComputedStyle(elm);
|
const styles = window.getComputedStyle(elm);
|
||||||
const delays = (styles.transitionDelay || "").split(", ");
|
const delays = (styles.transitionDelay || "").split(", ");
|
||||||
const durations = (styles.transitionDuration || "").split(", ");
|
const durations = (styles.transitionDuration || "").split(", ");
|
||||||
@@ -2715,6 +2741,27 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
QWeb.utils.assignHooks = function assignHooks(dataObj, hooks) {
|
||||||
|
if ("hook" in dataObj) {
|
||||||
|
const hookObject = dataObj.hook;
|
||||||
|
for (let name in hooks) {
|
||||||
|
const current = hookObject[name];
|
||||||
|
const fn = hooks[name];
|
||||||
|
if (current) {
|
||||||
|
hookObject[name] = (...args) => {
|
||||||
|
current(...args);
|
||||||
|
fn(...args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hookObject[name] = fn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dataObj.hook = hooks;
|
||||||
|
}
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* The t-component directive is certainly a complicated and hard to maintain piece
|
* The t-component directive is certainly a complicated and hard to maintain piece
|
||||||
* of code. To help you, fellow developer, if you have to maintain it, I offer
|
* of code. To help you, fellow developer, if you have to maintain it, I offer
|
||||||
@@ -2969,13 +3016,18 @@
|
|||||||
}
|
}
|
||||||
let eventsCode = events
|
let eventsCode = events
|
||||||
.map(function ([name, value]) {
|
.map(function ([name, value]) {
|
||||||
|
const capture = name.match(/\.capture/);
|
||||||
|
name = capture ? name.replace(/\.capture/, "") : name;
|
||||||
const { event, handler } = makeHandlerCode(ctx, name, value, false, T_COMPONENT_MODS_CODE);
|
const { event, handler } = makeHandlerCode(ctx, name, value, false, T_COMPONENT_MODS_CODE);
|
||||||
|
if (capture) {
|
||||||
|
return `vn.elm.addEventListener('${event}', ${handler}, true);`;
|
||||||
|
}
|
||||||
return `vn.elm.addEventListener('${event}', ${handler});`;
|
return `vn.elm.addEventListener('${event}', ${handler});`;
|
||||||
})
|
})
|
||||||
.join("");
|
.join("");
|
||||||
const styleExpr = tattStyle || (styleAttr ? `'${styleAttr}'` : false);
|
const styleExpr = tattStyle || (styleAttr ? `'${styleAttr}'` : false);
|
||||||
const styleCode = styleExpr ? `vn.elm.style = ${styleExpr};` : "";
|
const styleCode = styleExpr ? `vn.elm.style = ${styleExpr};` : "";
|
||||||
createHook = `vnode.data.hook = {create(_, vn){${styleCode}${eventsCode}}};`;
|
createHook = `utils.assignHooks(vnode.data, {create(_, vn){${styleCode}${eventsCode}}});`;
|
||||||
}
|
}
|
||||||
ctx.addLine(`let w${componentID} = ${templateKey} in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[${templateKey}]] : false;`);
|
ctx.addLine(`let w${componentID} = ${templateKey} in parent.__owl__.cmap ? parent.__owl__.children[parent.__owl__.cmap[${templateKey}]] : false;`);
|
||||||
let shouldProxy = !ctx.parentNode;
|
let shouldProxy = !ctx.parentNode;
|
||||||
@@ -3033,7 +3085,7 @@
|
|||||||
ctx.addLine(`w${componentID} = new W${componentID}(parent, props${componentID});`);
|
ctx.addLine(`w${componentID} = new W${componentID}(parent, props${componentID});`);
|
||||||
if (transition) {
|
if (transition) {
|
||||||
ctx.addLine(`const __patch${componentID} = w${componentID}.__patch;`);
|
ctx.addLine(`const __patch${componentID} = w${componentID}.__patch;`);
|
||||||
ctx.addLine(`w${componentID}.__patch = fiber => {__patch${componentID}.call(w${componentID}, fiber); if(!w${componentID}.__owl__.transitionInserted){w${componentID}.__owl__.transitionInserted = true;utils.transitionInsert(w${componentID}.__owl__.vnode, '${transition}');}};`);
|
ctx.addLine(`w${componentID}.__patch = (t, vn) => {__patch${componentID}.call(w${componentID}, t, vn); if(!w${componentID}.__owl__.transitionInserted){w${componentID}.__owl__.transitionInserted = true;utils.transitionInsert(w${componentID}.__owl__.vnode, '${transition}');}};`);
|
||||||
}
|
}
|
||||||
ctx.addLine(`parent.__owl__.cmap[${templateKey}] = w${componentID}.__owl__.id;`);
|
ctx.addLine(`parent.__owl__.cmap[${templateKey}] = w${componentID}.__owl__.id;`);
|
||||||
if (hasSlots) {
|
if (hasSlots) {
|
||||||
@@ -3115,6 +3167,16 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
rejectFiber(fiber, reason) {
|
||||||
|
fiber = fiber.root;
|
||||||
|
const index = this.tasks.findIndex(t => t.fiber === fiber);
|
||||||
|
if (index >= 0) {
|
||||||
|
const [task] = this.tasks.splice(index, 1);
|
||||||
|
fiber.cancel();
|
||||||
|
fiber.error = new Error(reason);
|
||||||
|
task.callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Process all current tasks. This only applies to the fibers that are ready.
|
* Process all current tasks. This only applies to the fibers that are ready.
|
||||||
* Other tasks are left unchanged.
|
* Other tasks are left unchanged.
|
||||||
@@ -3171,7 +3233,7 @@
|
|||||||
* states and in general determine the state of the rendering.
|
* states and in general determine the state of the rendering.
|
||||||
*/
|
*/
|
||||||
class Fiber {
|
class Fiber {
|
||||||
constructor(parent, component, force, inserter) {
|
constructor(parent, component, force, target, position) {
|
||||||
this.id = Fiber.nextId++;
|
this.id = Fiber.nextId++;
|
||||||
// isCompleted means that the rendering corresponding to this fiber's work is
|
// isCompleted means that the rendering corresponding to this fiber's work is
|
||||||
// done, either because the component has been mounted or patched, or because
|
// done, either because the component has been mounted or patched, or because
|
||||||
@@ -3199,7 +3261,8 @@
|
|||||||
this.parent = null;
|
this.parent = null;
|
||||||
this.component = component;
|
this.component = component;
|
||||||
this.force = force;
|
this.force = force;
|
||||||
this.inserter = inserter;
|
this.target = target;
|
||||||
|
this.position = position;
|
||||||
const __owl__ = component.__owl__;
|
const __owl__ = component.__owl__;
|
||||||
this.scope = __owl__.scope;
|
this.scope = __owl__.scope;
|
||||||
this.root = parent ? parent.root : this;
|
this.root = parent ? parent.root : this;
|
||||||
@@ -3307,7 +3370,7 @@
|
|||||||
complete() {
|
complete() {
|
||||||
let component = this.component;
|
let component = this.component;
|
||||||
this.isCompleted = true;
|
this.isCompleted = true;
|
||||||
if (!this.inserter && !component.__owl__.isMounted) {
|
if (!this.target && !component.__owl__.isMounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// build patchQueue
|
// build patchQueue
|
||||||
@@ -3333,16 +3396,41 @@
|
|||||||
for (let i = patchLen - 1; i >= 0; i--) {
|
for (let i = patchLen - 1; i >= 0; i--) {
|
||||||
const fiber = patchQueue[i];
|
const fiber = patchQueue[i];
|
||||||
component = fiber.component;
|
component = fiber.component;
|
||||||
component.__patch(fiber.vnode);
|
if (fiber.target && i === 0) {
|
||||||
if (!fiber.shouldPatch && (!fiber.inserter || i !== 0)) {
|
let target;
|
||||||
component.__owl__.pvnode.elm = component.__owl__.vnode.elm;
|
if (fiber.position === "self") {
|
||||||
|
target = fiber.target;
|
||||||
|
if (target.tagName.toLowerCase() !== fiber.vnode.sel) {
|
||||||
|
throw new Error(`Cannot attach '${component.constructor.name}' to target node (not same tag name)`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target = component.__owl__.vnode || document.createElement(fiber.vnode.sel);
|
||||||
|
}
|
||||||
|
component.__patch(target, fiber.vnode);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (fiber.shouldPatch) {
|
||||||
|
component.__patch(component.__owl__.vnode, fiber.vnode);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
component.__patch(document.createElement(fiber.vnode.sel), fiber.vnode);
|
||||||
|
component.__owl__.pvnode.elm = component.__owl__.vnode.elm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
component.__owl__.currentFiber = null;
|
component.__owl__.currentFiber = null;
|
||||||
}
|
}
|
||||||
// insert into the DOM (mount case)
|
// insert into the DOM (mount case)
|
||||||
let inDOM = false;
|
let inDOM = false;
|
||||||
if (this.inserter) {
|
if (this.target) {
|
||||||
this.inserter(this.component.el);
|
switch (this.position) {
|
||||||
|
case "first-child":
|
||||||
|
this.target.prepend(this.component.el);
|
||||||
|
break;
|
||||||
|
case "last-child":
|
||||||
|
this.target.appendChild(this.component.el);
|
||||||
|
break;
|
||||||
|
}
|
||||||
inDOM = document.body.contains(this.component.el);
|
inDOM = document.body.contains(this.component.el);
|
||||||
this.component.env.qweb.trigger("dom-appended");
|
this.component.env.qweb.trigger("dom-appended");
|
||||||
}
|
}
|
||||||
@@ -3350,13 +3438,13 @@
|
|||||||
for (let i = patchLen - 1; i >= 0; i--) {
|
for (let i = patchLen - 1; i >= 0; i--) {
|
||||||
const fiber = patchQueue[i];
|
const fiber = patchQueue[i];
|
||||||
component = fiber.component;
|
component = fiber.component;
|
||||||
if (fiber.shouldPatch && !this.inserter) {
|
if (fiber.shouldPatch && !this.target) {
|
||||||
component.patched();
|
component.patched();
|
||||||
if (component.__owl__.patchedCB) {
|
if (component.__owl__.patchedCB) {
|
||||||
component.__owl__.patchedCB();
|
component.__owl__.patchedCB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (this.inserter ? inDOM : true) {
|
else if (this.target ? inDOM : true) {
|
||||||
component.__callMounted();
|
component.__callMounted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3765,22 +3853,31 @@
|
|||||||
const position = options.position || "last-child";
|
const position = options.position || "last-child";
|
||||||
const __owl__ = this.__owl__;
|
const __owl__ = this.__owl__;
|
||||||
if (__owl__.isMounted) {
|
if (__owl__.isMounted) {
|
||||||
return Promise.resolve();
|
if (position !== "self" && this.el.parentNode !== target) {
|
||||||
|
// in this situation, we are trying to mount a component on a different
|
||||||
|
// target. In this case, we need to unmount first, otherwise it will
|
||||||
|
// not work.
|
||||||
|
this.unmount();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (__owl__.currentFiber) {
|
||||||
|
const currentFiber = __owl__.currentFiber;
|
||||||
|
if (currentFiber.target === target && currentFiber.position === position) {
|
||||||
|
return scheduler.addFiber(currentFiber);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scheduler.rejectFiber(currentFiber, "Mounting operation cancelled");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!(target instanceof HTMLElement || target instanceof DocumentFragment)) {
|
if (!(target instanceof HTMLElement || target instanceof DocumentFragment)) {
|
||||||
let message = `Component '${this.constructor.name}' cannot be mounted: the target is not a valid DOM node.`;
|
let message = `Component '${this.constructor.name}' cannot be mounted: the target is not a valid DOM node.`;
|
||||||
message += `\nMaybe the DOM is not ready yet? (in that case, you can use owl.utils.whenReady)`;
|
message += `\nMaybe the DOM is not ready yet? (in that case, you can use owl.utils.whenReady)`;
|
||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
let inserter = position === "last-child"
|
const fiber = new Fiber(null, this, false, target, position);
|
||||||
? el => target.appendChild(el)
|
|
||||||
: position === "first-child"
|
|
||||||
? el => target.prepend(el)
|
|
||||||
: el => { };
|
|
||||||
if (position === "self") {
|
|
||||||
this.__target = target;
|
|
||||||
}
|
|
||||||
const fiber = new Fiber(null, this, false, inserter);
|
|
||||||
fiber.shouldPatch = false;
|
fiber.shouldPatch = false;
|
||||||
if (!__owl__.vnode) {
|
if (!__owl__.vnode) {
|
||||||
this.__prepareAndRender(fiber, () => { });
|
this.__prepareAndRender(fiber, () => { });
|
||||||
@@ -3824,9 +3921,12 @@
|
|||||||
// currentFiber that is already rendered (isRendered is true), so we are
|
// currentFiber that is already rendered (isRendered is true), so we are
|
||||||
// about to be mounted
|
// about to be mounted
|
||||||
const isMounted = __owl__.isMounted;
|
const isMounted = __owl__.isMounted;
|
||||||
const fiber = new Fiber(null, this, force, null);
|
const fiber = new Fiber(null, this, force, null, null);
|
||||||
Promise.resolve().then(() => {
|
Promise.resolve().then(() => {
|
||||||
if (__owl__.isMounted || !isMounted) {
|
if (__owl__.isMounted || !isMounted) {
|
||||||
|
if (fiber.isCompleted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// we are mounted (__owl__.isMounted), or if we are currently being
|
// we are mounted (__owl__.isMounted), or if we are currently being
|
||||||
// mounted (!isMounted), so we call __render
|
// mounted (!isMounted), so we call __render
|
||||||
this.__render(fiber);
|
this.__render(fiber);
|
||||||
@@ -3971,7 +4071,7 @@
|
|||||||
const shouldUpdate = parentFiber.force || this.shouldUpdate(nextProps);
|
const shouldUpdate = parentFiber.force || this.shouldUpdate(nextProps);
|
||||||
if (shouldUpdate) {
|
if (shouldUpdate) {
|
||||||
const __owl__ = this.__owl__;
|
const __owl__ = this.__owl__;
|
||||||
const fiber = new Fiber(parentFiber, this, parentFiber.force, null);
|
const fiber = new Fiber(parentFiber, this, parentFiber.force, null, null);
|
||||||
if (!parentFiber.child) {
|
if (!parentFiber.child) {
|
||||||
parentFiber.child = fiber;
|
parentFiber.child = fiber;
|
||||||
}
|
}
|
||||||
@@ -4001,19 +4101,8 @@
|
|||||||
* Main patching method. We call the virtual dom patch method here to convert
|
* Main patching method. We call the virtual dom patch method here to convert
|
||||||
* a virtual dom vnode into some actual dom.
|
* a virtual dom vnode into some actual dom.
|
||||||
*/
|
*/
|
||||||
__patch(vnode) {
|
__patch(target, vnode) {
|
||||||
const __owl__ = this.__owl__;
|
this.__owl__.vnode = patch(target, vnode);
|
||||||
if (this.__target) {
|
|
||||||
if (this.__target.tagName.toLowerCase() !== vnode.sel) {
|
|
||||||
throw new Error(`Cannot attach '${this.constructor.name}' to target node (not same tag name)`);
|
|
||||||
}
|
|
||||||
__owl__.vnode = patch(this.__target, vnode);
|
|
||||||
delete this.__target;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const target = __owl__.vnode || document.createElement(vnode.sel);
|
|
||||||
__owl__.vnode = patch(target, vnode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* The __prepare method is only called by the t-component directive, when a
|
* The __prepare method is only called by the t-component directive, when a
|
||||||
@@ -4022,7 +4111,7 @@
|
|||||||
*/
|
*/
|
||||||
__prepare(parentFiber, scope, cb) {
|
__prepare(parentFiber, scope, cb) {
|
||||||
this.__owl__.scope = scope;
|
this.__owl__.scope = scope;
|
||||||
const fiber = new Fiber(parentFiber, this, parentFiber.force, null);
|
const fiber = new Fiber(parentFiber, this, parentFiber.force, null, null);
|
||||||
fiber.shouldPatch = false;
|
fiber.shouldPatch = false;
|
||||||
if (!parentFiber.child) {
|
if (!parentFiber.child) {
|
||||||
parentFiber.child = fiber;
|
parentFiber.child = fiber;
|
||||||
@@ -4607,19 +4696,6 @@
|
|||||||
}
|
}
|
||||||
AsyncRoot.template = xml `<t t-slot="default"/>`;
|
AsyncRoot.template = xml `<t t-slot="default"/>`;
|
||||||
|
|
||||||
/**
|
|
||||||
* Portal
|
|
||||||
*
|
|
||||||
* The Portal component allows to render a part of a component outside it's DOM.
|
|
||||||
* It is for example useful for dialogs: for css reasons, dialogs are in general
|
|
||||||
* placed in a specific spot of the DOM (e.g. directly in the body). With the
|
|
||||||
* Portal, a component can conditionally specify in its tempate that it contains
|
|
||||||
* a dialog, and where this dialog should be inserted in the DOM.
|
|
||||||
*
|
|
||||||
* The Portal component ensures that the communication between the content of
|
|
||||||
* the Portal and its parent properly works: business events reaching the Portal
|
|
||||||
* are re-triggered on an empty <portal> node located in the parent's DOM.
|
|
||||||
*/
|
|
||||||
class Portal extends Component {
|
class Portal extends Component {
|
||||||
constructor(parent, props) {
|
constructor(parent, props) {
|
||||||
super(parent, props);
|
super(parent, props);
|
||||||
@@ -4714,7 +4790,7 @@
|
|||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
__patch(vnode) {
|
__patch(target, vnode) {
|
||||||
if (this.doTargetLookUp) {
|
if (this.doTargetLookUp) {
|
||||||
const target = document.querySelector(this.props.target);
|
const target = document.querySelector(this.props.target);
|
||||||
if (!target) {
|
if (!target) {
|
||||||
@@ -4740,7 +4816,7 @@
|
|||||||
const portalPatch = this.portal ? this.portal : document.createElement(vnode.children[0].sel);
|
const portalPatch = this.portal ? this.portal : document.createElement(vnode.children[0].sel);
|
||||||
this.portal = patch(portalPatch, vnode.children[0]);
|
this.portal = patch(portalPatch, vnode.children[0]);
|
||||||
vnode.children = [];
|
vnode.children = [];
|
||||||
super.__patch(vnode);
|
super.__patch(target, vnode);
|
||||||
if (shouldDeploy) {
|
if (shouldDeploy) {
|
||||||
this.__deployPortal();
|
this.__deployPortal();
|
||||||
}
|
}
|
||||||
@@ -5058,9 +5134,9 @@
|
|||||||
exports.useState = useState$1;
|
exports.useState = useState$1;
|
||||||
exports.utils = utils;
|
exports.utils = utils;
|
||||||
|
|
||||||
exports.__info__.version = '1.0.0';
|
exports.__info__.version = '1.0.5';
|
||||||
exports.__info__.date = '2020-01-09T13:45:31.837Z';
|
exports.__info__.date = '2020-02-21T08:52:31.577Z';
|
||||||
exports.__info__.hash = '3d0f046';
|
exports.__info__.hash = 'fd6327b';
|
||||||
exports.__info__.url = 'https://github.com/odoo/owl';
|
exports.__info__.url = 'https://github.com/odoo/owl';
|
||||||
|
|
||||||
}(this.owl = this.owl || {}));
|
}(this.owl = this.owl || {}));
|
||||||
|
|||||||
@@ -1811,6 +1811,49 @@ const WMS_CSS = `body {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
const SFC = `// This example illustrates how Owl enables single file components,
|
||||||
|
// which include code, template and style.
|
||||||
|
//
|
||||||
|
// This is very useful in some situations, such as testing or quick prototyping.
|
||||||
|
// Note that this example has no external xml or css file, everything is
|
||||||
|
// contained in a single js file.
|
||||||
|
|
||||||
|
const { Component, useState, tags } = owl;
|
||||||
|
const { xml, css } = tags;
|
||||||
|
|
||||||
|
// Counter component
|
||||||
|
const COUNTER_TEMPLATE = xml\`
|
||||||
|
<button t-on-click="state.value++">
|
||||||
|
Click! [<t t-esc="state.value"/>]
|
||||||
|
</button>\`;
|
||||||
|
|
||||||
|
const COUNTER_STYLE = css\`
|
||||||
|
button {
|
||||||
|
color: blue;
|
||||||
|
}\`;
|
||||||
|
|
||||||
|
class Counter extends Component {
|
||||||
|
state = useState({ value: 0})
|
||||||
|
}
|
||||||
|
Counter.template = COUNTER_TEMPLATE;
|
||||||
|
Counter.style = COUNTER_STYLE;
|
||||||
|
|
||||||
|
// App
|
||||||
|
const APP_TEMPLATE = xml\`
|
||||||
|
<div>
|
||||||
|
<Counter/>
|
||||||
|
<Counter/>
|
||||||
|
</div>\`;
|
||||||
|
|
||||||
|
class App extends Component {}
|
||||||
|
App.template = APP_TEMPLATE;
|
||||||
|
App.components = { Counter };
|
||||||
|
|
||||||
|
// Application setup
|
||||||
|
const app = new App();
|
||||||
|
app.mount(document.body);
|
||||||
|
`;
|
||||||
|
|
||||||
export const SAMPLES = [
|
export const SAMPLES = [
|
||||||
{
|
{
|
||||||
description: "Components",
|
description: "Components",
|
||||||
@@ -1823,6 +1866,10 @@ export const SAMPLES = [
|
|||||||
code: FORM,
|
code: FORM,
|
||||||
xml: FORM_XML
|
xml: FORM_XML
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "Single File Components",
|
||||||
|
code: SFC
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "Animations",
|
description: "Animations",
|
||||||
code: ANIMATION,
|
code: ANIMATION,
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
# v1.0.5
|
||||||
|
|
||||||
|
- lots of doc improvements
|
||||||
|
- qweb: ignore comments between t-if/t-elif/t-else
|
||||||
|
- qweb: support attributes with inside quotes
|
||||||
|
- component: concurrency bug fix
|
||||||
|
- component: cancel previous mounting operations if necessary
|
||||||
|
- transition: no crash if element added/removed quickly
|
||||||
Reference in New Issue
Block a user