app-decorators
Version:
Collection of useful ES7 Decorators, writtin in ES6, that can be used for building webapps
207 lines (170 loc) • 8.39 kB
JavaScript
System.register(['app-decorators/src/libs/element-to-function', '../libs/stylesheet', '../datas/init-maps', '../libs/random-storage', '../libs/eventhandler', '../apps/router'], function (_export, _context) {
"use strict";
var _elementToFunc, Stylesheet, initCoreMap, initStyleMap, storage, Eventhandler, Router, getHandler, syncStylesheetStates, setPath, createStylesheet;
/**
* Style
* @param {string|Array} styles
* @param options {{fallback: Function}}
* @return {Function}
*/
function style(styles) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return function (Class) {
initCoreMap(storage, Class);
initStyleMap(storage, Class);
var map = storage.get(Class);
var styleMap = map.get('@style');
// Stylesheets holds the styles (ast) that
// are passed by the @style decorator
styleMap.set('stylesheets', styles);
// referenceNodes holds the current created domNodes (customElements)
var nodes = styleMap.get('referenceNodes');
// stylesheetStates holds the event state (event reached or not)
// of each style-ast in styles object
var stylesheetStates = styleMap.get('stylesheetStates');
/**
* Its required when we use @style multiple times!
* Only once registration!
*/
if (map.get('@style').get('callbacksDefined')) {
return;
}
var createdAndAttached = function createdAndAttached(domNode) {
//TODO: create eventhandler if not created
setPath(domNode, '$stylesheets', []);
// create stylesheet node when no referenceNodes (customelement) exists
if (!nodes.size) {
// default state of each style-ast is false (undefined)
var _stylesheetStates = styleMap.get('stylesheetStates');
createStylesheet(Class, styles, domNode, options, _stylesheetStates);
}
!nodes.has(domNode) && nodes.set(domNode, domNode);
};
map.get('@callbacks').get('created').push(createdAndAttached);
map.get('@callbacks').get('attached').push(createdAndAttached);
map.get('@callbacks').get('detached').push(function (domNode) {
// cleanup
domNode.$stylesheets.forEach(function (stylesheet) {
return stylesheet.destroy();
});
// remove detached node from referenceNodes
nodes.has(domNode) && nodes.delete(domNode);
// not each domNode has $stylesheets, so return when no once found.
if (!domNode.$stylesheets.length) {
return null;
}
// stylesheetStates (attachOn) are the event state (reached or not reached) of each
// array object (styles, imports, ...) that are passed by style decorator.
// The state of an array object is required ...
// [
// {
// attachOn: 'load',
// type: 'on',
// imports: ["a.css", "b.css", "c.css"],
// styles: '.baz {color: green;}',
// },
// {
// attachOn: 'immediately',
// type: 'lala',
// imports: [],
// styles: '.laz {color: green;}',
// }
// ]
stylesheetStates = syncStylesheetStates(domNode.$stylesheets, stylesheetStates) || [];
// when elements detached from document.body, we need a new node that take the role of $stylesheet
var node = nodes.values().next().value;
// when node is valid, create fresh stylesheet
if (node) {
createStylesheet(Class, styles, node, options, stylesheetStates);
}
// save the stylesheetStates
styleMap.set('stylesheetStates', stylesheetStates);
//cleanup
delete domNode.$stylesheets;
});
map.get('@style').set('callbacksDefined', true);
};
}
return {
setters: [function (_appDecoratorsSrcLibsElementToFunction) {
_elementToFunc = _appDecoratorsSrcLibsElementToFunction.default;
}, function (_libsStylesheet) {
Stylesheet = _libsStylesheet.Stylesheet;
}, function (_datasInitMaps) {
initCoreMap = _datasInitMaps.initCoreMap;
initStyleMap = _datasInitMaps.initStyleMap;
}, function (_libsRandomStorage) {
storage = _libsRandomStorage.storage;
}, function (_libsEventhandler) {
Eventhandler = _libsEventhandler.Eventhandler;
}, function (_appsRouter) {
Router = _appsRouter.Router;
}],
execute: function () {
getHandler = function getHandler(style, element) {
var type = style.type;
// default state is immediately
if (type === "on" || type === "default") {
return new Eventhandler({ element: element });
} else if (type === "action") {
style.attachOn += ' ' + style.attachOn;
var router = Router.create({
scope: element
});
router.start();
return router;
} else if (type === "query") {
// https://wicg.github.io/ResizeObserver/
return {
on: function on() {},
off: function off() {}
};
}
};
syncStylesheetStates = function syncStylesheetStates(stylesheets, stylesheetStates) {
stylesheetStates = [];
stylesheets.forEach(function (stylesheet) {
return stylesheetStates.push(stylesheet.alreadyDone);
});
return stylesheetStates;
};
setPath = function setPath(object, key, value) {
if (!(object[key] && object[key].length)) {
object[key] = value;
}
};
createStylesheet = function createStylesheet(Class, styles, domNode, options, stylesheetStates) {
var _loop = function _loop(i, len) {
var style = styles[i];
var stylesheet = new Stylesheet({
appendTo: domNode,
attachOn: style.attachOn,
imports: style.imports,
styles: style.styles,
type: style.type,
order: i,
alreadyDone: stylesheetStates[i],
fallback: options.fallback,
// 1.) hole route oder eventhandler instance aus element, wenn welches existiert
// 2.) wenn existiert, dann weiter zu punkt 3 ansonsten wie gehabt eventFactory
// 4.) prüfe ob event z.B. click .a oder /a/b/c.html existiert
// 5.) wenn füge es dem event denn callback hinzu, statt ihn wieder anzumelden
// 6.) Eventuell reicht instance zu holen (wenn existiert) und einfach mit .on
// anzuhängen siehe. eventhandler.js zeile 224
eventFactory: function eventFactory(element) {
return getHandler(style, element);
}
});
domNode.$stylesheets.push(stylesheet);
};
// TODO: alles in einem eventhandler per .on ( hinzufugen
for (var i = 0, len = styles.length; i < len; i++) {
_loop(i, len);
}
return domNode;
};
_export('style', style);
}
};
});
//# sourceMappingURL=style.js.map