define(
'tinymce.themes.mobile.ios.core.IosEvents',
[
'ephox.alloy.events.TapEvent',
'ephox.katamari.api.Arr',
'ephox.katamari.api.Throttler',
'ephox.sugar.api.dom.Compare',
'ephox.sugar.api.events.DomEvent',
'ephox.sugar.api.view.Height',
'ephox.sugar.api.view.Location',
'tinymce.themes.mobile.util.TappingEvent'
],
function (TapEvent, Arr, Throttler, Compare, DomEvent, Height, Location, TappingEvent) {
var initEvents = function (editorApi, iosApi, toolstrip, socket, dropup) {
var saveSelectionFirst = function () {
iosApi.run(function (api) {
api.highlightSelection();
});
};
var refreshIosSelection = function () {
iosApi.run(function (api) {
api.refreshSelection();
});
};
var scrollToY = function (yTop, height) {
// Because the iframe has no scroll, and the socket is the part that scrolls,
// anything visible inside the iframe actually has a top value (for bounding
// rectangle) > socket.scrollTop. The rectangle is with respect to the top of
// the iframe, which has scrolled up above the socket viewport.
var y = yTop - socket.dom().scrollTop;
iosApi.run(function (api) {
api.scrollIntoView(y, y + height);
});
};
var scrollToElement = function (target) {
var yTop = Location.absolute(target).top();
var height = Height.get(target);
scrollToY(iosApi, socket, yTop, height);
};
var scrollToCursor = function () {
editorApi.getCursorBox().each(function (box) {
scrollToY(box.top(), box.height());
});
};
var clearSelection = function () {
// Clear any fake selections visible.
iosApi.run(function (api) {
api.clearSelection();
});
};
var clearAndRefresh = function () {
clearSelection();
refreshThrottle.throttle();
};
var refreshView = function () {
scrollToCursor(editorApi, iosApi, socket);
iosApi.run(function (api) {
api.syncHeight();
});
};
var reposition = function () {
var toolbarHeight = Height.get(toolstrip);
iosApi.run(function (api) {
api.setViewportOffset(toolbarHeight);
});
refreshIosSelection(iosApi);
refreshView(editorApi, iosApi, socket);
};
var toEditing = function () {
iosApi.run(function (api) {
api.toEditing();
});
};
var toReading = function () {
iosApi.run(function (api) {
api.toReading();
});
};
var onToolbarTouch = function (event) {
iosApi.run(function (api) {
api.onToolbarTouch(event);
});
};
var tapping = TappingEvent.monitor(editorApi);
var refreshThrottle = Throttler.last(refreshView, 300);
var listeners = [
// Clear any fake selections, scroll to cursor, and update the iframe height
editorApi.onKeyup(clearAndRefresh),
// Update any fake selections that are showing
editorApi.onNodeChanged(refreshIosSelection),
// Scroll to cursor, and update the iframe height
editorApi.onDomChanged(refreshThrottle.throttle),
// Update any fake selections that are showing
editorApi.onDomChanged(refreshIosSelection),
// Scroll to cursor and update the iframe height
editorApi.onScrollToCursor(function (tinyEvent) {
tinyEvent.preventDefault();
refreshThrottle.throttle();
}),
// Scroll to element
editorApi.onScrollToElement(function (event) {
scrollToElement(event.element());
}),
// Focus the content and show the keyboard
editorApi.onToEditing(toEditing),
// Dismiss keyboard
editorApi.onToReading(toReading),
// If the user is touching outside the content, but on the body(?) or html elements, find the nearest selection
// and focus that.
DomEvent.bind(editorApi.doc(), 'touchend', function (touchEvent) {
if (Compare.eq(editorApi.html(), touchEvent.target()) || Compare.eq(editorApi.body(), touchEvent.target())) {
// IosHacks.setSelectionAtTouch(editorApi, touchEvent);
}
}),
// Listen to the toolstrip growing animation so that we can update the position of the socket once it is done.
DomEvent.bind(toolstrip, 'transitionend', function (transitionEvent) {
if (transitionEvent.raw().propertyName === 'height') {
reposition();
}
}),
// Capture the start of interacting with a toolstrip. It is most likely going to lose the selection, so we save it
// before that happens
DomEvent.capture(toolstrip, 'touchstart', function (touchEvent) {
// When touching the toolbar, the first thing that we need to do is 'represent' the selection. We do this with
// a fake selection. As soon as the focus switches away from the content, the real selection will disappear, so
// this lets the user still see their selection.
saveSelectionFirst();
// Then, depending on the keyboard mode, we may need to do something else (like dismiss the keyboard)
onToolbarTouch(touchEvent);
// Fire the touchstart event to the theme for things like hiding dropups
editorApi.onTouchToolstrip();
}),
// When the user clicks back into the content, clear any fake selections
DomEvent.bind(editorApi.body(), 'touchstart', function (evt) {
clearSelection();
editorApi.onTouchContent();
tapping.fireTouchstart(evt);
}),
tapping.onTouchmove(),
tapping.onTouchend(),
// Stop any "clicks" being processed in the body at alls
DomEvent.bind(editorApi.body(), 'click', function (event) {
event.kill();
}),
// Close any menus when scrolling the toolstrip
DomEvent.bind(toolstrip, 'touchmove', function (/* event */) {
editorApi.onToolbarScrollStart();
})
];
var destroy = function () {
Arr.each(listeners, function (l) {
l.unbind();
});
};
return {
destroy: destroy
};
};
return {
initEvents: initEvents
};
}
);
|