[IMP] component/tags: add inline css tag

This add an important feature: defining completely standalone owl
components, with the template/style and javascript code together.

closes #284
This commit is contained in:
Géry Debongnie
2019-12-19 21:54:35 +01:00
committed by aab-odoo
parent 4f61d9f1e0
commit 953778dc50
10 changed files with 345 additions and 30 deletions
+18
View File
@@ -6,6 +6,7 @@ import "./directive";
import { Fiber } from "./fiber";
import "./props_validation";
import { Scheduler, scheduler } from "./scheduler";
import { activateSheet } from "./styles";
/**
* Owl Component System
@@ -199,6 +200,9 @@ export class Component<T extends Env, Props extends {}> {
refs: null,
scope: null
};
if (constr.style) {
this.__applyStyles(constr);
}
}
/**
@@ -580,6 +584,20 @@ export class Component<T extends Env, Props extends {}> {
return fiber;
}
/**
* Apply the stylesheets defined by the component. Note that we need to make
* sure all inherited stylesheets are applied as well. We then delete the
* `style` key from the constructor to make sure we do not apply it again.
*/
private __applyStyles(constr) {
while (constr && constr.style) {
if (constr.hasOwnProperty("style")) {
activateSheet(constr.style, constr.name);
delete constr.style;
}
constr = constr.__proto__;
}
}
__getTemplate(qweb: QWeb): string {
let p = (<any>this).constructor;
if (!p.hasOwnProperty("_template")) {
+56
View File
@@ -0,0 +1,56 @@
/**
* Owl Style System
*
* This files contains the Owl code related to processing (extended) css strings
* and creating/adding <style> tags to the document head.
*/
export const STYLESHEETS: { [id: string]: HTMLStyleElement } = {};
function processSheet(str: string): string {
const tokens = str.split(/(\{|\}|;)/).map(s => s.trim());
const selectorStack: string[] = [];
const parts: string[] = [];
let rules: string[] = [];
function generateRules() {
if (rules.length) {
parts.push(selectorStack.join(" ") + " {");
parts.push(...rules);
parts.push("}");
rules = [];
}
}
while (tokens.length) {
let token = tokens.shift()!;
if (token === "}") {
generateRules();
selectorStack.pop();
} else {
if (tokens[0] === "{") {
generateRules();
selectorStack.push(token);
tokens.shift();
}
if (tokens[0] === ";") {
rules.push(" " + token + ";");
}
}
}
return parts.join("\n");
}
export function registerSheet(id: string, css: string) {
const sheet = document.createElement("style");
sheet.innerHTML = processSheet(css);
STYLESHEETS[id] = sheet;
}
export function activateSheet(id, name) {
const sheet = STYLESHEETS[id];
if (!sheet) {
throw new Error(
`Invalid css stylesheet for component '${name}'. Did you forget to use the 'css' tag helper?`
);
}
sheet.setAttribute("component", name);
document.head.appendChild(sheet);
}