js/breadcrumb.js   A
last analyzed

Complexity

Total Complexity 35
Complexity/F 2.69

Size

Lines of Code 273
Function Count 13

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 133
dl 0
loc 273
rs 9.6
c 0
b 0
f 0
wmc 35
mnd 22
bc 22
fnc 13
bpm 1.6923
cpm 2.6923
noi 1
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 Handlebars, Gallery */
13
(function ($, OC, t, Gallery) {
14
	"use strict";
15
16
	/**
17
	 * Breadcrumbs that represent the path to the current album
18
	 *
19
	 * @constructor
20
	 */
21
	var Breadcrumb = function () {
22
		this.breadcrumbsElement = $('#breadcrumbs');
23
	};
24
25
	Breadcrumb.prototype = {
26
		breadcrumbs: [],
27
		breadcrumbsElement: null,
28
		ellipsis: null,
29
		albumPath: null,
30
		availableWidth: 0,
31
		onClick: null,
32
		droppableOptions: {
33
			accept: "#gallery > .row > a",
34
			activeClass: 'breadcrumbs-droppable',
35
			hoverClass: 'breadcrumbs-droppable-hover',
36
			tolerance: 'pointer'
37
		},
38
39
		/**
40
		 * Initialises the breadcrumbs for the current album
41
		 *
42
		 * @param {string} albumPath
43
		 * @param {int} availableWidth
44
		 */
45
		init: function (albumPath, availableWidth) {
46
			this.albumPath = albumPath;
47
			this.availableWidth = availableWidth;
48
			this.breadcrumbs = [];
49
			this._build();
50
			this._resize(this.availableWidth);
51
		},
52
53
		/**
54
		 * Defines the maximum available width in which we can build the breadcrumb and resizes it
55
		 *
56
		 * @param {int} availableWidth
57
		 */
58
		setMaxWidth: function (availableWidth) {
59
			if (this.availableWidth > availableWidth || this.ellipsis.is(":visible")) {
60
				this.availableWidth = availableWidth;
61
				this._resize(this.availableWidth);
62
			}
63
		},
64
65
		/**
66
		 * Processes UI elements dropped on the breadcrumbs
67
		 *
68
		 * @param event
69
		 * @param ui
70
		 */
71
		onDrop: function (event, ui) {
72
			var $item = ui.draggable;
73
			var $clone = ui.helper;
74
			var $target = $(event.target);
75
			if (!$target.is('.crumb')) {
76
				$target = $target.closest('.crumb');
77
			}
78
			var targetPath = $(event.target).data('dir').toString();
79
			var dir = Gallery.currentAlbum;
80
81
			while (dir.substr(0, 1) === '/') {//remove extra leading /'s
82
				dir = dir.substr(1);
83
			}
84
			dir = '/' + dir;
85
			if (dir.substr(-1, 1) !== '/') {
86
				dir = dir + '/';
87
			}
88
			// Do nothing if dragged on current dir
89
			if (targetPath === dir || targetPath + '/' === dir) {
90
				return;
91
			}
92
			var filePath = $item.data('path').toString();
93
			var fileName = OC.basename(filePath);
94
95
			$clone.fadeOut("normal", function () {
96
				Gallery.move($item, fileName, filePath, $target, targetPath);
97
			});
98
		},
99
100
		/**
101
		 * Shows the dark spinner on the crumb
102
		 */
103
		showLoader: function () {
104
			$(this).addClass("icon-loading-small-dark");
105
		},
106
107
		/**
108
		 * Builds the breadcrumbs array
109
		 *
110
		 * @private
111
		 */
112
		_build: function () {
113
			var i, crumbs, name, path, currentAlbum;
114
			var albumName = $('#app-content').data('albumname');
115
			if (!albumName) {
116
				albumName = t('gallery', 'Gallery');
117
			}
118
			path = '';
119
			name = '';
0 ignored issues
show
Unused Code introduced by
The assignment to variable name seems to be never used. Consider removing it.
Loading history...
120
			crumbs = this.albumPath.split('/');
121
			currentAlbum = crumbs.pop();
122
123
			// This adds the home button
124
			this._addHome(albumName, currentAlbum);
125
			// We always add a hidden ellipsis
126
			this._pushCrumb('...', '', null, 'ellipsis');
127
128
			if (currentAlbum) {
129
				// This builds the crumbs between home and the current folder
130
				var crumbsLength = crumbs.length;
131
				if (crumbsLength > 0) {
132
					// We add all albums to the breadcrumbs array
133
					for (i = 0; i < crumbsLength; i++) {
134
						if (crumbs[i]) {
135
							name = crumbs[i];
136
							if (path) {
137
								path += '/' + crumbs[i];
138
							} else {
139
								path += crumbs[i];
140
							}
141
							this._pushCrumb(name, path, null, '');
142
						}
143
					}
144
				}
145
				// We finally push the current folder
146
				this._pushCrumb(currentAlbum, '', null, 'last');
147
			}
148
149
			this._render();
150
		},
151
152
		/**
153
		 * Adds the Home button
154
		 *
155
		 * @param {string} albumName
156
		 * @param {string} currentAlbum
157
		 * @private
158
		 */
159
		_addHome: function (albumName, currentAlbum) {
160
			var crumbImg = {
161
				imageSrc: OC.imagePath('core', 'places/home'),
162
				title: albumName
163
			};
164
			var cssClass = 'home';
165
			if (!currentAlbum) {
166
				cssClass += ' last';
167
			}
168
169
			this._pushCrumb('', '', crumbImg, cssClass);
170
		},
171
172
		/**
173
		 * Pushes crumb objects to the breadcrumbs array
174
		 *
175
		 * @param {string} name
176
		 * @param {string|boolean} link
177
		 * @param {Object} img
178
		 * @param {string} cssClass
179
		 * @private
180
		 */
181
		_pushCrumb: function (name, link, img, cssClass) {
182
			var hash = '';
183
184
			// Prevent the last crumb from getting a link unless the last crumb is 'home'.
185
			if ( cssClass.indexOf('last') === -1 || cssClass.indexOf('home') > -1 ) {
186
				hash = '#' + encodeURIComponent(link);
187
			}
188
189
			this.breadcrumbs.push({
190
				name: name,
191
				dir: link,
192
				link: hash,
193
				img: img,
194
				cssClass: cssClass
195
			});
196
		},
197
198
		/**
199
		 * Renders the full breadcrumb based on crumbs we have collected
200
		 *
201
		 * @private
202
		 */
203
		_render: function () {
204
			this.breadcrumbsElement.children().remove();
205
206
			var breadcrumbs = Gallery.Templates.breadcrumb({
207
				crumbs: this.breadcrumbs
208
			});
209
210
			this.breadcrumbsElement.append(breadcrumbs);
211
212
			this.droppableOptions.drop = this.onDrop.bind(this);
213
			this.breadcrumbsElement.find('.crumb:not(.last)').droppable(this.droppableOptions);
214
		},
215
216
		/**
217
		 * Alters the breadcrumb to make it fit within the asked dimensions
218
		 *
219
		 * @param {int} availableWidth
220
		 *
221
		 * @private
222
		 */
223
		_resize: function (availableWidth) {
224
			var crumbs = this.breadcrumbsElement.children();
225
			var shorten = false;
226
			var ellipsisPath = '';
227
			var self = this;
228
229
			// Hide everything first, so that we can check the width after adding each crumb
230
			crumbs.hide();
231
232
			// We go through the array in reverse order
233
			var crumbsElement = crumbs.get().reverse();
234
			$(crumbsElement).each(function () {
235
				if ($(this).hasClass('home')) {
236
					$(this).show();
237
					if (self.breadcrumbs.length > 2) {
238
						$(this).click(self.showLoader);
239
					}
240
					return;
241
				}
242
				// 1st sub-album has no-parent and the breadcrumbs contain home, ellipsis and last
243
				if (self.breadcrumbs.length > 3) {
244
					$(this).click(self.showLoader);
245
				}
246
				if ($(this).hasClass('ellipsis')) {
247
					self.ellipsis = $(this);
248
					return;
249
				}
250
				if (!shorten) {
251
					$(this).show();
252
				}
253
254
				// If we've reached the maximum width, we start hiding crumbs
255
				if (self.breadcrumbsElement.width() > availableWidth) {
256
					shorten = true;
257
					$(this).hide();
258
					if (!ellipsisPath) {
259
						ellipsisPath = $(this).data('dir');
260
					}
261
				}
262
			});
263
264
			// If we had to hide crumbs, we add a way to go to the parent folder
265
			if (shorten) {
266
				this.ellipsis.show();
267
268
				if (!ellipsisPath) {
269
					ellipsisPath = OC.dirname(this.albumPath);
270
				}
271
272
				this.ellipsis.children('a').attr('href', '#' + encodeURIComponent(ellipsisPath));
273
				this.ellipsis.attr('data-original-title', ellipsisPath).tooltip({
274
					fade: true,
275
					placement: 'bottom',
276
					delay: {
277
						hide: 5
278
					}
279
				});
280
			}
281
		}
282
	};
283
284
	Gallery.Breadcrumb = Breadcrumb;
285
})(jQuery, OC, t, Gallery);
286