Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
* As soon as the window is back to 0 (idle), scroll the toolbar and socket back into place on scroll.
*/
scroller.idle(function () {
IosUpdates.updatePositions(container, outerWindow.pageYOffset).get(function (/* _ */) {
const extraScroll = scrollBounds();
extraScroll.each(function (extra) {
// TODO: Smoothly animate this in a way that doesn't conflict with anything else.
socket.dom().scrollTop = socket.dom().scrollTop + extra.top();
});
scroller.start(0);
structure.refresh();
});
});
}, 1000);
const onScroll = DomEvent.bind(Element.fromDom(outerWindow), 'scroll', function () {
if (outerWindow.pageYOffset < 0) {
return;
}
/*
We've experimented with trying to set the socket scroll (hidden vs. scroll) based on whether the outer body
has scrolled. When the window starts scrolling, we would lock the socket scroll, and we would
unlock it when the window stopped scrolling. This would give a nice rubber-band effect at the end
of the content, but would break the code that tried to position the text in the viewable area
(more details below). Also, as soon as you flicked to outer scroll, if you started scrolling up again,
you would drag the whole window down, because you would still be in outerscroll mode. That's hardly
much of a problem, but it is a minor issue. It also didn't play nicely with keeping the toolbar on the screen.
The big problem was that this was incompatible with the toolbar and scrolling code. We need a padding inside
the socket so that the bottom of the content can be scrolled into the viewable greenzone. If it doesn't
have padding, then unless we move the socket top to some negative value as well, then we can't get
editorApi.getCursorBox().each(function (bounds) {
const cWin = editorApi.win();
// The goal here is to shift as little as required.
const isOutside = bounds.top() > cWin.innerHeight || bounds.bottom() > cWin.innerHeight;
const cScrollBy = isOutside ? bounds.bottom() - cWin.innerHeight + 50 /*EXTRA_SPACING*/ : 0;
if (cScrollBy !== 0) {
cWin.scrollTo(cWin.pageXOffset, cWin.pageYOffset + cScrollBy);
}
});
})
].concat(
isAndroid6 === true ? [ ] : [
DomEvent.bind(Element.fromDom(editorApi.win()), 'blur', function () {
alloy.getByDom(toolstrip).each(Toggling.off);
}),
DomEvent.bind(outerDoc, 'select', updateMargin),
DomEvent.bind(editorApi.doc(), 'selectionchange', updateMargin)
]
);
const destroy = function () {
Arr.each(listeners, function (l) {
l.unbind();
});
};
return {
destroy
};
};
const hasRangeInUi = function () {
return Focus.active(outerDoc).filter(function (input) {
return Node.name(input) === 'input';
}).exists(function (input: Element) {
return input.dom().selectionStart !== input.dom().selectionEnd;
});
};
const updateMargin = function () {
const rangeInContent = editorApi.doc().dom().hasFocus() && editorApi.getSelection().exists(isRanged);
alloy.getByDom(toolstrip).each((rangeInContent || hasRangeInUi()) === true ? Toggling.on : Toggling.off);
};
const listeners = [
DomEvent.bind(editorApi.body(), 'touchstart', function (evt) {
editorApi.onTouchContent();
tapping.fireTouchstart(evt);
}),
tapping.onTouchmove(),
tapping.onTouchend(),
DomEvent.bind(toolstrip, 'touchstart', function (evt) {
editorApi.onTouchToolstrip();
}),
editorApi.onToReading(function () {
Focus.blur(editorApi.body());
}),
editorApi.onToEditing(Fun.noop),
// Scroll to cursor and update the iframe height
const broadcastOn = (channel: string, message: Record) => {
Arr.each([ mothership, uiMothership ], (ship) => {
ship.broadcastOn([ channel ], message);
});
};
const fireDismissPopups = (evt: EventArgs) => broadcastOn(Channels.dismissPopups(), { target: evt.target() });
// Document touch events
const onTouchstart = DomEvent.bind(Element.fromDom(document), 'touchstart', fireDismissPopups);
const onTouchmove = DomEvent.bind(Element.fromDom(document), 'touchmove', (evt) => broadcastEvent(SystemEvents.documentTouchmove(), evt));
const onTouchend = DomEvent.bind(Element.fromDom(document), 'touchend', (evt) => broadcastEvent(SystemEvents.documentTouchend(), evt));
// Document mouse events
const onMousedown = DomEvent.bind(Element.fromDom(document), 'mousedown', fireDismissPopups);
const onMouseup = DomEvent.bind(Element.fromDom(document), 'mouseup', (evt) => {
if (evt.raw().button === 0) {
broadcastOn(Channels.mouseReleased(), { target: evt.target() });
}
});
// Editor content events
const onContentClick = (raw: UIEvent) => broadcastOn(Channels.dismissPopups(), { target: Element.fromDom(raw.target as DomNode) });
const onContentMouseup = (raw: MouseEvent) => {
if (raw.button === 0) {
broadcastOn(Channels.mouseReleased(), { target: Element.fromDom(raw.target as DomNode) });
}
};
// Window events
const onWindowScroll = (evt: UIEvent) => broadcastEvent(SystemEvents.windowScroll(), DomEvent.fromRawEvent(evt));
const onWindowResize = (evt: UIEvent) => {
const broadcastOn = (channel: string, message: Record) => {
Arr.each([ mothership, uiMothership ], (ship) => {
ship.broadcastOn([ channel ], message);
});
};
const fireDismissPopups = (evt: EventArgs) => broadcastOn(Channels.dismissPopups(), { target: evt.target() });
// Document touch events
const onTouchstart = DomEvent.bind(Element.fromDom(document), 'touchstart', fireDismissPopups);
const onTouchmove = DomEvent.bind(Element.fromDom(document), 'touchmove', (evt) => broadcastEvent(SystemEvents.documentTouchmove(), evt));
const onTouchend = DomEvent.bind(Element.fromDom(document), 'touchend', (evt) => broadcastEvent(SystemEvents.documentTouchend(), evt));
// Document mouse events
const onMousedown = DomEvent.bind(Element.fromDom(document), 'mousedown', fireDismissPopups);
const onMouseup = DomEvent.bind(Element.fromDom(document), 'mouseup', (evt) => {
if (evt.raw().button === 0) {
broadcastOn(Channels.mouseReleased(), { target: evt.target() });
}
});
// Editor content events
const onContentClick = (raw: UIEvent) => broadcastOn(Channels.dismissPopups(), { target: Element.fromDom(raw.target as DomNode) });
const onContentMouseup = (raw: MouseEvent) => {
if (raw.button === 0) {
broadcastOn(Channels.mouseReleased(), { target: Element.fromDom(raw.target as DomNode) });
}
};
// Window events
const onWindowScroll = (evt: UIEvent) => broadcastEvent(SystemEvents.windowScroll(), DomEvent.fromRawEvent(evt));
Arr.each([ mothership, uiMothership ], (ship) => {
ship.broadcastEvent(name, evt);
});
};
const broadcastOn = (channel: string, message: Record) => {
Arr.each([ mothership, uiMothership ], (ship) => {
ship.broadcastOn([ channel ], message);
});
};
const fireDismissPopups = (evt: EventArgs) => broadcastOn(Channels.dismissPopups(), { target: evt.target() });
// Document touch events
const onTouchstart = DomEvent.bind(Element.fromDom(document), 'touchstart', fireDismissPopups);
const onTouchmove = DomEvent.bind(Element.fromDom(document), 'touchmove', (evt) => broadcastEvent(SystemEvents.documentTouchmove(), evt));
const onTouchend = DomEvent.bind(Element.fromDom(document), 'touchend', (evt) => broadcastEvent(SystemEvents.documentTouchend(), evt));
// Document mouse events
const onMousedown = DomEvent.bind(Element.fromDom(document), 'mousedown', fireDismissPopups);
const onMouseup = DomEvent.bind(Element.fromDom(document), 'mouseup', (evt) => {
if (evt.raw().button === 0) {
broadcastOn(Channels.mouseReleased(), { target: evt.target() });
}
});
// Editor content events
const onContentClick = (raw: UIEvent) => broadcastOn(Channels.dismissPopups(), { target: Element.fromDom(raw.target as DomNode) });
const onContentMouseup = (raw: MouseEvent) => {
if (raw.button === 0) {
broadcastOn(Channels.mouseReleased(), { target: Element.fromDom(raw.target as DomNode) });
}
keyboardModel.onToolbarTouch(event);
};
const onOrientation = Orientation.onChange(outerWindow, {
onChange: Fun.noop,
onReady: structure.refresh
});
// NOTE: When the window is resizing (probably due to meta tags and viewport definitions), we are not receiving a window resize event.
// However, it happens shortly after we start Ios mode, so here we just wait for the first window size event that we get. This code
// is also the same code that is used for the Orientation ready event.
onOrientation.onAdjustment(function () {
structure.refresh();
});
const onResize = DomEvent.bind(Element.fromDom(outerWindow), 'resize', function () {
if (structure.isExpanding()) {
structure.refresh();
}
});
const onScroll = register(toolstrip, socket, bag.outerBody(), outerWindow, structure, cWin);
const unfocusedSelection = FakeSelection(cWin, contentElement);
const refreshSelection = function () {
if (unfocusedSelection.isActive()) {
unfocusedSelection.update();
}
};
const highlightSelection = function () {
ship.broadcastEvent(name, evt);
});
};
const broadcastOn = (channel: string, message: Record) => {
Arr.each([ mothership, uiMothership ], (ship) => {
ship.broadcastOn([ channel ], message);
});
};
const fireDismissPopups = (evt: EventArgs) => broadcastOn(Channels.dismissPopups(), { target: evt.target() });
// Document touch events
const onTouchstart = DomEvent.bind(Element.fromDom(document), 'touchstart', fireDismissPopups);
const onTouchmove = DomEvent.bind(Element.fromDom(document), 'touchmove', (evt) => broadcastEvent(SystemEvents.documentTouchmove(), evt));
const onTouchend = DomEvent.bind(Element.fromDom(document), 'touchend', (evt) => broadcastEvent(SystemEvents.documentTouchend(), evt));
// Document mouse events
const onMousedown = DomEvent.bind(Element.fromDom(document), 'mousedown', fireDismissPopups);
const onMouseup = DomEvent.bind(Element.fromDom(document), 'mouseup', (evt) => {
if (evt.raw().button === 0) {
broadcastOn(Channels.mouseReleased(), { target: evt.target() });
}
});
// Editor content events
const onContentClick = (raw: UIEvent) => broadcastOn(Channels.dismissPopups(), { target: Element.fromDom(raw.target as DomNode) });
const onContentMouseup = (raw: MouseEvent) => {
if (raw.button === 0) {
broadcastOn(Channels.mouseReleased(), { target: Element.fromDom(raw.target as DomNode) });
}
};
const broadcastEvent = (name: string, evt: EventArgs) => {
Arr.each([ mothership, uiMothership ], (ship) => {
ship.broadcastEvent(name, evt);
});
};
const broadcastOn = (channel: string, message: Record) => {
Arr.each([ mothership, uiMothership ], (ship) => {
ship.broadcastOn([ channel ], message);
});
};
const fireDismissPopups = (evt: EventArgs) => broadcastOn(Channels.dismissPopups(), { target: evt.target() });
// Document touch events
const onTouchstart = DomEvent.bind(Element.fromDom(document), 'touchstart', fireDismissPopups);
const onTouchmove = DomEvent.bind(Element.fromDom(document), 'touchmove', (evt) => broadcastEvent(SystemEvents.documentTouchmove(), evt));
const onTouchend = DomEvent.bind(Element.fromDom(document), 'touchend', (evt) => broadcastEvent(SystemEvents.documentTouchend(), evt));
// Document mouse events
const onMousedown = DomEvent.bind(Element.fromDom(document), 'mousedown', fireDismissPopups);
const onMouseup = DomEvent.bind(Element.fromDom(document), 'mouseup', (evt) => {
if (evt.raw().button === 0) {
broadcastOn(Channels.mouseReleased(), { target: evt.target() });
}
});
// Editor content events
const onContentClick = (raw: UIEvent) => broadcastOn(Channels.dismissPopups(), { target: Element.fromDom(raw.target as DomNode) });
const onContentMouseup = (raw: MouseEvent) => {
if (raw.button === 0) {
broadcastOn(Channels.mouseReleased(), { target: Element.fromDom(raw.target as DomNode) });
return function (handler) {
return DomEvent.bind(doc, type, handler);
};
});