cyclejs-modal
Version:
An easy way to open custom modals in a cyclejs app
1,236 lines (1,222 loc) • 630 kB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var rxjs_run_1 = require("@cycle/rxjs-run");
var rxjs_1 = require("rxjs");
var operators_1 = require("rxjs/operators");
var dom_1 = require("@cycle/dom");
var isolate_1 = require("@cycle/isolate");
var modalify_1 = require("../../../src/modalify");
function main(_a) {
var DOM = _a.DOM;
return {
DOM: rxjs_1.of(dom_1.button('.button', ['open modal'])),
modal: DOM.select('.button')
.events('click')
.pipe(operators_1.mapTo({
type: 'open',
component: isolate_1.default(modal)
}))
};
}
function modal(_a) {
var DOM = _a.DOM;
return {
DOM: rxjs_1.of(dom_1.div('.div', [
dom_1.span('.span', ['This is an rxjs modal! :)']),
dom_1.button('.button', ['close'])
])),
modal: DOM.select('.button')
.events('click')
.pipe(operators_1.mapTo({ type: 'close' }))
};
}
rxjs_run_1.run(modalify_1.modalify(main), {
DOM: dom_1.makeDOMDriver('#app')
});
},{"../../../src/modalify":2,"@cycle/dom":16,"@cycle/isolate":23,"@cycle/rxjs-run":28,"rxjs":32,"rxjs/operators":230}],2:[function(require,module,exports){
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var xstream_1 = require("xstream");
var dom_1 = require("@cycle/dom");
var adapt_1 = require("@cycle/run/lib/adapt");
var cyclejs_utils_1 = require("cyclejs-utils");
var ModalSource = /** @class */ (function () {
function ModalSource(_namespace, _sinks$$) {
if (_sinks$$ === void 0) { _sinks$$ = xstream_1.default.create(); }
this._namespace = _namespace;
this._sinks$$ = _sinks$$;
}
ModalSource.prototype.select = function (id) {
return new ModalSource(this._namespace, this._sinks$$.filter(function (o) { return o.id !== undefined && o.id === id; }));
};
ModalSource.prototype.sinks = function (driverNames) {
if (driverNames) {
return cyclejs_utils_1.extractSinks(this.sinks(), driverNames);
}
return this._sinks$$.map(function (o) { return o.sinks$; }).flatten();
};
ModalSource.prototype.isolateSource = function (source, scope) {
return new ModalSource(source._namespace.concat(scope), source._sinks$$
.filter(function (o) { return o.namespace[0] === scope; })
.map(function (o) { return (__assign({}, o, { namespace: o.namespace.slice(1) })); }));
};
ModalSource.prototype.isolateSink = function (modal$, scope) {
var _this = this;
return modal$.map(function (action) { return (__assign({}, action, { namespace: action.namespace
? action.namespace
: _this._namespace.concat(scope) })); });
};
return ModalSource;
}());
exports.ModalSource = ModalSource;
function modalify(main, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.name, name = _c === void 0 ? 'modal' : _c, _d = _b.DOMDriverKey, DOMDriverKey = _d === void 0 ? 'DOM' : _d, _e = _b.center, center = _e === void 0 ? true : _e, _f = _b.wrapperClass, wrapperClass = _f === void 0 ? null : _f, _g = _b.modalContainerClass, modalContainerClass = _g === void 0 ? null : _g, _h = _b.background, background = _h === void 0 ? 'rgba(0,0,0,0.8)' : _h, _j = _b.zIndex, zIndex = _j === void 0 ? 500 : _j;
return function (sources) {
var _a, _b;
var modalSource = new ModalSource([]);
var parentSinks = main(__assign({}, sources, (_a = {}, _a[name] = modalSource, _a)));
var sinks = Object.keys(parentSinks)
.map(function (k) {
var _a;
return (_a = {}, _a[k] = xstream_1.default.fromObservable(parentSinks[k]), _a);
})
.reduce(function (prev, curr) { return Object.assign(prev, curr); }, {});
if (sinks[name]) {
var modalProxy$ = xstream_1.default.create();
var modalStack$ = xstream_1.default
.merge(sinks[name], modalProxy$)
.fold(function (acc, curr) {
if (curr.type === 'close') {
var count = curr.count || 1;
for (var i = 0; i < Math.min(acc.length, count); i++) {
var _a = acc[acc.length - i - 1], id = _a[0], namespace = _a[1], _ = _a[2];
modalSource._sinks$$.shamefullySendNext({
id: id,
namespace: namespace,
sinks$: xstream_1.default.never()
});
}
return acc.slice(0, Math.max(acc.length - count, 0));
}
else if (curr.type === 'open') {
var _sources = curr.sources !== undefined ? curr.sources : sources;
var overlayClose$ = xstream_1.default.never();
if (curr.backgroundOverlayClose !== false) {
overlayClose$ = xstream_1.default
.fromObservable(sources[DOMDriverKey].select('div.cyclejs-modal').events('click'))
.map(function (ev) {
ev.stopPropagation();
return ev;
})
.filter(function (e) {
return e.target ===
(e.currentTarget || e.ownerTarget);
})
.mapTo({ type: 'close' });
}
var componentSinks_1 = curr.component(_sources);
var xsComponentSinks = Object.keys(componentSinks_1)
.map(function (k) {
var _a;
return (_a = {},
_a[k] = xstream_1.default.fromObservable(componentSinks_1[k]),
_a);
})
.reduce(function (prev, curr) { return Object.assign(prev, curr); }, {});
var domlessSinks = __assign({}, componentSinks_1);
delete domlessSinks[DOMDriverKey];
modalSource._sinks$$.shamefullySendNext({
id: curr.id,
namespace: curr.namespace || [],
sinks$: xstream_1.default.never().startWith(domlessSinks)
});
return acc.concat([
[
curr.id,
curr.namespace || [],
__assign({}, xsComponentSinks, { modal: xstream_1.default.merge(xsComponentSinks[name] || xstream_1.default.never(), overlayClose$) })
]
]);
}
return acc;
}, []);
var modalVDom$ = modalStack$
.map(function (arr) { return arr.map(function (s) { return s[2][DOMDriverKey]; }); })
.map(function (arr) { return xstream_1.default.combine.apply(xstream_1.default, arr); })
.flatten();
var mergedVDom$ = xstream_1.default
.combine(sinks[DOMDriverKey], modalVDom$)
.map(function (_a) {
var vdom = _a[0], modals = _a[1];
return dom_1.h('div', { attrs: { class: wrapperClass || '' } }, [
vdom,
center && modals.length > 0
? displayModals(wrapModals(modals, modalContainerClass), background, zIndex)
: dom_1.h('div', {
attrs: {
class: modalContainerClass || ''
}
}, modals)
]);
});
var extractedSinks = cyclejs_utils_1.extractSinks(modalStack$
.map(function (arr) {
return arr.filter(function (s) { return s[0] === undefined; }).map(function (s) { return s[2]; });
})
.map(cyclejs_utils_1.mergeSinks), Object.keys(sinks));
modalProxy$.imitate(extractedSinks[name]);
var newSinks_1 = __assign({}, cyclejs_utils_1.mergeSinks([extractedSinks, sinks]), (_b = {}, _b[DOMDriverKey] = mergedVDom$, _b));
return Object.keys(newSinks_1)
.map(function (k) {
var _a;
return (_a = {}, _a[k] = adapt_1.adapt(newSinks_1[k]), _a);
})
.reduce(function (prev, curr) { return Object.assign(prev, curr); }, {});
}
return sinks;
};
}
exports.modalify = modalify;
function centerHTML(children) {
return dom_1.h('div', {
style: {
width: '100%',
height: '100%',
position: 'relative',
'pointer-events': 'none'
}
}, children.map(function (child) {
return dom_1.h('div', {
style: {
position: 'absolute',
top: '50%',
left: '50%',
'-ms-transform': 'translate(-50%, -50%)',
'-webkit-transform': 'translate(-50%, -50%)',
transform: 'translate(-50%, -50%)',
'pointer-events': 'auto'
}
}, [child]);
}));
}
exports.centerHTML = centerHTML;
function displayModals(modals, background, zIndex) {
if (background === void 0) { background = 'rgba(0,0,0,0.8)'; }
if (zIndex === void 0) { zIndex = 500; }
var processedModals = modals.map(function (m, i) {
return addStyles({
'z-index': i * 5 + 10 + zIndex
}, m);
});
return addStyles({
background: background,
'z-index': zIndex,
top: '0px',
left: '0px',
position: 'fixed',
width: '100%',
height: '100%'
}, dom_1.h('div.cyclejs-modal', {}, [centerHTML(processedModals)]));
}
function wrapModals(modals, containerClass) {
if (containerClass === void 0) { containerClass = null; }
var wrapper = function (child) {
return dom_1.h('div', containerClass
? {
attrs: {
class: containerClass
}
}
: {
style: {
display: 'block',
padding: '10px',
background: 'white',
width: 'auto',
height: 'auto',
'border-radius': '5px'
}
}, [child]);
};
return modals.map(wrapper);
}
function addStyles(styles, vnode) {
return __assign({}, vnode, { data: __assign({}, (vnode.data || {}), { style: __assign({}, (vnode.data.style || {}), styles) }) });
}
},{"@cycle/dom":16,"@cycle/run/lib/adapt":24,"cyclejs-utils":29,"xstream":259}],3:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var xstream_1 = require("xstream");
var adapt_1 = require("@cycle/run/lib/adapt");
var fromEvent_1 = require("./fromEvent");
var BodyDOMSource = /** @class */ (function () {
function BodyDOMSource(_name) {
this._name = _name;
}
BodyDOMSource.prototype.select = function (selector) {
// This functionality is still undefined/undecided.
return this;
};
BodyDOMSource.prototype.elements = function () {
var out = adapt_1.adapt(xstream_1.default.of([document.body]));
out._isCycleSource = this._name;
return out;
};
BodyDOMSource.prototype.element = function () {
var out = adapt_1.adapt(xstream_1.default.of(document.body));
out._isCycleSource = this._name;
return out;
};
BodyDOMSource.prototype.events = function (eventType, options, bubbles) {
if (options === void 0) { options = {}; }
var stream;
stream = fromEvent_1.fromEvent(document.body, eventType, options.useCapture, options.preventDefault);
var out = adapt_1.adapt(stream);
out._isCycleSource = this._name;
return out;
};
return BodyDOMSource;
}());
exports.BodyDOMSource = BodyDOMSource;
},{"./fromEvent":14,"@cycle/run/lib/adapt":24,"xstream":259}],4:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var xstream_1 = require("xstream");
var adapt_1 = require("@cycle/run/lib/adapt");
var fromEvent_1 = require("./fromEvent");
var DocumentDOMSource = /** @class */ (function () {
function DocumentDOMSource(_name) {
this._name = _name;
}
DocumentDOMSource.prototype.select = function (selector) {
// This functionality is still undefined/undecided.
return this;
};
DocumentDOMSource.prototype.elements = function () {
var out = adapt_1.adapt(xstream_1.default.of([document]));
out._isCycleSource = this._name;
return out;
};
DocumentDOMSource.prototype.element = function () {
var out = adapt_1.adapt(xstream_1.default.of(document));
out._isCycleSource = this._name;
return out;
};
DocumentDOMSource.prototype.events = function (eventType, options, bubbles) {
if (options === void 0) { options = {}; }
var stream;
stream = fromEvent_1.fromEvent(document, eventType, options.useCapture, options.preventDefault);
var out = adapt_1.adapt(stream);
out._isCycleSource = this._name;
return out;
};
return DocumentDOMSource;
}());
exports.DocumentDOMSource = DocumentDOMSource;
},{"./fromEvent":14,"@cycle/run/lib/adapt":24,"xstream":259}],5:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ScopeChecker_1 = require("./ScopeChecker");
var utils_1 = require("./utils");
function toElArray(input) {
return Array.prototype.slice.call(input);
}
var ElementFinder = /** @class */ (function () {
function ElementFinder(namespace, isolateModule) {
this.namespace = namespace;
this.isolateModule = isolateModule;
}
ElementFinder.prototype.call = function () {
var namespace = this.namespace;
var selector = utils_1.getSelectors(namespace);
var scopeChecker = new ScopeChecker_1.ScopeChecker(namespace, this.isolateModule);
var topNode = this.isolateModule.getElement(namespace.filter(function (n) { return n.type !== 'selector'; }));
if (topNode === undefined) {
return [];
}
if (selector === '') {
return [topNode];
}
return toElArray(topNode.querySelectorAll(selector))
.filter(scopeChecker.isDirectlyInScope, scopeChecker)
.concat(topNode.matches(selector) ? [topNode] : []);
};
return ElementFinder;
}());
exports.ElementFinder = ElementFinder;
},{"./ScopeChecker":11,"./utils":22}],6:[function(require,module,exports){
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var xstream_1 = require("xstream");
var ScopeChecker_1 = require("./ScopeChecker");
var utils_1 = require("./utils");
var ElementFinder_1 = require("./ElementFinder");
var SymbolTree_1 = require("./SymbolTree");
var RemovalSet_1 = require("./RemovalSet");
var PriorityQueue_1 = require("./PriorityQueue");
var fromEvent_1 = require("./fromEvent");
exports.eventTypesThatDontBubble = [
"blur",
"canplay",
"canplaythrough",
"durationchange",
"emptied",
"ended",
"focus",
"load",
"loadeddata",
"loadedmetadata",
"mouseenter",
"mouseleave",
"pause",
"play",
"playing",
"ratechange",
"reset",
"scroll",
"seeked",
"seeking",
"stalled",
"submit",
"suspend",
"timeupdate",
"unload",
"volumechange",
"waiting",
];
/**
* Manages "Event delegation", by connecting an origin with multiple
* destinations.
*
* Attaches a DOM event listener to the DOM element called the "origin",
* and delegates events to "destinations", which are subjects as outputs
* for the DOMSource. Simulates bubbling or capturing, with regards to
* isolation boundaries too.
*/
var EventDelegator = /** @class */ (function () {
function EventDelegator(rootElement$, isolateModule) {
var _this = this;
this.rootElement$ = rootElement$;
this.isolateModule = isolateModule;
this.virtualListeners = new SymbolTree_1.default(function (x) { return x.scope; });
this.nonBubblingListenersToAdd = new RemovalSet_1.default();
this.virtualNonBubblingListener = [];
this.isolateModule.setEventDelegator(this);
this.domListeners = new Map();
this.domListenersToAdd = new Map();
this.nonBubblingListeners = new Map();
rootElement$.addListener({
next: function (el) {
if (_this.origin !== el) {
_this.origin = el;
_this.resetEventListeners();
_this.domListenersToAdd.forEach(function (passive, type) {
return _this.setupDOMListener(type, passive);
});
_this.domListenersToAdd.clear();
}
_this.resetNonBubblingListeners();
_this.nonBubblingListenersToAdd.forEach(function (arr) {
_this.setupNonBubblingListener(arr);
});
},
});
}
EventDelegator.prototype.addEventListener = function (eventType, namespace, options, bubbles) {
var subject = xstream_1.default.never();
var scopeChecker = new ScopeChecker_1.ScopeChecker(namespace, this.isolateModule);
var dest = this.insertListener(subject, scopeChecker, eventType, options);
var shouldBubble = bubbles === undefined
? exports.eventTypesThatDontBubble.indexOf(eventType) === -1
: bubbles;
if (shouldBubble) {
if (!this.domListeners.has(eventType)) {
this.setupDOMListener(eventType, !!options.passive);
}
}
else {
var finder = new ElementFinder_1.ElementFinder(namespace, this.isolateModule);
this.setupNonBubblingListener([eventType, finder, dest]);
}
return subject;
};
EventDelegator.prototype.removeElement = function (element, namespace) {
if (namespace !== undefined) {
this.virtualListeners.delete(namespace);
}
var toRemove = [];
this.nonBubblingListeners.forEach(function (map, type) {
if (map.has(element)) {
toRemove.push([type, element]);
}
});
for (var i = 0; i < toRemove.length; i++) {
var map = this.nonBubblingListeners.get(toRemove[i][0]);
if (!map) {
continue;
}
map.delete(toRemove[i][1]);
if (map.size === 0) {
this.nonBubblingListeners.delete(toRemove[i][0]);
}
else {
this.nonBubblingListeners.set(toRemove[i][0], map);
}
}
};
EventDelegator.prototype.insertListener = function (subject, scopeChecker, eventType, options) {
var relevantSets = [];
var n = scopeChecker._namespace;
var max = n.length;
do {
relevantSets.push(this.getVirtualListeners(eventType, n, true, max));
max--;
} while (max >= 0 && n[max].type !== 'total');
var destination = __assign({}, options, { scopeChecker: scopeChecker,
subject: subject, bubbles: !!options.bubbles, useCapture: !!options.useCapture, passive: !!options.passive });
for (var i = 0; i < relevantSets.length; i++) {
relevantSets[i].add(destination, n.length);
}
return destination;
};
/**
* Returns a set of all virtual listeners in the scope of the namespace
* Set `exact` to true to treat sibiling isolated scopes as total scopes
*/
EventDelegator.prototype.getVirtualListeners = function (eventType, namespace, exact, max) {
if (exact === void 0) { exact = false; }
var _max = max !== undefined ? max : namespace.length;
if (!exact) {
for (var i = _max - 1; i >= 0; i--) {
if (namespace[i].type === 'total') {
_max = i + 1;
break;
}
_max = i;
}
}
var map = this.virtualListeners.getDefault(namespace, function () { return new Map(); }, _max);
if (!map.has(eventType)) {
map.set(eventType, new PriorityQueue_1.default());
}
return map.get(eventType);
};
EventDelegator.prototype.setupDOMListener = function (eventType, passive) {
var _this = this;
if (this.origin) {
var sub = fromEvent_1.fromEvent(this.origin, eventType, false, false, passive).subscribe({
next: function (event) { return _this.onEvent(eventType, event, passive); },
error: function () { },
complete: function () { },
});
this.domListeners.set(eventType, { sub: sub, passive: passive });
}
else {
this.domListenersToAdd.set(eventType, passive);
}
};
EventDelegator.prototype.setupNonBubblingListener = function (input) {
var _this = this;
var eventType = input[0], elementFinder = input[1], destination = input[2];
if (!this.origin) {
this.nonBubblingListenersToAdd.add(input);
return;
}
var element = elementFinder.call()[0];
if (element) {
this.nonBubblingListenersToAdd.delete(input);
var sub = fromEvent_1.fromEvent(element, eventType, false, false, destination.passive).subscribe({
next: function (ev) { return _this.onEvent(eventType, ev, !!destination.passive, false); },
error: function () { },
complete: function () { },
});
if (!this.nonBubblingListeners.has(eventType)) {
this.nonBubblingListeners.set(eventType, new Map());
}
var map = this.nonBubblingListeners.get(eventType);
if (!map) {
return;
}
map.set(element, { sub: sub, destination: destination });
}
else {
this.nonBubblingListenersToAdd.add(input);
}
};
EventDelegator.prototype.resetEventListeners = function () {
var iter = this.domListeners.entries();
var curr = iter.next();
while (!curr.done) {
var _a = curr.value, type = _a[0], _b = _a[1], sub = _b.sub, passive = _b.passive;
sub.unsubscribe();
this.setupDOMListener(type, passive);
curr = iter.next();
}
};
EventDelegator.prototype.resetNonBubblingListeners = function () {
var _this = this;
var newMap = new Map();
var insert = utils_1.makeInsert(newMap);
this.nonBubblingListeners.forEach(function (map, type) {
map.forEach(function (value, elm) {
if (!document.body.contains(elm)) {
var sub = value.sub, destination_1 = value.destination;
if (sub) {
sub.unsubscribe();
}
var elementFinder = new ElementFinder_1.ElementFinder(destination_1.scopeChecker.namespace, _this.isolateModule);
var newElm = elementFinder.call()[0];
var newSub = fromEvent_1.fromEvent(newElm, type, false, false, destination_1.passive).subscribe({
next: function (event) {
return _this.onEvent(type, event, !!destination_1.passive, false);
},
error: function () { },
complete: function () { },
});
insert(type, newElm, { sub: newSub, destination: destination_1 });
}
else {
insert(type, elm, value);
}
});
_this.nonBubblingListeners = newMap;
});
};
EventDelegator.prototype.putNonBubblingListener = function (eventType, elm, useCapture, passive) {
var map = this.nonBubblingListeners.get(eventType);
if (!map) {
return;
}
var listener = map.get(elm);
if (listener &&
listener.destination.passive === passive &&
listener.destination.useCapture === useCapture) {
this.virtualNonBubblingListener[0] = listener.destination;
}
};
EventDelegator.prototype.onEvent = function (eventType, event, passive, bubbles) {
if (bubbles === void 0) { bubbles = true; }
var cycleEvent = this.patchEvent(event);
var rootElement = this.isolateModule.getRootElement(event.target);
if (bubbles) {
var namespace = this.isolateModule.getNamespace(event.target);
if (!namespace) {
return;
}
var listeners = this.getVirtualListeners(eventType, namespace);
this.bubble(eventType, event.target, rootElement, cycleEvent, listeners, namespace, namespace.length - 1, true, passive);
this.bubble(eventType, event.target, rootElement, cycleEvent, listeners, namespace, namespace.length - 1, false, passive);
}
else {
this.putNonBubblingListener(eventType, event.target, true, passive);
this.doBubbleStep(eventType, event.target, rootElement, cycleEvent, this.virtualNonBubblingListener, true, passive);
this.putNonBubblingListener(eventType, event.target, false, passive);
this.doBubbleStep(eventType, event.target, rootElement, cycleEvent, this.virtualNonBubblingListener, false, passive);
event.stopPropagation(); //fix reset event (spec'ed as non-bubbling, but bubbles in reality
}
};
EventDelegator.prototype.bubble = function (eventType, elm, rootElement, event, listeners, namespace, index, useCapture, passive) {
if (!useCapture && !event.propagationHasBeenStopped) {
this.doBubbleStep(eventType, elm, rootElement, event, listeners, useCapture, passive);
}
var newRoot = rootElement;
var newIndex = index;
if (elm === rootElement) {
if (index >= 0 && namespace[index].type === 'sibling') {
newRoot = this.isolateModule.getElement(namespace, index);
newIndex--;
}
else {
return;
}
}
if (elm.parentNode && newRoot) {
this.bubble(eventType, elm.parentNode, newRoot, event, listeners, namespace, newIndex, useCapture, passive);
}
if (useCapture && !event.propagationHasBeenStopped) {
this.doBubbleStep(eventType, elm, rootElement, event, listeners, useCapture, passive);
}
};
EventDelegator.prototype.doBubbleStep = function (eventType, elm, rootElement, event, listeners, useCapture, passive) {
if (!rootElement) {
return;
}
this.mutateEventCurrentTarget(event, elm);
listeners.forEach(function (dest) {
if (dest.passive === passive && dest.useCapture === useCapture) {
var sel = utils_1.getSelectors(dest.scopeChecker.namespace);
if (!event.propagationHasBeenStopped &&
dest.scopeChecker.isDirectlyInScope(elm) &&
((sel !== '' && elm.matches(sel)) ||
(sel === '' && elm === rootElement))) {
fromEvent_1.preventDefaultConditional(event, dest.preventDefault);
dest.subject.shamefullySendNext(event);
}
}
});
};
EventDelegator.prototype.patchEvent = function (event) {
var pEvent = event;
pEvent.propagationHasBeenStopped = false;
var oldStopPropagation = pEvent.stopPropagation;
pEvent.stopPropagation = function stopPropagation() {
oldStopPropagation.call(this);
this.propagationHasBeenStopped = true;
};
return pEvent;
};
EventDelegator.prototype.mutateEventCurrentTarget = function (event, currentTargetElement) {
try {
Object.defineProperty(event, "currentTarget", {
value: currentTargetElement,
configurable: true,
});
}
catch (err) {
console.log("please use event.ownerTarget");
}
event.ownerTarget = currentTargetElement;
};
return EventDelegator;
}());
exports.EventDelegator = EventDelegator;
},{"./ElementFinder":5,"./PriorityQueue":9,"./RemovalSet":10,"./ScopeChecker":11,"./SymbolTree":12,"./fromEvent":14,"./utils":22,"xstream":259}],7:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var utils_1 = require("./utils");
var SymbolTree_1 = require("./SymbolTree");
var IsolateModule = /** @class */ (function () {
function IsolateModule() {
this.namespaceTree = new SymbolTree_1.default(function (x) { return x.scope; });
this.namespaceByElement = new Map();
this.vnodesBeingRemoved = [];
}
IsolateModule.prototype.setEventDelegator = function (del) {
this.eventDelegator = del;
};
IsolateModule.prototype.insertElement = function (namespace, el) {
this.namespaceByElement.set(el, namespace);
this.namespaceTree.set(namespace, el);
};
IsolateModule.prototype.removeElement = function (elm) {
this.namespaceByElement.delete(elm);
var namespace = this.getNamespace(elm);
if (namespace) {
this.namespaceTree.delete(namespace);
}
};
IsolateModule.prototype.getElement = function (namespace, max) {
return this.namespaceTree.get(namespace, undefined, max);
};
IsolateModule.prototype.getRootElement = function (elm) {
if (this.namespaceByElement.has(elm)) {
return elm;
}
//TODO: Add quick-lru or similar as additional O(1) cache
var curr = elm;
while (!this.namespaceByElement.has(curr)) {
curr = curr.parentNode;
if (!curr) {
return undefined;
}
else if (curr.tagName === 'HTML') {
throw new Error('No root element found, this should not happen at all');
}
}
return curr;
};
IsolateModule.prototype.getNamespace = function (elm) {
var rootElement = this.getRootElement(elm);
if (!rootElement) {
return undefined;
}
return this.namespaceByElement.get(rootElement);
};
IsolateModule.prototype.createModule = function () {
var self = this;
return {
create: function (emptyVNode, vNode) {
var elm = vNode.elm, _a = vNode.data, data = _a === void 0 ? {} : _a;
var namespace = data.isolate;
if (Array.isArray(namespace)) {
self.insertElement(namespace, elm);
}
},
update: function (oldVNode, vNode) {
var oldElm = oldVNode.elm, _a = oldVNode.data, oldData = _a === void 0 ? {} : _a;
var elm = vNode.elm, _b = vNode.data, data = _b === void 0 ? {} : _b;
var oldNamespace = oldData.isolate;
var namespace = data.isolate;
if (!utils_1.isEqualNamespace(oldNamespace, namespace)) {
if (Array.isArray(oldNamespace)) {
self.removeElement(oldElm);
}
}
if (Array.isArray(namespace)) {
self.insertElement(namespace, elm);
}
},
destroy: function (vNode) {
self.vnodesBeingRemoved.push(vNode);
},
remove: function (vNode, cb) {
self.vnodesBeingRemoved.push(vNode);
cb();
},
post: function () {
var vnodesBeingRemoved = self.vnodesBeingRemoved;
for (var i = vnodesBeingRemoved.length - 1; i >= 0; i--) {
var vnode = vnodesBeingRemoved[i];
var namespace = vnode.data !== undefined
? vnode.data.isolation
: undefined;
if (namespace !== undefined) {
self.removeElement(namespace);
}
self.eventDelegator.removeElement(vnode.elm, namespace);
}
self.vnodesBeingRemoved = [];
},
};
};
return IsolateModule;
}());
exports.IsolateModule = IsolateModule;
},{"./SymbolTree":12,"./utils":22}],8:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var adapt_1 = require("@cycle/run/lib/adapt");
var DocumentDOMSource_1 = require("./DocumentDOMSource");
var BodyDOMSource_1 = require("./BodyDOMSource");
var ElementFinder_1 = require("./ElementFinder");
var isolate_1 = require("./isolate");
var MainDOMSource = /** @class */ (function () {
function MainDOMSource(_rootElement$, _sanitation$, _namespace, _isolateModule, _eventDelegator, _name) {
if (_namespace === void 0) { _namespace = []; }
this._rootElement$ = _rootElement$;
this._sanitation$ = _sanitation$;
this._namespace = _namespace;
this._isolateModule = _isolateModule;
this._eventDelegator = _eventDelegator;
this._name = _name;
this.isolateSource = function (source, scope) {
return new MainDOMSource(source._rootElement$, source._sanitation$, source._namespace.concat(isolate_1.getScopeObj(scope)), source._isolateModule, source._eventDelegator, source._name);
};
this.isolateSink = isolate_1.makeIsolateSink(this._namespace);
}
MainDOMSource.prototype._elements = function () {
if (this._namespace.length === 0) {
return this._rootElement$.map(function (x) { return [x]; });
}
else {
var elementFinder_1 = new ElementFinder_1.ElementFinder(this._namespace, this._isolateModule);
return this._rootElement$.map(function () { return elementFinder_1.call(); });
}
};
MainDOMSource.prototype.elements = function () {
var out = adapt_1.adapt(this._elements().remember());
out._isCycleSource = this._name;
return out;
};
MainDOMSource.prototype.element = function () {
var out = adapt_1.adapt(this._elements()
.filter(function (arr) { return arr.length > 0; })
.map(function (arr) { return arr[0]; })
.remember());
out._isCycleSource = this._name;
return out;
};
Object.defineProperty(MainDOMSource.prototype, "namespace", {
get: function () {
return this._namespace;
},
enumerable: true,
configurable: true
});
MainDOMSource.prototype.select = function (selector) {
if (typeof selector !== 'string') {
throw new Error("DOM driver's select() expects the argument to be a " +
"string as a CSS selector");
}
if (selector === 'document') {
return new DocumentDOMSource_1.DocumentDOMSource(this._name);
}
if (selector === 'body') {
return new BodyDOMSource_1.BodyDOMSource(this._name);
}
var namespace = selector === ':root'
? []
: this._namespace.concat({ type: 'selector', scope: selector.trim() });
return new MainDOMSource(this._rootElement$, this._sanitation$, namespace, this._isolateModule, this._eventDelegator, this._name);
};
MainDOMSource.prototype.events = function (eventType, options, bubbles) {
if (options === void 0) { options = {}; }
if (typeof eventType !== "string") {
throw new Error("DOM driver's events() expects argument to be a " +
"string representing the event type to listen for.");
}
var event$ = this._eventDelegator.addEventListener(eventType, this._namespace, options, bubbles);
var out = adapt_1.adapt(event$);
out._isCycleSource = this._name;
return out;
};
MainDOMSource.prototype.dispose = function () {
this._sanitation$.shamefullySendNext(null);
//this._isolateModule.reset();
};
return MainDOMSource;
}());
exports.MainDOMSource = MainDOMSource;
},{"./BodyDOMSource":3,"./DocumentDOMSource":4,"./ElementFinder":5,"./isolate":17,"@cycle/run/lib/adapt":24}],9:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var PriorityQueue = /** @class */ (function () {
function PriorityQueue() {
this.arr = [];
this.prios = [];
}
PriorityQueue.prototype.add = function (t, prio) {
for (var i = 0; i < this.arr.length; i++) {
if (this.prios[i] < prio) {
this.arr.splice(i, 0, t);
this.prios.splice(i, 0, prio);
return;
}
}
this.arr.push(t);
this.prios.push(prio);
};
PriorityQueue.prototype.forEach = function (f) {
for (var i = 0; i < this.arr.length; i++) {
f(this.arr[i], i, this.arr);
}
};
PriorityQueue.prototype.delete = function (t) {
for (var i = 0; i < this.arr.length; i++) {
if (this.arr[i] === t) {
this.arr.splice(i, 1);
this.prios.splice(i, 1);
return;
}
}
};
return PriorityQueue;
}());
exports.default = PriorityQueue;
},{}],10:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var RemovalSet = /** @class */ (function () {
function RemovalSet() {
this.toDelete = [];
this.toDeleteSize = 0;
this._set = new Set();
}
RemovalSet.prototype.add = function (t) {
this._set.add(t);
};
RemovalSet.prototype.forEach = function (f) {
this._set.forEach(f);
this.flush();
};
RemovalSet.prototype.delete = function (t) {
if (this.toDelete.length === this.toDeleteSize) {
this.toDelete.push(t);
}
else {
this.toDelete[this.toDeleteSize] = t;
}
this.toDeleteSize++;
};
RemovalSet.prototype.flush = function () {
for (var i = 0; i < this.toDelete.length; i++) {
if (i < this.toDeleteSize) {
this._set.delete(this.toDelete[i]);
}
this.toDelete[i] = undefined;
}
this.toDeleteSize = 0;
};
return RemovalSet;
}());
exports.default = RemovalSet;
},{}],11:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var utils_1 = require("./utils");
var ScopeChecker = /** @class */ (function () {
function ScopeChecker(namespace, isolateModule) {
this.namespace = namespace;
this.isolateModule = isolateModule;
this._namespace = namespace.filter(function (n) { return n.type !== 'selector'; });
}
/**
* Checks whether the given element is *directly* in the scope of this
* scope checker. Being contained *indirectly* through other scopes
* is not valid. This is crucial for implementing parent-child isolation,
* so that the parent selectors don't search inside a child scope.
*/
ScopeChecker.prototype.isDirectlyInScope = function (leaf) {
var namespace = this.isolateModule.getNamespace(leaf);
if (!namespace) {
return false;
}
if (this._namespace.length > namespace.length ||
!utils_1.isEqualNamespace(this._namespace, namespace.slice(0, this._namespace.length))) {
return false;
}
for (var i = this._namespace.length; i < namespace.length; i++) {
if (namespace[i].type === 'total') {
return false;
}
}
return true;
};
return ScopeChecker;
}());
exports.ScopeChecker = ScopeChecker;
},{"./utils":22}],12:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var SymbolTree = /** @class */ (function () {
function SymbolTree(mapper) {
this.mapper = mapper;
this.tree = [undefined, {}];
}
SymbolTree.prototype.set = function (path, element, max) {
var curr = this.tree;
var _max = max !== undefined ? max : path.length;
for (var i = 0; i < _max; i++) {
var n = this.mapper(path[i]);
var child = curr[1][n];
if (!child) {
child = [undefined, {}];
curr[1][n] = child;
}
curr = child;
}
curr[0] = element;
};
SymbolTree.prototype.getDefault = function (path, mkDefaultElement, max) {
return this.get(path, mkDefaultElement, max);
};
/**
* Returns the payload of the path
* If a default element creator is given, it will insert it at the path
*/
SymbolTree.prototype.get = function (path, mkDefaultElement, max) {
var curr = this.tree;
var _max = max !== undefined ? max : path.length;
for (var i = 0; i < _max; i++) {
var n = this.mapper(path[i]);
var child = curr[1][n];
if (!child) {
if (mkDefaultElement) {
child = [undefined, {}];
curr[1][n] = child;
}
else {
return undefined;
}
}
curr = child;
}
if (mkDefaultElement && !curr[0]) {
curr[0] = mkDefaultElement();
}
return curr[0];
};
SymbolTree.prototype.delete = function (path) {
var curr = this.tree;
for (var i = 0; i < path.length - 1; i++) {
var child = curr[1][this.mapper(path[i])];
if (!child) {
return;
}
curr = child;
}
delete curr[1][this.mapper(path[path.length - 1])];
};
return SymbolTree;
}());
exports.default = SymbolTree;
},{}],13:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var vnode_1 = require("snabbdom/vnode");
var h_1 = require("snabbdom/h");
var snabbdom_selector_1 = require("snabbdom-selector");
var utils_1 = require("./utils");
var VNodeWrapper = /** @class */ (function () {
function VNodeWrapper(rootElement) {
this.rootElement = rootElement;
}
VNodeWrapper.prototype.call = function (vnode) {
if (utils_1.isDocFrag(this.rootElement)) {
return this.wrapDocFrag(vnode === null ? [] : [vnode]);
}
if (vnode === null) {
return this.wrap([]);
}
var _a = snabbdom_selector_1.selectorParser(vnode), selTagName = _a.tagName, selId = _a.id;
var vNodeClassName = snabbdom_selector_1.classNameFromVNode(vnode);
var vNodeData = vnode.data || {};
var vNodeDataProps = vNodeData.props || {};
var _b = vNodeDataProps.id, vNodeId = _b === void 0 ? selId : _b;
var isVNodeAndRootElementIdentical = typeof vNodeId === 'string' &&
vNodeId.toUpperCase() === this.rootElement.id.toUpperCase() &&
selTagName.toUpperCase() === this.rootElement.tagName.toUpperCase() &&
vNodeClassName.toUpperCase() === this.rootElement.className.toUpperCase();
if (isVNodeAndRootElementIdentical) {
return vnode;
}
return this.wrap([vnode]);
};
VNodeWrapper.prototype.wrapDocFrag = function (children) {
return vnode_1.vnode('', { isolate: [] }, children, undefined, this
.rootElement);
};
VNodeWrapper.prototype.wrap = function (children) {
var _a = this.rootElement, tagName = _a.tagName, id = _a.id, className = _a.className;
var selId = id ? "#" + id : '';
var selClass = className ? "." + className.split(" ").join(".") : '';
var vnode = h_1.h("" + tagName.toLowerCase() + selId + selClass, {}, children);
vnode.data = vnode.data || {};
vnode.data.isolate = vnode.data.isolate || [];
return vnode;
};
return VNodeWrapper;
}());
exports.VNodeWrapper = VNodeWrapper;
},{"./utils":22,"snabbdom-selector":234,"snabbdom/h":238,"snabbdom/vnode":249}],14:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var xstream_1 = require("xstream");
function fromEvent(element, eventName, useCapture, preventDefault, passive) {
if (useCapture === void 0) { useCapture = false; }
if (preventDefault === void 0) { preventDefault = false; }
if (passive === void 0) { passive = false; }
var next = null;
return xstream_1.Stream.create({
start: function start(listener) {
if (preventDefault) {
next = function _next(event) {
preventDefaultConditional(event, preventDefault);
listener.next(event);
};
}
else {
next = function _next(event) {
listener.next(event);
};
}
element.addEventListener(eventName, next, {
capture: useCapture,
passive: passive,
});
},
stop: function stop() {
element.removeEventListener(eventName, next, useCapture);
},
});
}
exports.fromEvent = fromEvent;
function matchObject(matcher, obj) {
var keys = Object.keys(matcher);
var n = keys.length;
for (var i = 0; i < n; i++) {
var k = keys[i];
if (typeof matcher[k] === 'object' && typeof obj[k] === 'object') {
if (!matchObject(matcher[k], obj[k])) {
return false;
}
}
else if (matcher[k] !== obj[k]) {
return false;
}
}
return true;
}
function preventDefaultConditional(event, preventDefault) {
if (preventDefault) {
if (typeof preventDefault === 'boolean') {
event.preventDefault();
}
else if (isPredicate(preventDefault)) {
if (preventDefault(event)) {
event.preventDefault();
}
}
else if (typeof preventDefault === 'object') {
if (matchObject(preventDefault, event)) {
event.preventDefault();
}
}
else {
throw new Error('preventDefault has to be either a boolean, predicate function or object');
}
}
}
exports.preventDefaultConditional = preventDefaultConditional;
function isPredicate(fn) {
return typeof fn === 'function';
}
},{"xstream":259}],15:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// tslint:disable:max-file-line-count
var h_1 = require("snabbdom/h");
function isValidString(param) {
return typeof param === 'string' && param.length > 0;
}
function isSelector(param) {
return isValidString(param) && (param[0] === '.' || param[0] === '#');
}
function createTagFunction(tagName) {
return function hyperscript(a, b, c) {
var hasA = typeof a !== 'undefined';
var hasB = typeof b !== 'undefined';
var hasC = typeof c !== 'undefined';
if (isSelector(a)) {
if (hasB && hasC) {
return h_1.h(tagName + a, b, c);
}
else if (hasB) {
return h_1.h(tagName + a, b);
}
else {
return h_1.h(tagName + a, {});
}
}
else if (hasC) {
return h_1.h(tagName + a, b, c);
}
else if (hasB) {
return h_1.h(tagName, a, b);
}
else if (hasA) {
return h_1.h(tagName, a);
}