js/galleryrow.js   A
last analyzed

Complexity

Total Complexity 17
Complexity/F 1.31

Size

Lines of Code 154
Function Count 13

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 80
dl 0
loc 154
rs 10
c 0
b 0
f 0
wmc 17
mnd 4
bc 4
fnc 13
bpm 0.3076
cpm 1.3076
noi 0
1
/**
2
 * Nextcloud - Gallery
3
 *
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Olivier Paroz <[email protected]>
9
 *
10
 * @copyright Olivier Paroz 2017
11
 */
12
/* global Gallery, Album */
13
(function ($, Gallery) {
14
	"use strict";
15
	/**
16
	 * Creates a row
17
	 *
18
	 * @param {number} targetWidth
19
	 * @constructor
20
	 */
21
	var Row = function (targetWidth) {
22
		this.targetWidth = targetWidth;
23
		this.items = [];
24
		this.width = 4; // 4px margin to start with
25
		this.domDef = $('<div/>').addClass('row');
26
	};
27
28
	Row.prototype = {
29
		targetHeight: 200, // standard row height
30
		draggableOptions: {
31
			revert: 'invalid',
32
			revertDuration: 300,
33
			opacity: 0.7,
34
			distance: 20,
35
			zIndex: 1000,
36
			cursor: 'move',
37
			helper: function (e) {
38
				// Capture the original element
39
				var original = $(e.target).hasClass("ui-draggable") ? $(e.target) : $(
40
					e.target).closest(".ui-draggable");
41
42
				// Create a clone 50% smaller and link it to the #content element
43
				var clone = original.clone()
44
					.css({'transform': 'scale(0.5)'})
45
					.appendTo('#content');
46
47
				// Remove the labels
48
				clone.children('.image-label,.album-label').remove();
49
50
				// Centre the mouse pointer
51
				$(this).draggable("option", "cursorAt", {
52
					left: Math.floor($(this).width() / 2),
53
					top: Math.floor($(this).height() / 2)
54
				});
55
56
				return clone;
57
			},
58
			start: function (e) {
59
				// Disable all mouse interactions when dragging
60
				$('#gallery').css({'pointer-events': 'none'});
61
				$(e.target).css({opacity: 0.7});
62
			},
63
			stop: function (e) { // need to put it back on stop
64
				$('#gallery').css({'pointer-events': 'all'});
65
				$(e.target).css({opacity: 1});
66
			}
67
		},
68
69
		/**
70
		 * Adds sub-albums and images to the row until it's full
71
		 *
72
		 * @param {Album|GalleryImage} element
73
		 *
74
		 * @return {jQuery.Deferred<bool>} true if more images can be added to the row
75
		 */
76
		addElement: function (element) {
77
			var row = this;
78
			var fileNotFoundStatus = 404;
79
			var def = new $.Deferred();
80
			var itemDom;
81
82
			var validateRowWidth = function (width) {
83
				row.items.push(element);
84
				row.width += width + 4; // add 4px for the margin
85
				def.resolve(!row._isFull());
86
			};
87
88
			itemDom = element.getDom(row.targetHeight);
89
			row.domDef.append(itemDom);
90
			itemDom.draggable(this.draggableOptions);
91
92
			// The width of an album is always the same as its height
93
			if (element instanceof Album) {
94
				validateRowWidth(row.targetHeight);
95
			} else {
96
				// We can't calculate the total width if we don't have the width of the thumbnail
97
				element.getThumbnailWidth(row.targetHeight).then(function (width) {
98
					if (element.thumbnail.status !== fileNotFoundStatus) {
99
						element.resize(row.targetHeight, width);
100
						validateRowWidth(width);
101
					} else {
102
						itemDom.remove();
103
						def.resolve(true);
104
					}
105
				}, function () {
106
					itemDom.remove();
107
					def.resolve(true);
108
				});
109
			}
110
111
			return def.promise();
112
		},
113
114
		/**
115
		 * Returns the DOM element of the row
116
		 *
117
		 * @returns {*}
118
		 */
119
		getDom: function () {
120
			return this.domDef;
121
		},
122
123
		/**
124
		 * Resizes the row once it's full
125
		 */
126
		fit: function () {
127
			var scaleRatio = (this.width > this.targetWidth) ? this.targetWidth / this.width : 1;
128
129
			// This animates the elements when the window is resized
130
			var targetHeight = 4 + (this.targetHeight * scaleRatio);
131
			targetHeight = targetHeight.toFixed(3);
132
			this.domDef.height(targetHeight);
133
			this.domDef.width(this.width * scaleRatio);
134
135
			// Resizes and scales all photowall elements to make them fit within the window's width
136
			this.domDef.find('a').each(function () {
137
				// Necessary since DOM elements are not resized when CSS transform is used
138
				$(this).css('width', $(this).data('width') * scaleRatio)
139
					.css('height', $(this).data('height') * scaleRatio);
140
				// This scales the containers inside the anchors
141
				$(this).children('.container').css('transform-origin', 'left top')
142
					.css('-webkit-transform-origin', 'left top')
143
					.css('-ms-transform-origin', 'left top')
144
					.css('transform', 'scale(' + scaleRatio + ')')
145
					.css('-webkit-transform', 'scale(' + scaleRatio + ')')
146
					.css('-ms-transform', 'scale(' + scaleRatio + ')');
147
			});
148
149
			// Restore the rows to their normal opacity. This happens immediately with rows
150
			// containing albums only
151
			this.domDef.css('opacity', 1);
152
		},
153
154
		/**
155
		 * Calculates if the row is full
156
		 *
157
		 * @returns {boolean}
158
		 * @private
159
		 */
160
		_isFull: function () {
161
			return this.width > this.targetWidth;
162
		}
163
	};
164
165
	Gallery.Row = Row;
166
})(jQuery, Gallery);
167