summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/js/document_viewer.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/mail/static/src/js/document_viewer.js')
-rw-r--r--addons/mail/static/src/js/document_viewer.js396
1 files changed, 396 insertions, 0 deletions
diff --git a/addons/mail/static/src/js/document_viewer.js b/addons/mail/static/src/js/document_viewer.js
new file mode 100644
index 00000000..b46aea30
--- /dev/null
+++ b/addons/mail/static/src/js/document_viewer.js
@@ -0,0 +1,396 @@
+odoo.define('mail.DocumentViewer', function (require) {
+"use strict";
+
+var core = require('web.core');
+var Widget = require('web.Widget');
+
+var QWeb = core.qweb;
+
+var SCROLL_ZOOM_STEP = 0.1;
+var ZOOM_STEP = 0.5;
+
+/**
+ * This widget is deprecated, and should instead use AttachmentViewer component.
+ * @see `mail/static/src/components/attachment_viewer/attachment_viewer.js`
+ * TODO: remove this widget when it's not longer used
+ *
+ * @deprecated
+ */
+var DocumentViewer = Widget.extend({
+ template: "DocumentViewer",
+ events: {
+ 'click .o_download_btn': '_onDownload',
+ 'click .o_viewer_img': '_onImageClicked',
+ 'click .o_viewer_video': '_onVideoClicked',
+ 'click .move_next': '_onNext',
+ 'click .move_previous': '_onPrevious',
+ 'click .o_rotate': '_onRotate',
+ 'click .o_zoom_in': '_onZoomIn',
+ 'click .o_zoom_out': '_onZoomOut',
+ 'click .o_zoom_reset': '_onZoomReset',
+ 'click .o_close_btn, .o_viewer_img_wrapper': '_onClose',
+ 'click .o_print_btn': '_onPrint',
+ 'DOMMouseScroll .o_viewer_content': '_onScroll', // Firefox
+ 'mousewheel .o_viewer_content': '_onScroll', // Chrome, Safari, IE
+ 'keydown': '_onKeydown',
+ 'keyup': '_onKeyUp',
+ 'mousedown .o_viewer_img': '_onStartDrag',
+ 'mousemove .o_viewer_content': '_onDrag',
+ 'mouseup .o_viewer_content': '_onEndDrag'
+ },
+ /**
+ * The documentViewer takes an array of objects describing attachments in
+ * argument, and the ID of an active attachment (the one to display first).
+ * Documents that are not of type image or video are filtered out.
+ *
+ * @override
+ * @param {Array<Object>} attachments list of attachments
+ * @param {integer} activeAttachmentID
+ */
+ init: function (parent, attachments, activeAttachmentID) {
+ this._super.apply(this, arguments);
+ this.attachment = _.filter(attachments, function (attachment) {
+ var match = attachment.type === 'url' ? attachment.url.match("(youtu|.png|.jpg|.gif)") : attachment.mimetype.match("(image|video|application/pdf|text)");
+ if (match) {
+ attachment.fileType = match[1];
+ if (match[1].match("(.png|.jpg|.gif)")) {
+ attachment.fileType = 'image';
+ }
+ if (match[1] === 'youtu') {
+ var youtube_array = attachment.url.split('/');
+ var youtube_token = youtube_array[youtube_array.length-1];
+ if (youtube_token.indexOf('watch') !== -1) {
+ youtube_token = youtube_token.split('v=')[1];
+ var amp = youtube_token.indexOf('&')
+ if (amp !== -1){
+ youtube_token = youtube_token.substring(0, amp);
+ }
+ }
+ attachment.youtube = youtube_token;
+ }
+ return true;
+ }
+ });
+ this.activeAttachment = _.findWhere(attachments, {id: activeAttachmentID});
+ this.modelName = 'ir.attachment';
+ this._reset();
+ },
+ /**
+ * Open a modal displaying the active attachment
+ * @override
+ */
+ start: function () {
+ this.$el.modal('show');
+ this.$el.on('hidden.bs.modal', _.bind(this._onDestroy, this));
+ this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
+ this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
+ return this._super.apply(this, arguments);
+ },
+ /**
+ * @override
+ */
+ destroy: function () {
+ if (this.isDestroyed()) {
+ return;
+ }
+ this.$el.modal('hide');
+ this.$el.remove();
+ this._super.apply(this, arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //---------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ _next: function () {
+ var index = _.findIndex(this.attachment, this.activeAttachment);
+ index = (index + 1) % this.attachment.length;
+ this.activeAttachment = this.attachment[index];
+ this._updateContent();
+ },
+ /**
+ * @private
+ */
+ _previous: function () {
+ var index = _.findIndex(this.attachment, this.activeAttachment);
+ index = index === 0 ? this.attachment.length - 1 : index - 1;
+ this.activeAttachment = this.attachment[index];
+ this._updateContent();
+ },
+ /**
+ * @private
+ */
+ _reset: function () {
+ this.scale = 1;
+ this.dragStartX = this.dragstopX = 0;
+ this.dragStartY = this.dragstopY = 0;
+ },
+ /**
+ * Render the active attachment
+ *
+ * @private
+ */
+ _updateContent: function () {
+ this.$('.o_viewer_content').html(QWeb.render('DocumentViewer.Content', {
+ widget: this
+ }));
+ this.$('.o_viewer_img').on("load", _.bind(this._onImageLoaded, this));
+ this.$('[data-toggle="tooltip"]').tooltip({delay: 0});
+ this._reset();
+ },
+ /**
+ * Get CSS transform property based on scale and angle
+ *
+ * @private
+ * @param {float} scale
+ * @param {float} angle
+ */
+ _getTransform: function(scale, angle) {
+ return 'scale3d(' + scale + ', ' + scale + ', 1) rotate(' + angle + 'deg)';
+ },
+ /**
+ * Rotate image clockwise by provided angle
+ *
+ * @private
+ * @param {float} angle
+ */
+ _rotate: function (angle) {
+ this._reset();
+ var new_angle = (this.angle || 0) + angle;
+ this.$('.o_viewer_img').css('transform', this._getTransform(this.scale, new_angle));
+ this.$('.o_viewer_img').css('max-width', new_angle % 180 !== 0 ? $(document).height() : '100%');
+ this.$('.o_viewer_img').css('max-height', new_angle % 180 !== 0 ? $(document).width() : '100%');
+ this.angle = new_angle;
+ },
+ /**
+ * Zoom in/out image by provided scale
+ *
+ * @private
+ * @param {integer} scale
+ */
+ _zoom: function (scale) {
+ if (scale > 0.5) {
+ this.$('.o_viewer_img').css('transform', this._getTransform(scale, this.angle || 0));
+ this.scale = scale;
+ }
+ this.$('.o_zoom_reset').add('.o_zoom_out').toggleClass('disabled', scale === 1);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onClose: function (e) {
+ e.preventDefault();
+ this.destroy();
+ },
+ /**
+ * When popup close complete destroyed modal even DOM footprint too
+ *
+ * @private
+ */
+ _onDestroy: function () {
+ this.destroy();
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onDownload: function (e) {
+ e.preventDefault();
+ window.location = '/web/content/' + this.modelName + '/' + this.activeAttachment.id + '/' + 'datas' + '?download=true';
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onDrag: function (e) {
+ e.preventDefault();
+ if (this.enableDrag) {
+ var $image = this.$('.o_viewer_img');
+ var $zoomer = this.$('.o_viewer_zoomer');
+ var top = $image.prop('offsetHeight') * this.scale > $zoomer.height() ? e.clientY - this.dragStartY : 0;
+ var left = $image.prop('offsetWidth') * this.scale > $zoomer.width() ? e.clientX - this.dragStartX : 0;
+ $zoomer.css("transform", "translate3d("+ left +"px, " + top + "px, 0)");
+ $image.css('cursor', 'move');
+ }
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onEndDrag: function (e) {
+ e.preventDefault();
+ if (this.enableDrag) {
+ this.enableDrag = false;
+ this.dragstopX = e.clientX - this.dragStartX;
+ this.dragstopY = e.clientY - this.dragStartY;
+ this.$('.o_viewer_img').css('cursor', '');
+ }
+ },
+ /**
+ * On click of image do not close modal so stop event propagation
+ *
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onImageClicked: function (e) {
+ e.stopPropagation();
+ },
+ /**
+ * Remove loading indicator when image loaded
+ * @private
+ */
+ _onImageLoaded: function () {
+ this.$('.o_loading_img').hide();
+ },
+ /**
+ * Move next previous attachment on keyboard right left key
+ *
+ * @private
+ * @param {KeyEvent} e
+ */
+ _onKeydown: function (e){
+ switch (e.which) {
+ case $.ui.keyCode.RIGHT:
+ e.preventDefault();
+ this._next();
+ break;
+ case $.ui.keyCode.LEFT:
+ e.preventDefault();
+ this._previous();
+ break;
+ }
+ },
+ /**
+ * Close popup on ESCAPE keyup
+ *
+ * @private
+ * @param {KeyEvent} e
+ */
+ _onKeyUp: function (e) {
+ switch (e.which) {
+ case $.ui.keyCode.ESCAPE:
+ e.preventDefault();
+ this._onClose(e);
+ break;
+ }
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onNext: function (e) {
+ e.preventDefault();
+ this._next();
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onPrevious: function (e) {
+ e.preventDefault();
+ this._previous();
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onPrint: function (e) {
+ e.preventDefault();
+ var src = this.$('.o_viewer_img').prop('src');
+ var script = QWeb.render('PrintImage', {
+ src: src
+ });
+ var printWindow = window.open('about:blank', "_new");
+ printWindow.document.open();
+ printWindow.document.write(script);
+ printWindow.document.close();
+ },
+ /**
+ * Zoom image on scroll
+ *
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onScroll: function (e) {
+ var scale;
+ if (e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) {
+ scale = this.scale + SCROLL_ZOOM_STEP;
+ this._zoom(scale);
+ } else {
+ scale = this.scale - SCROLL_ZOOM_STEP;
+ this._zoom(scale);
+ }
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onStartDrag: function (e) {
+ e.preventDefault();
+ this.enableDrag = true;
+ this.dragStartX = e.clientX - (this.dragstopX || 0);
+ this.dragStartY = e.clientY - (this.dragstopY || 0);
+ },
+ /**
+ * On click of video do not close modal so stop event propagation
+ * and provide play/pause the video instead of quitting it
+ *
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onVideoClicked: function (e) {
+ e.stopPropagation();
+ var videoElement = e.target;
+ if (videoElement.paused) {
+ videoElement.play();
+ } else {
+ videoElement.pause();
+ }
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onRotate: function (e) {
+ e.preventDefault();
+ this._rotate(90);
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onZoomIn: function (e) {
+ e.preventDefault();
+ var scale = this.scale + ZOOM_STEP;
+ this._zoom(scale);
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onZoomOut: function (e) {
+ e.preventDefault();
+ var scale = this.scale - ZOOM_STEP;
+ this._zoom(scale);
+ },
+ /**
+ * @private
+ * @param {MouseEvent} e
+ */
+ _onZoomReset: function (e) {
+ e.preventDefault();
+ this.$('.o_viewer_zoomer').css("transform", "");
+ this._zoom(1);
+ },
+});
+return DocumentViewer;
+});