This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | /* global Handlebars, Gallery */ |
||
2 | (function ($, _, OC, t, Gallery) { |
||
3 | "use strict"; |
||
4 | |||
5 | var TEMPLATE_ADDBUTTON = '<a href="#" class="button new"><img src="{{iconUrl}}" alt="{{addText}}"></img></a>'; |
||
6 | |||
7 | /** |
||
8 | * Builds and updates the Gallery view |
||
9 | * |
||
10 | * @constructor |
||
11 | */ |
||
12 | var View = function () { |
||
13 | this.element = $('#gallery'); |
||
14 | this.loadVisibleRows.loading = false; |
||
15 | this._setupUploader(); |
||
16 | this.breadcrumb = new Gallery.Breadcrumb(); |
||
17 | this.emptyContentElement = $('#emptycontent'); |
||
18 | this.controlsElement = $('#controls'); |
||
19 | }; |
||
20 | |||
21 | View.prototype = { |
||
22 | element: null, |
||
23 | breadcrumb: null, |
||
24 | requestId: -1, |
||
25 | emptyContentElement: null, |
||
26 | controlsElement: null, |
||
27 | |||
28 | /** |
||
29 | * Removes all thumbnails from the view |
||
30 | */ |
||
31 | clear: function () { |
||
32 | this.loadVisibleRows.processing = false; |
||
33 | this.loadVisibleRows.loading = null; |
||
34 | // We want to keep all the events |
||
35 | this.element.children().detach(); |
||
36 | this.showLoading(); |
||
37 | }, |
||
38 | |||
39 | /** |
||
40 | * Populates the view if there are images or albums to show |
||
41 | * |
||
42 | * @param {string} albumPath |
||
43 | * @param {string|undefined} errorMessage |
||
44 | */ |
||
45 | init: function (albumPath, errorMessage) { |
||
46 | // Only do it when the app is initialised |
||
47 | if (this.requestId === -1) { |
||
48 | this._initButtons(); |
||
49 | this._blankUrl(); |
||
50 | } |
||
51 | if ($.isEmptyObject(Gallery.imageMap)) { |
||
52 | Gallery.view.showEmptyFolder(albumPath, errorMessage); |
||
53 | } else { |
||
54 | this.viewAlbum(albumPath); |
||
55 | } |
||
56 | |||
57 | this._setBackgroundColour(); |
||
58 | }, |
||
59 | |||
60 | /** |
||
61 | * Starts the slideshow |
||
62 | * |
||
63 | * @param {string} path |
||
64 | * @param {string} albumPath |
||
65 | */ |
||
66 | startSlideshow: function (path, albumPath) { |
||
67 | var album = Gallery.albumMap[albumPath]; |
||
68 | var images = album.images; |
||
69 | var startImage = Gallery.imageMap[path]; |
||
70 | Gallery.slideShow(images, startImage, false); |
||
71 | }, |
||
72 | |||
73 | /** |
||
74 | * Sets up the controls and starts loading the gallery rows |
||
75 | * |
||
76 | * @param {string|null} albumPath |
||
77 | */ |
||
78 | viewAlbum: function (albumPath) { |
||
79 | albumPath = albumPath || ''; |
||
80 | if (!Gallery.albumMap[albumPath]) { |
||
81 | return; |
||
82 | } |
||
83 | |||
84 | this.clear(); |
||
85 | |||
86 | if (albumPath !== Gallery.currentAlbum |
||
87 | || (albumPath === Gallery.currentAlbum && |
||
88 | Gallery.albumMap[albumPath].etag !== Gallery.currentEtag)) { |
||
89 | Gallery.currentAlbum = albumPath; |
||
90 | Gallery.currentEtag = Gallery.albumMap[albumPath].etag; |
||
91 | this._setupButtons(albumPath); |
||
92 | } |
||
93 | |||
94 | Gallery.albumMap[albumPath].viewedItems = 0; |
||
95 | Gallery.albumMap[albumPath].preloadOffset = 0; |
||
96 | |||
97 | // Each request has a unique ID, so that we can track which request a row belongs to |
||
98 | this.requestId = Math.random(); |
||
99 | Gallery.albumMap[Gallery.currentAlbum].requestId = this.requestId; |
||
100 | |||
101 | // Loading rows without blocking the execution of the rest of the script |
||
102 | setTimeout(function () { |
||
103 | this.loadVisibleRows.activeIndex = 0; |
||
104 | this.loadVisibleRows(Gallery.albumMap[Gallery.currentAlbum]); |
||
105 | }.bind(this), 0); |
||
106 | }, |
||
107 | |||
108 | /** |
||
109 | * Manages the sorting interface |
||
110 | * |
||
111 | * @param {string} sortType name or date |
||
112 | * @param {string} sortOrder asc or des |
||
113 | */ |
||
114 | sortControlsSetup: function (sortType, sortOrder) { |
||
115 | var reverseSortType = 'date'; |
||
116 | if (sortType === 'date') { |
||
117 | reverseSortType = 'name'; |
||
118 | } |
||
119 | this._setSortButton(sortType, sortOrder, true); |
||
120 | this._setSortButton(reverseSortType, 'asc', false); // default icon |
||
121 | }, |
||
122 | |||
123 | /** |
||
124 | * Loads and displays gallery rows on screen |
||
125 | * |
||
126 | * view.loadVisibleRows.loading holds the Promise of a row |
||
127 | * |
||
128 | * @param {Album} album |
||
129 | */ |
||
130 | loadVisibleRows: function (album) { |
||
131 | var view = this; |
||
132 | // Wait for the previous request to be completed |
||
133 | if (this.loadVisibleRows.processing) { |
||
134 | return; |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * At this stage, there is no loading taking place, so we can look for new rows |
||
139 | */ |
||
140 | |||
141 | var scroll = $('#content-wrapper').scrollTop() + $(window).scrollTop(); |
||
142 | // 2 windows worth of rows is the limit from which we need to start loading new rows. |
||
143 | // As we scroll down, it grows |
||
144 | var targetHeight = ($(window).height() * 2) + scroll; |
||
145 | // We throttle rows in order to try and not generate too many CSS resizing events at |
||
146 | // the same time |
||
147 | var showRows = _.throttle(function (album) { |
||
148 | |||
149 | // If we've reached the end of the album, we kill the loader |
||
150 | if (!(album.viewedItems < album.subAlbums.length + album.images.length)) { |
||
0 ignored issues
–
show
|
|||
151 | view.loadVisibleRows.processing = false; |
||
152 | view.loadVisibleRows.loading = null; |
||
153 | return; |
||
154 | } |
||
155 | |||
156 | // Prevents creating rows which are no longer required. I.e when changing album |
||
157 | if (view.requestId !== album.requestId) { |
||
158 | return; |
||
159 | } |
||
160 | |||
161 | // We can now safely create a new row |
||
162 | var row = album.getRow($(window).width()); |
||
163 | var rowDom = row.getDom(); |
||
164 | view.element.append(rowDom); |
||
165 | |||
166 | return album.fillNextRow(row).then(function () { |
||
167 | if (album.viewedItems < album.subAlbums.length + album.images.length && |
||
168 | view.element.height() < targetHeight) { |
||
169 | return showRows(album); |
||
170 | } |
||
171 | // No more rows to load at the moment |
||
172 | view.loadVisibleRows.processing = false; |
||
173 | view.loadVisibleRows.loading = null; |
||
174 | }, function () { |
||
175 | // Something went wrong, so kill the loader |
||
176 | view.loadVisibleRows.processing = false; |
||
177 | view.loadVisibleRows.loading = null; |
||
178 | }); |
||
179 | }, 100); |
||
180 | if (this.element.height() < targetHeight) { |
||
181 | this._showNormal(); |
||
182 | this.loadVisibleRows.processing = true; |
||
183 | album.requestId = view.requestId; |
||
184 | this.loadVisibleRows.loading = showRows(album); |
||
185 | } |
||
186 | }, |
||
187 | |||
188 | /** |
||
189 | * Shows an empty gallery message |
||
190 | * |
||
191 | * @param {string} albumPath |
||
192 | * @param {string|null} errorMessage |
||
193 | */ |
||
194 | showEmptyFolder: function (albumPath, errorMessage) { |
||
195 | var message = '<div class="icon-gallery"></div>'; |
||
196 | var uploadAllowed = true; |
||
197 | |||
198 | this.element.children().detach(); |
||
199 | this.removeLoading(); |
||
200 | |||
201 | if (!_.isUndefined(errorMessage) && errorMessage !== null) { |
||
202 | message += '<h2>' + t('gallery', |
||
203 | 'Album cannot be shown') + '</h2>'; |
||
204 | message += '<p>' + escapeHTML(errorMessage) + '</p>'; |
||
0 ignored issues
–
show
|
|||
205 | uploadAllowed = false; |
||
206 | } else { |
||
207 | message += '<h2>' + t('gallery', |
||
208 | 'No media files found') + '</h2>'; |
||
209 | // We can't upload yet on the public side |
||
210 | if (Gallery.token) { |
||
211 | message += '<p>' + t('gallery', |
||
212 | 'Upload pictures in the files app to display them here') + '</p>'; |
||
213 | } else { |
||
214 | message += '<p>' + t('gallery', |
||
215 | 'Upload new files via drag and drop or by using the [+] button above') + |
||
216 | '</p>'; |
||
217 | } |
||
218 | } |
||
219 | this.emptyContentElement.html(message); |
||
220 | this.emptyContentElement.removeClass('hidden'); |
||
221 | |||
222 | this._hideButtons(uploadAllowed); |
||
223 | Gallery.currentAlbum = albumPath; |
||
224 | var availableWidth = $(window).width() - Gallery.buttonsWidth; |
||
225 | this.breadcrumb.init(albumPath, availableWidth); |
||
226 | Gallery.config.albumDesign = null; |
||
227 | }, |
||
228 | |||
229 | /** |
||
230 | * Dims the controls bar when retrieving new content. Matches the effect in Files |
||
231 | */ |
||
232 | dimControls: function () { |
||
233 | // Use the existing mask if its already there |
||
234 | var $mask = this.controlsElement.find('.mask'); |
||
235 | if ($mask.exists()) { |
||
236 | return; |
||
237 | } |
||
238 | $mask = $('<div class="mask transparent"></div>'); |
||
239 | this.controlsElement.append($mask); |
||
240 | $mask.removeClass('transparent'); |
||
241 | }, |
||
242 | |||
243 | /** |
||
244 | * Shows the infamous loading spinner |
||
245 | */ |
||
246 | showLoading: function () { |
||
247 | this.emptyContentElement.addClass('hidden'); |
||
248 | this.controlsElement.removeClass('hidden'); |
||
249 | $('#content').addClass('icon-loading'); |
||
250 | this.dimControls(); |
||
251 | }, |
||
252 | |||
253 | /** |
||
254 | * Removes the spinner in the main area and restore normal visibility of the controls bar |
||
255 | */ |
||
256 | removeLoading: function () { |
||
257 | $('#content').removeClass('icon-loading'); |
||
258 | this.controlsElement.find('.mask').remove(); |
||
259 | }, |
||
260 | |||
261 | /** |
||
262 | * Shows thumbnails |
||
263 | */ |
||
264 | _showNormal: function () { |
||
265 | this.emptyContentElement.addClass('hidden'); |
||
266 | this.controlsElement.removeClass('hidden'); |
||
267 | this.removeLoading(); |
||
268 | }, |
||
269 | |||
270 | /** |
||
271 | * Sets up our custom handlers for folder uploading operations |
||
272 | * |
||
273 | * @see OC.Upload.init/file_upload_param.done() |
||
274 | * |
||
275 | * @private |
||
276 | */ |
||
277 | _setupUploader: function () { |
||
278 | var self = this; |
||
0 ignored issues
–
show
|
|||
279 | var $uploadEl = $('#file_upload_start'); |
||
280 | var uploads = []; |
||
0 ignored issues
–
show
|
|||
281 | if (!$uploadEl.exists()) { |
||
282 | return; |
||
283 | } |
||
284 | this._uploader = new OC.Uploader($uploadEl, { |
||
285 | fileList: FileList, |
||
286 | dropZone: $('#content') |
||
287 | }); |
||
288 | this._uploader.on('add', function (e, data) { |
||
289 | data.targetDir = '/' + Gallery.currentAlbum; |
||
290 | }); |
||
291 | this._uploader.on('done', function (e, upload) { |
||
292 | var data = upload.data; |
||
293 | // is that the last upload ? |
||
294 | if (data.files[0] === data.originalFiles[data.originalFiles.length - 1]) { |
||
295 | var fileList = data.originalFiles; |
||
296 | //Ask for a refresh of the photowall |
||
297 | Gallery.getFiles(Gallery.currentAlbum).done(function () { |
||
298 | var fileId, path; |
||
299 | // Removes the cached thumbnails of files which have been re-uploaded |
||
300 | _(fileList).each(function (fileName) { |
||
301 | path = Gallery.currentAlbum + '/' + fileName; |
||
302 | if (Gallery.imageMap[path]) { |
||
303 | fileId = Gallery.imageMap[path].fileId; |
||
304 | if (Thumbnails.map[fileId]) { |
||
0 ignored issues
–
show
|
|||
305 | delete Thumbnails.map[fileId]; |
||
0 ignored issues
–
show
|
|||
306 | } |
||
307 | } |
||
308 | }); |
||
309 | |||
310 | Gallery.view.init(Gallery.currentAlbum); |
||
311 | }); |
||
312 | } |
||
313 | }); |
||
314 | |||
315 | // Since 9.0 |
||
316 | if (OC.Uploader) { |
||
317 | OC.Uploader.prototype._isReceivedSharedFile = function (file) { |
||
318 | var path = file.name; |
||
319 | var sharedWith = false; |
||
320 | |||
321 | if (Gallery.currentAlbum !== '' && Gallery.currentAlbum !== '/') { |
||
322 | path = Gallery.currentAlbum + '/' + path; |
||
323 | } |
||
324 | if (Gallery.imageMap[path] && Gallery.imageMap[path].sharedWithUser) { |
||
325 | sharedWith = true; |
||
326 | } |
||
327 | |||
328 | return sharedWith; |
||
329 | }; |
||
330 | } |
||
331 | }, |
||
332 | |||
333 | /** |
||
334 | * Adds all the click handlers to buttons the first time they appear in the interface |
||
335 | * |
||
336 | * @private |
||
337 | */ |
||
338 | _initButtons: function () { |
||
339 | this.element.on("contextmenu", function(e) { e.preventDefault(); }); |
||
340 | $('#filelist-button').click(Gallery.switchToFilesView); |
||
341 | $('#download').click(Gallery.download); |
||
342 | $('#share-button').click(Gallery.share); |
||
343 | Gallery.infoBox = new Gallery.InfoBox(); |
||
344 | $('#album-info-button').click(Gallery.showInfo); |
||
345 | $('#sort-name-button').click(Gallery.sorter); |
||
346 | $('#sort-date-button').click(Gallery.sorter); |
||
347 | $('#save #save-button').click(Gallery.showSaveForm); |
||
348 | $('.save-form').submit(Gallery.saveForm); |
||
349 | this._renderNewButton(); |
||
350 | // Trigger cancelling of file upload |
||
351 | $('#uploadprogresswrapper .stop').on('click', function () { |
||
352 | OC.Upload.cancelUploads(); |
||
353 | }); |
||
354 | this.requestId = Math.random(); |
||
355 | }, |
||
356 | |||
357 | /** |
||
358 | * Sets up all the buttons of the interface and the breadcrumbs |
||
359 | * |
||
360 | * @param {string} albumPath |
||
361 | * @private |
||
362 | */ |
||
363 | _setupButtons: function (albumPath) { |
||
364 | this._shareButtonSetup(albumPath); |
||
365 | this._infoButtonSetup(); |
||
366 | |||
367 | var availableWidth = $(window).width() - Gallery.buttonsWidth; |
||
368 | this.breadcrumb.init(albumPath, availableWidth); |
||
369 | var album = Gallery.albumMap[albumPath]; |
||
370 | |||
371 | var sum = album.images.length + album.subAlbums.length; |
||
372 | //If sum of the number of images and subalbums exceeds 1 then show the buttons. |
||
373 | if(sum > 1) |
||
374 | { |
||
375 | $('#sort-name-button').show(); |
||
376 | $('#sort-date-button').show(); |
||
377 | } |
||
378 | else |
||
379 | { |
||
380 | $('#sort-name-button').hide(); |
||
381 | $('#sort-date-button').hide(); |
||
382 | } |
||
383 | var currentSort = Gallery.config.albumSorting; |
||
384 | this.sortControlsSetup(currentSort.type, currentSort.order); |
||
385 | Gallery.albumMap[Gallery.currentAlbum].images.sort( |
||
386 | Gallery.utility.sortBy(currentSort.type, |
||
387 | currentSort.order)); |
||
388 | Gallery.albumMap[Gallery.currentAlbum].subAlbums.sort(Gallery.utility.sortBy('name', |
||
389 | currentSort.albumOrder)); |
||
390 | |||
391 | $('#save-button').show(); |
||
392 | $('#download').show(); |
||
393 | $('a.button.new').show(); |
||
394 | }, |
||
395 | |||
396 | /** |
||
397 | * Hide buttons in the controls bar |
||
398 | * |
||
399 | * @param uploadAllowed |
||
400 | */ |
||
401 | _hideButtons: function (uploadAllowed) { |
||
402 | $('#album-info-button').hide(); |
||
403 | $('#share-button').hide(); |
||
404 | $('#sort-name-button').hide(); |
||
405 | $('#sort-date-button').hide(); |
||
406 | $('#save-button').hide(); |
||
407 | $('#download').hide(); |
||
408 | |||
409 | if (!uploadAllowed) { |
||
410 | $('a.button.new').hide(); |
||
411 | } |
||
412 | }, |
||
413 | |||
414 | /** |
||
415 | * Shows or hides the share button depending on if we're in a public gallery or not |
||
416 | * |
||
417 | * @param {string} albumPath |
||
418 | * @private |
||
419 | */ |
||
420 | _shareButtonSetup: function (albumPath) { |
||
421 | var shareButton = $('#share-button'); |
||
422 | if (albumPath === '' || Gallery.token) { |
||
423 | shareButton.hide(); |
||
424 | } else { |
||
425 | shareButton.show(); |
||
426 | } |
||
427 | }, |
||
428 | |||
429 | /** |
||
430 | * Shows or hides the info button based on the information we've received from the server |
||
431 | * |
||
432 | * @private |
||
433 | */ |
||
434 | _infoButtonSetup: function () { |
||
435 | var infoButton = $('#album-info-button'); |
||
436 | infoButton.find('span').hide(); |
||
437 | var infoContentContainer = $('.album-info-container'); |
||
438 | infoContentContainer.slideUp(); |
||
439 | infoContentContainer.css('max-height', |
||
440 | $(window).height() - Gallery.browserToolbarHeight); |
||
441 | var albumInfo = Gallery.config.albumInfo; |
||
442 | if (Gallery.config.albumError) { |
||
443 | infoButton.hide(); |
||
444 | var text = '<strong>' + t('gallery', 'Configuration error') + '</strong></br>' + |
||
445 | Gallery.config.albumError.message + '</br></br>'; |
||
446 | Gallery.utility.showHtmlNotification(text, 7); |
||
447 | } else if ($.isEmptyObject(albumInfo)) { |
||
448 | infoButton.hide(); |
||
449 | } else { |
||
450 | infoButton.show(); |
||
451 | if (albumInfo.inherit !== 'yes' || albumInfo.level === 0) { |
||
452 | infoButton.find('span').delay(1000).slideDown(); |
||
453 | } |
||
454 | } |
||
455 | }, |
||
456 | |||
457 | /** |
||
458 | * Sets the background colour of the photowall |
||
459 | * |
||
460 | * @private |
||
461 | */ |
||
462 | _setBackgroundColour: function () { |
||
463 | var wrapper = $('#content-wrapper'); |
||
464 | var albumDesign = Gallery.config.albumDesign; |
||
465 | if (!$.isEmptyObject(albumDesign) && albumDesign.background) { |
||
466 | wrapper.css('background-color', albumDesign.background); |
||
467 | } else { |
||
468 | wrapper.css('background-color', '#fff'); |
||
469 | } |
||
470 | }, |
||
471 | |||
472 | /** |
||
473 | * Picks the image which matches the sort order |
||
474 | * |
||
475 | * @param {string} sortType name or date |
||
476 | * @param {string} sortOrder asc or des |
||
477 | * @param {boolean} active determines if we're setting up the active sort button |
||
478 | * @private |
||
479 | */ |
||
480 | _setSortButton: function (sortType, sortOrder, active) { |
||
481 | var button = $('#sort-' + sortType + '-button'); |
||
482 | // Removing all the classes which control the image in the button |
||
483 | button.removeClass('active-button'); |
||
484 | button.find('img').removeClass('front'); |
||
485 | button.find('img').removeClass('back'); |
||
486 | |||
487 | // We need to determine the reverse order in order to send that image to the back |
||
488 | var reverseSortOrder = 'des'; |
||
489 | if (sortOrder === 'des') { |
||
490 | reverseSortOrder = 'asc'; |
||
491 | } |
||
492 | |||
493 | // We assign the proper order to the button images |
||
494 | button.find('img.' + sortOrder).addClass('front'); |
||
495 | button.find('img.' + reverseSortOrder).addClass('back'); |
||
496 | |||
497 | // The active button needs a hover action for the flip effect |
||
498 | if (active) { |
||
499 | button.addClass('active-button'); |
||
500 | if (button.is(":hover")) { |
||
501 | button.removeClass('hover'); |
||
502 | } |
||
503 | // We can't use a toggle here |
||
504 | button.hover(function () { |
||
505 | $(this).addClass('hover'); |
||
506 | }, |
||
507 | function () { |
||
508 | $(this).removeClass('hover'); |
||
509 | }); |
||
510 | } |
||
511 | }, |
||
512 | |||
513 | /** |
||
514 | * If no url is entered then do not show the error box. |
||
515 | * |
||
516 | */ |
||
517 | _blankUrl: function() { |
||
518 | $('#remote_address').on("change keyup paste", function() { |
||
519 | if ($(this).val() === '') { |
||
520 | $('#save-button-confirm').prop('disabled', true); |
||
521 | } else { |
||
522 | $('#save-button-confirm').prop('disabled', false); |
||
523 | } |
||
524 | }); |
||
525 | }, |
||
526 | |||
527 | /** |
||
528 | * Creates the [+] button allowing users who can't drag and drop to upload files |
||
529 | * |
||
530 | * @see core/apps/files/js/filelist.js |
||
531 | * @private |
||
532 | */ |
||
533 | _renderNewButton: function () { |
||
534 | // if no actions container exist, skip |
||
535 | var $actionsContainer = $('.actions'); |
||
536 | if (!$actionsContainer.length) { |
||
537 | return; |
||
538 | } |
||
539 | if (!this._addButtonTemplate) { |
||
540 | this._addButtonTemplate = Handlebars.compile(TEMPLATE_ADDBUTTON); |
||
541 | } |
||
542 | var $newButton = $(this._addButtonTemplate({ |
||
543 | addText: t('gallery', 'New'), |
||
544 | iconUrl: OC.imagePath('core', 'actions/add') |
||
545 | })); |
||
546 | |||
547 | $actionsContainer.prepend($newButton); |
||
548 | $newButton.tooltip({'placement': 'bottom'}); |
||
549 | |||
550 | $newButton.click(_.bind(this._onClickNewButton, this)); |
||
551 | this._newButton = $newButton; |
||
552 | }, |
||
553 | |||
554 | /** |
||
555 | * Creates the click handler for the [+] button |
||
556 | * @param event |
||
557 | * @returns {boolean} |
||
558 | * |
||
559 | * @see core/apps/files/js/filelist.js |
||
560 | * @private |
||
561 | */ |
||
562 | _onClickNewButton: function (event) { |
||
563 | var $target = $(event.target); |
||
564 | if (!$target.hasClass('.button')) { |
||
565 | $target = $target.closest('.button'); |
||
566 | } |
||
567 | this._newButton.tooltip('hide'); |
||
568 | event.preventDefault(); |
||
569 | if ($target.hasClass('disabled')) { |
||
570 | return false; |
||
571 | } |
||
572 | if (!this._newFileMenu) { |
||
573 | this._newFileMenu = new Gallery.NewFileMenu(); |
||
574 | $('body').append(this._newFileMenu.$el); |
||
575 | } |
||
576 | this._newFileMenu.showAt($target); |
||
577 | |||
578 | if (Gallery.currentAlbum === '') { |
||
579 | $('.menuitem[data-action="hideAlbum"]').parent().hide(); |
||
580 | } |
||
581 | return false; |
||
582 | } |
||
583 | }; |
||
584 | |||
585 | Gallery.View = View; |
||
586 | })(jQuery, _, OC, t, Gallery); |
||
587 |
The following shows a case which JSHint considers confusing and its respective non-confusing counterpart: