Passed
Push — master ( de752f...295ecd )
by
unknown
11:00
created

client/filepreviewer/ViewerJS/viewer.js   F

Complexity

Total Complexity 142
Complexity/F 1.8

Size

Lines of Code 955
Function Count 79

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 571
c 0
b 0
f 0
dl 0
loc 955
rs 2
wmc 142
mnd 63
bc 63
fnc 79
bpm 0.7974
cpm 1.7974
noi 11

8 Functions

Rating   Name   Duplication   Size   Complexity  
A viewer.js ➔ loadPlugin 0 9 1
A viewer.js ➔ getMimeByExtension 0 23 2
A viewer.js ➔ doEstimateTypeByFileExtension 0 13 3
A viewer.js ➔ parseSearchParameters 0 16 3
F viewer.js ➔ estimateTypeByHeaderContentType 0 30 24
F viewer.js ➔ Viewer 0 580 96
A viewer.js ➔ estimateTypeByFileExtension 0 12 2
A viewer.js ➔ estimateTypeByFileExtensionFromPath 0 12 2

How to fix   Complexity   

Complexity

Complex classes like client/filepreviewer/ViewerJS/viewer.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
ViewerJS_version = '0.7.0';
0 ignored issues
show
Bug introduced by
The variable ViewerJS_version seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.ViewerJS_version.
Loading history...
2
3
function loadPlugin( pluginFile, callback ) {
4
    "use strict";
5
    var script    = document.createElement('script');
6
    script.async  = false;
7
    script.onload = callback;
8
    script.src    = pluginFile;
9
    script.type   = 'text/javascript';
10
    document.head.appendChild(script);
11
}
12
/**
13
 * Copyright (C) 2012-2015 KO GmbH <[email protected]>
14
 * Copyright (C) 2020-2022 grommunio GmbH <[email protected]>
15
 *
16
 * @licstart
17
 * This file is part of ViewerJS.
18
 *
19
 * ViewerJS is free software: you can redistribute it and/or modify it
20
 * under the terms of the GNU Affero General Public License (GNU AGPL)
21
 * as published by the Free Software Foundation, either version 3 of
22
 * the License, or (at your option) any later version.
23
 *
24
 * ViewerJS is distributed in the hope that it will be useful, but
25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
 * GNU Affero General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU Affero General Public License
30
 * along with ViewerJS.  If not, see <http://www.gnu.org/licenses/>.
31
 * @licend
32
 *
33
 * @source: http://viewerjs.org/
34
 * @source: http://github.com/kogmbh/ViewerJS
35
 */
36
37
/*
38
 * This file is a derivative from a part of Mozilla's PDF.js project. The
39
 * original license header follows.
40
 */
41
42
/* Copyright 2012 Mozilla Foundation
43
 *
44
 * Licensed under the Apache License, Version 2.0 (the "License");
45
 * you may not use this file except in compliance with the License.
46
 * You may obtain a copy of the License at
47
 *
48
 * http://www.apache.org/licenses/LICENSE-2.0
49
 *
50
 * Unless required by applicable law or agreed to in writing, software
51
 * distributed under the License is distributed on an "AS IS" BASIS,
52
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
53
 * See the License for the specific language governing permissions and
54
 * limitations under the License.
55
 */
56
57
/*global document, window*/
58
59
function Viewer( viewerPlugin, parameters ) {
60
    "use strict";
61
62
    var self               = this,
63
        kScrollbarPadding  = 40,
64
        kMinScale          = 0.25,
65
        kMaxScale          = 4.0,
66
        kDefaultScaleDelta = 1.1,
67
        kDefaultScale      = 'auto',
68
        presentationMode   = false,
69
        isFullScreen       = false,
70
        initialized        = false,
71
        url,
72
        viewerElement      = document.getElementById('viewer'),
73
        canvasContainer    = document.getElementById('canvasContainer'),
74
        overlayNavigator   = document.getElementById('overlayNavigator'),
75
        titlebar           = document.getElementById('titlebar'),
76
        toolbar            = document.getElementById('toolbarContainer'),
77
        pageSwitcher       = document.getElementById('toolbarLeft'),
78
        zoomWidget         = document.getElementById('toolbarMiddleContainer'),
79
        scaleSelector      = document.getElementById('scaleSelect'),
80
        dialogOverlay      = document.getElementById('dialogOverlay'),
0 ignored issues
show
Unused Code introduced by
The variable dialogOverlay seems to be never used. Consider removing it.
Loading history...
81
        toolbarRight       = document.getElementById('toolbarRight'),
0 ignored issues
show
Unused Code introduced by
The variable toolbarRight seems to be never used. Consider removing it.
Loading history...
82
        pages              = [],
83
        currentPage,
84
        scaleChangeTimer,
85
        touchTimer,
86
        toolbarTouchTimer,
87
        UI_FADE_DURATION   = 5000;
88
89
    function isBlankedOut() {
90
        return (blanked.style.display === 'block');
91
    }
92
93
    function selectScaleOption( value ) {
94
        // Retrieve the options from the zoom level <select> element
95
        var options              = scaleSelector.options,
96
            option,
97
            predefinedValueFound = false,
98
            i;
99
100
        for ( i = 0; i < options.length; i += 1 ) {
101
            option = options[i];
102
            if ( option.value !== value ) {
103
                option.selected = false;
104
                continue;
105
            }
106
            option.selected      = true;
107
            predefinedValueFound = true;
108
        }
109
        return predefinedValueFound;
110
    }
111
112
    function getPages() {
113
        return viewerPlugin.getPages();
114
    }
115
116
    function setScale( val, resetAutoSettings ) {
117
        if ( val === self.getZoomLevel() ) {
118
            return;
119
        }
120
121
        self.setZoomLevel(val);
122
123
        var event = document.createEvent('UIEvents');
124
        event.initUIEvent('scalechange', false, false, window, 0);
125
        event.scale             = val;
126
        event.resetAutoSettings = resetAutoSettings;
127
        window.dispatchEvent(event);
128
    }
129
130
    function onScroll() {
131
        var pageNumber;
132
133
        if ( viewerPlugin.onScroll ) {
134
            viewerPlugin.onScroll();
135
        }
136
        if ( viewerPlugin.getPageInView ) {
137
            pageNumber = viewerPlugin.getPageInView();
138
            if ( pageNumber ) {
139
                currentPage                                 = pageNumber;
140
                document.getElementById('pageNumber').value = pageNumber;
141
            }
142
        }
143
    }
144
145
    function delayedRefresh( milliseconds ) {
146
        window.clearTimeout(scaleChangeTimer);
147
        scaleChangeTimer = window.setTimeout(function () {
148
            onScroll();
149
        }, milliseconds);
150
    }
151
152
    function parseScale( value, resetAutoSettings ) {
153
        var scale,
154
            maxWidth,
155
            maxHeight;
156
157
        if ( value === 'custom' ) {
158
            scale = parseFloat(document.getElementById('customScaleOption').textContent) / 100;
159
        } else {
160
            scale = parseFloat(value);
161
        }
162
163
        if ( scale ) {
164
            setScale(scale, true);
165
            delayedRefresh(300);
166
            return;
167
        }
168
169
        maxWidth  = canvasContainer.clientWidth - kScrollbarPadding;
170
        maxHeight = canvasContainer.clientHeight - kScrollbarPadding;
171
172
        switch ( value ) {
173
            case 'page-actual':
174
                setScale(1, resetAutoSettings);
175
                break;
176
            case 'page-width':
177
                viewerPlugin.fitToWidth(maxWidth);
178
                break;
179
            case 'page-height':
180
                viewerPlugin.fitToHeight(maxHeight);
181
                break;
182
            case 'page-fit':
183
                viewerPlugin.fitToPage(maxWidth, maxHeight);
184
                break;
185
            case 'auto':
186
                if ( viewerPlugin.isSlideshow() ) {
187
                    viewerPlugin.fitToPage(maxWidth + kScrollbarPadding, maxHeight + kScrollbarPadding);
188
                } else {
189
                    viewerPlugin.fitSmart(maxWidth);
190
                }
191
                break;
192
        }
193
194
        selectScaleOption(value);
195
        delayedRefresh(300);
196
    }
197
198
    function readZoomParameter( zoom ) {
199
        var validZoomStrings = ["auto", "page-actual", "page-width"],
200
            number;
201
202
        if ( validZoomStrings.indexOf(zoom) !== -1 ) {
203
            return zoom;
204
        }
205
        number = parseFloat(zoom);
206
        if ( number && kMinScale <= number && number <= kMaxScale ) {
207
            return zoom;
208
        }
209
        return kDefaultScale;
210
    }
211
212
    function readStartPageParameter( startPage ) {
213
        var result = parseInt(startPage, 10);
214
        return isNaN(result) ? 1 : result;
215
    }
216
217
    this.initialize = function () {
218
        var initialScale;
219
220
        initialScale = readZoomParameter(parameters.zoom);
221
222
        url                    = parameters.documentUrl;
223
        document.title         = parameters.title;
224
        var documentName       = document.getElementById('documentName');
225
        documentName.innerHTML = "";
226
        documentName.appendChild(documentName.ownerDocument.createTextNode(parameters.title));
227
228
        viewerPlugin.onLoad = function () {
229
230
            if ( viewerPlugin.isSlideshow() ) {
231
                // Slideshow pages should be centered
232
                canvasContainer.classList.add("slideshow");
233
                // Show page nav controls only for presentations
234
                pageSwitcher.style.visibility = 'visible';
235
            } else {
236
                // For text documents, show the zoom widget.
237
                zoomWidget.style.visibility = 'visible';
238
                // Only show the page switcher widget if the plugin supports page numbers
239
                if ( viewerPlugin.getPageInView ) {
240
                    pageSwitcher.style.visibility = 'visible';
241
                }
242
            }
243
244
            initialized                                   = true;
245
            pages                                         = getPages();
246
            document.getElementById('numPages').innerHTML = 'of ' + pages.length;
247
248
            self.showPage(readStartPageParameter(parameters.startpage));
249
250
            // Set default scale
251
            parseScale(initialScale);
252
253
            canvasContainer.onscroll = onScroll;
254
            delayedRefresh();
255
            // Doesn't work in older browsers: document.getElementById('loading-document').remove();
256
            var loading = document.getElementById('loading-document');
257
            loading.parentNode.removeChild(loading);
258
        };
259
260
        viewerPlugin.initialize(canvasContainer, url);
261
    };
262
263
    /**
264
     * Shows the 'n'th page. If n is larger than the page count,
265
     * shows the last page. If n is less than 1, shows the first page.
266
     * @return {undefined}
267
     */
268
    this.showPage = function ( n ) {
269
        if ( n <= 0 ) {
270
            n = 1;
271
        } else if ( n > pages.length ) {
272
            n = pages.length;
273
        }
274
275
        viewerPlugin.showPage(n);
276
277
        currentPage                                 = n;
278
        document.getElementById('pageNumber').value = currentPage;
279
    };
280
281
    /**
282
     * Shows the next page. If there is no subsequent page, does nothing.
283
     * @return {undefined}
284
     */
285
    this.showNextPage = function () {
286
        self.showPage(currentPage + 1);
287
    };
288
289
    /**
290
     * Shows the previous page. If there is no previous page, does nothing.
291
     * @return {undefined}
292
     */
293
    this.showPreviousPage = function () {
294
        self.showPage(currentPage - 1);
295
    };
296
297
    /**
298
     * Attempts to 'download' the file.
299
     * @return {undefined}
300
     */
301
    this.download = function () {
302
        var documentUrl = url.split('#')[0];
303
        if ( documentUrl.indexOf('?') !== -1 ) {
304
            documentUrl += '&contentDispositionType=attachment';
305
        } else {
306
            documentUrl += '?contentDispositionType=attachment';
307
        }
308
        window.open(documentUrl, '_parent');
309
    };
310
311
    /**
312
     * Prints the document canvas.
313
     * @return {undefined}
314
     */
315
    this.printDocument = function () {
316
        window.print();
317
    };
318
319
    /**
320
     * Toggles the fullscreen state of the viewer
321
     * @return {undefined}
322
     */
323
    this.toggleFullScreen = function () {
324
        var elem = viewerElement;
325
        if ( !isFullScreen ) {
326
            if ( elem.requestFullscreen ) {
327
                elem.requestFullscreen();
328
            } else if ( elem.mozRequestFullScreen ) {
329
                elem.mozRequestFullScreen();
330
            } else if ( elem.webkitRequestFullscreen ) {
331
                elem.webkitRequestFullscreen();
332
            } else if ( elem.webkitRequestFullScreen ) {
333
                elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
334
            } else if ( elem.msRequestFullscreen ) {
335
                elem.msRequestFullscreen();
336
            }
337
        } else {
338
            if ( document.exitFullscreen ) {
339
                document.exitFullscreen();
340
            } else if ( document.cancelFullScreen ) {
341
                document.cancelFullScreen();
342
            } else if ( document.mozCancelFullScreen ) {
343
                document.mozCancelFullScreen();
344
            } else if ( document.webkitExitFullscreen ) {
345
                document.webkitExitFullscreen();
346
            } else if ( document.webkitCancelFullScreen ) {
347
                document.webkitCancelFullScreen();
348
            } else if ( document.msExitFullscreen ) {
349
                document.msExitFullscreen();
350
            }
351
        }
352
    };
353
354
    /**
355
     * Toggles the presentation mode of the viewer.
356
     * Presentation mode involves fullscreen + hidden UI controls
357
     */
358
    this.togglePresentationMode = function () {
359
        var overlayCloseButton = document.getElementById('overlayCloseButton');
360
361
        if ( !presentationMode ) {
362
            titlebar.style.display = toolbar.style.display = 'none';
363
            overlayCloseButton.style.display = 'block';
364
            canvasContainer.classList.add('presentationMode');
365
            canvasContainer.onmousedown   = function ( event ) {
366
                event.preventDefault();
367
            };
368
            canvasContainer.oncontextmenu = function ( event ) {
369
                event.preventDefault();
370
            };
371
            canvasContainer.onmouseup     = function ( event ) {
372
                event.preventDefault();
373
                if ( event.which === 1 ) {
374
                    self.showNextPage();
375
                } else {
376
                    self.showPreviousPage();
377
                }
378
            };
379
            parseScale('page-fit');
380
        } else {
381
            if ( isBlankedOut() ) {
382
                leaveBlankOut();
383
            }
384
            titlebar.style.display = toolbar.style.display = 'block';
385
            overlayCloseButton.style.display = 'none';
386
            canvasContainer.classList.remove('presentationMode');
387
            canvasContainer.onmouseup     = function () {
388
            };
389
            canvasContainer.oncontextmenu = function () {
390
            };
391
            canvasContainer.onmousedown   = function () {
392
            };
393
            parseScale('auto');
394
        }
395
396
        presentationMode = !presentationMode;
397
    };
398
399
    /**
400
     * Gets the zoom level of the document
401
     * @return {!number}
402
     */
403
    this.getZoomLevel = function () {
404
        return viewerPlugin.getZoomLevel();
405
    };
406
407
    /**
408
     * Set the zoom level of the document
409
     * @param {!number} value
410
     * @return {undefined}
411
     */
412
    this.setZoomLevel = function ( value ) {
413
        viewerPlugin.setZoomLevel(value);
414
    };
415
416
    /**
417
     * Zoom out by 10 %
418
     * @return {undefined}
419
     */
420
    this.zoomOut = function () {
421
        // 10 % decrement
422
        var newScale = (self.getZoomLevel() / kDefaultScaleDelta).toFixed(2);
423
        newScale     = Math.max(kMinScale, newScale);
424
        parseScale(newScale, true);
425
    };
426
427
    /**
428
     * Zoom in by 10%
429
     * @return {undefined}
430
     */
431
    this.zoomIn = function () {
432
        // 10 % increment
433
        var newScale = (self.getZoomLevel() * kDefaultScaleDelta).toFixed(2);
434
        newScale     = Math.min(kMaxScale, newScale);
435
        parseScale(newScale, true);
436
    };
437
438
    function cancelPresentationMode() {
439
        if ( presentationMode && !isFullScreen ) {
440
            self.togglePresentationMode();
441
        }
442
    }
443
444
    function handleFullScreenChange() {
445
        isFullScreen = !isFullScreen;
446
        cancelPresentationMode();
447
    }
448
449
    function showOverlayNavigator() {
450
        if ( presentationMode || viewerPlugin.isSlideshow() ) {
451
            overlayNavigator.className = 'viewer-touched';
452
            window.clearTimeout(touchTimer);
453
            touchTimer = window.setTimeout(function () {
454
                overlayNavigator.className = '';
455
            }, UI_FADE_DURATION);
456
        }
457
    }
458
459
    /**
460
     */
461
    function showToolbars() {
462
        titlebar.classList.add('viewer-touched');
463
        toolbar.classList.add('viewer-touched');
464
        window.clearTimeout(toolbarTouchTimer);
465
        toolbarTouchTimer = window.setTimeout(function () {
466
            hideToolbars();
467
        }, UI_FADE_DURATION);
468
    }
469
470
    function hideToolbars() {
471
        titlebar.classList.remove('viewer-touched');
472
        toolbar.classList.remove('viewer-touched');
473
    }
474
475
    function toggleToolbars() {
476
        if ( titlebar.classList.contains('viewer-touched') ) {
477
            hideToolbars();
478
        } else {
479
            showToolbars();
480
        }
481
    }
482
483
    function blankOut( value ) {
484
        blanked.style.display         = 'block';
485
        blanked.style.backgroundColor = value;
486
        hideToolbars();
487
    }
488
489
    function leaveBlankOut() {
490
        blanked.style.display = 'none';
491
        toggleToolbars();
492
    }
493
494
    function setButtonClickHandler( buttonId, handler ) {
495
        var button = document.getElementById(buttonId);
496
497
        button.addEventListener('click', function () {
498
            handler();
499
            button.blur();
500
        });
501
    }
502
503
    function init() {
504
505
        if ( viewerPlugin ) {
506
            self.initialize();
507
508
            if ( !(document.exitFullscreen || document.cancelFullScreen || document.mozCancelFullScreen || document.webkitExitFullscreen || document.webkitCancelFullScreen || document.msExitFullscreen) ) {
509
                document.getElementById('fullscreen').style.visibility   = 'hidden';
510
                document.getElementById('presentation').style.visibility = 'hidden';
511
            }
512
513
            setButtonClickHandler('overlayCloseButton', self.toggleFullScreen);
514
            setButtonClickHandler('fullscreen', self.toggleFullScreen);
515
            setButtonClickHandler('print', self.printDocument);
516
            setButtonClickHandler('presentation', function () {
517
                if ( !isFullScreen ) {
518
                    self.toggleFullScreen();
519
                }
520
                self.togglePresentationMode();
521
            });
522
523
            document.addEventListener('fullscreenchange', handleFullScreenChange);
524
            document.addEventListener('webkitfullscreenchange', handleFullScreenChange);
525
            document.addEventListener('mozfullscreenchange', handleFullScreenChange);
526
            document.addEventListener('MSFullscreenChange', handleFullScreenChange);
527
528
            setButtonClickHandler('download', self.download);
529
530
            setButtonClickHandler('zoomOut', self.zoomOut);
531
            setButtonClickHandler('zoomIn', self.zoomIn);
532
533
            setButtonClickHandler('previous', self.showPreviousPage);
534
            setButtonClickHandler('next', self.showNextPage);
535
536
            setButtonClickHandler('previousPage', self.showPreviousPage);
537
            setButtonClickHandler('nextPage', self.showNextPage);
538
539
            document.getElementById('pageNumber').addEventListener('change', function () {
540
                self.showPage(this.value);
541
            });
542
543
            document.getElementById('scaleSelect').addEventListener('change', function () {
544
                parseScale(this.value);
545
            });
546
547
            canvasContainer.addEventListener('click', showOverlayNavigator);
548
            overlayNavigator.addEventListener('click', showOverlayNavigator);
549
            canvasContainer.addEventListener('click', toggleToolbars);
550
            titlebar.addEventListener('click', showToolbars);
551
            toolbar.addEventListener('click', showToolbars);
552
553
            window.addEventListener('scalechange', function ( evt ) {
554
                var customScaleOption    = document.getElementById('customScaleOption'),
555
                    predefinedValueFound = selectScaleOption(String(evt.scale));
556
557
                customScaleOption.selected = false;
558
559
                if ( !predefinedValueFound ) {
560
                    customScaleOption.textContent = Math.round(evt.scale * 10000) / 100 + '%';
561
                    customScaleOption.selected    = true;
562
                }
563
            }, true);
564
565
            window.addEventListener('resize', function () {
566
                if ( initialized &&
567
                    (document.getElementById('pageWidthOption').selected ||
568
                    document.getElementById('pageAutoOption').selected) ) {
569
                    parseScale(document.getElementById('scaleSelect').value);
570
                }
571
                showOverlayNavigator();
572
            });
573
574
            window.addEventListener('keydown', function ( evt ) {
575
                var key      = evt.keyCode,
576
                    shiftKey = evt.shiftKey;
577
578
                // blanked-out mode?
579
                if ( isBlankedOut() ) {
580
                    switch ( key ) {
581
                        case 16: // Shift
582
                        case 17: // Ctrl
583
                        case 18: // Alt
584
                        case 91: // LeftMeta
585
                        case 93: // RightMeta
586
                        case 224: // MetaInMozilla
587
                        case 225: // AltGr
588
                            // ignore modifier keys alone
589
                            break;
590
                        default:
591
                            leaveBlankOut();
592
                            break;
593
                    }
594
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
595
                    switch ( key ) {
596
                        case 8: // backspace
597
                        case 33: // pageUp
598
                        case 37: // left arrow
599
                        case 38: // up arrow
600
                        case 80: // key 'p'
601
                            self.showPreviousPage();
602
                            break;
603
                        case 13: // enter
604
                        case 34: // pageDown
605
                        case 39: // right arrow
606
                        case 40: // down arrow
607
                        case 78: // key 'n'
608
                            self.showNextPage();
609
                            break;
610
                        case 32: // space
611
                            shiftKey ? self.showPreviousPage() : self.showNextPage();
612
                            break;
613
                        case 66:  // key 'b' blanks screen (to black) or returns to the document
614
                        case 190: // and so does the key '.' (dot)
615
                            if ( presentationMode ) {
616
                                blankOut('#000');
617
                            }
618
                            break;
619
                        case 87:  // key 'w' blanks page (to white) or returns to the document
620
                        case 188: // and so does the key ',' (comma)
621
                            if ( presentationMode ) {
622
                                blankOut('#FFF');
623
                            }
624
                            break;
625
                        case 36: // key 'Home' goes to first page
626
                            self.showPage(1);
627
                            break;
628
                        case 35: // key 'End' goes to last page
629
                            self.showPage(pages.length);
630
                            break;
631
                    }
632
                }
633
            });
634
        }
635
    }
636
637
    init();
638
}
639
/**
640
 * Copyright (C) 2012-2015 KO GmbH <[email protected]>
641
 *
642
 * @licstart
643
 * This file is part of ViewerJS.
644
 *
645
 * ViewerJS is free software: you can redistribute it and/or modify it
646
 * under the terms of the GNU Affero General Public License (GNU AGPL)
647
 * as published by the Free Software Foundation, either version 3 of
648
 * the License, or (at your option) any later version.
649
 *
650
 * ViewerJS is distributed in the hope that it will be useful, but
651
 * WITHOUT ANY WARRANTY; without even the implied warranty of
652
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
653
 * GNU Affero General Public License for more details.
654
 *
655
 * You should have received a copy of the GNU Affero General Public License
656
 * along with ViewerJS.  If not, see <http://www.gnu.org/licenses/>.
657
 * @licend
658
 *
659
 * @source: http://viewerjs.org/
660
 * @source: http://github.com/kogmbh/ViewerJS
661
 */
662
663
/*global document, window, Viewer, ODFViewerPlugin, PDFViewerPlugin*/
664
665
(function () {
666
    "use strict";
667
668
    var css,
0 ignored issues
show
Unused Code introduced by
The variable css seems to be never used. Consider removing it.
Loading history...
669
        pluginRegistry  = [
670
            (function () {
671
                var odfMimetypes      = [
672
                    'application/vnd.oasis.opendocument.text',
673
                    'application/vnd.oasis.opendocument.text-flat-xml',
674
                    'application/vnd.oasis.opendocument.text-template',
675
                    'application/vnd.oasis.opendocument.presentation',
676
                    'application/vnd.oasis.opendocument.presentation-flat-xml',
677
                    'application/vnd.oasis.opendocument.presentation-template',
678
                    'application/vnd.oasis.opendocument.spreadsheet',
679
                    'application/vnd.oasis.opendocument.spreadsheet-flat-xml',
680
                    'application/vnd.oasis.opendocument.spreadsheet-template'];
681
                var odfFileExtensions = [
682
                    'odt',
683
                    'fodt',
684
                    'ott',
685
                    'odp',
686
                    'fodp',
687
                    'otp',
688
                    'ods',
689
                    'fods',
690
                    'ots'];
691
692
                return {
693
                    supportsMimetype:      function ( mimetype ) {
694
                        return (odfMimetypes.indexOf(mimetype) !== -1);
695
                    },
696
                    supportsFileExtension: function ( extension ) {
697
                        return (odfFileExtensions.indexOf(extension) !== -1);
698
                    },
699
                    path:                  "./ODFViewerPlugin.js",
700
                    getClass:              function () {
701
                        return ODFViewerPlugin;
702
                    }
703
                };
704
            }()),
705
            (function () {
706
                var imageMimetypes      = [
707
                    'image/jpeg',
708
                    'image/pjpeg',
709
                    'image/gif',
710
                    'image/png',
711
                    'image/bmp'];
712
                var imageFileExtensions = [
713
                    'png',
714
                    'jpg',
715
                    'jpeg',
716
                    'gif',
717
                    'bmp'];
718
719
                return {
720
                    supportsMimetype:      function ( mimetype ) {
721
                        return (imageMimetypes.indexOf(mimetype) !== -1);
722
                    },
723
                    supportsFileExtension: function ( extension ) {
724
                        return (imageFileExtensions.indexOf(extension) !== -1);
725
                    },
726
                    path:                  "./ImageViewerPlugin.js",
727
                    getClass:              function () {
728
                        return ImageViewerPlugin;
729
                    }
730
                };
731
            }()),
732
            (function () {
733
                var multimediaMimetypes      = [
734
                    'video/mp4',
735
                    'video/ogg',
736
                    'video/webm',
737
                    'audio/aac',
738
                    'audio/mp4',
739
                    'audio/mpeg',
740
                    'audio/ogg',
741
                    'audio/wav',
742
                    'audio/webm'];
743
                var multimediaFileExtensions = [
744
                    'aac',
745
                    'mp4',
746
                    'm4a',
747
                    'mp3',
748
                    'mpg',
749
                    'mpeg',
750
                    'ogg',
751
                    'wav',
752
                    'webm',
753
                    'm4v',
754
                    'ogv',
755
                    'oga',
756
                    'mp1',
757
                    'mp2'];
758
759
                return {
760
                    supportsMimetype:      function ( mimetype ) {
761
                        return (multimediaMimetypes.indexOf(mimetype) !== -1);
762
                    },
763
                    supportsFileExtension: function ( extension ) {
764
                        return (multimediaFileExtensions.indexOf(extension) !== -1);
765
                    },
766
                    path:                  "./MultimediaViewerPlugin.js",
767
                    getClass:              function () {
768
                        return MultimediaViewerPlugin;
769
                    }
770
                };
771
            }())
772
        ],
773
        unknownFileType = {
774
            supportsMimetype:      function () {
775
                return true;
776
            },
777
            supportsFileExtension: function () {
778
                return true;
779
            },
780
            path:                  "./UnknownFilePlugin.js",
781
            getClass:              function () {
782
                return UnknownFilePlugin;
783
            }
784
        };
785
786
    function estimateTypeByHeaderContentType( documentUrl, cb ) {
787
        var xhr                = new XMLHttpRequest();
788
        xhr.onreadystatechange = function () {
789
            var mimetype, matchingPluginData;
790
            if ( xhr.readyState === 4 ) {
791
                if ( (xhr.status >= 200 && xhr.status < 300) || xhr.status === 0 ) {
792
                    mimetype = xhr.getResponseHeader('content-type');
793
794
                    if ( mimetype ) {
795
                        pluginRegistry.some(function ( pluginData ) {
796
                            if ( pluginData.supportsMimetype(mimetype) ) {
797
                                matchingPluginData = pluginData;
798
                                console.log('Found plugin by mimetype and xhr head: ' + mimetype);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
799
                                // store the mimetype globally
800
                                window.mimetype = mimetype;
801
                                return true;
802
                            }
803
                            return false;
804
                        });
805
                    }
806
                }
807
                if ( !matchingPluginData ) {
808
                    matchingPluginData = unknownFileType;
809
                }
810
                cb(matchingPluginData);
811
            }
812
        };
813
        xhr.open("HEAD", documentUrl, true);
814
        xhr.send();
815
    }
816
817
    function doEstimateTypeByFileExtension( extension ) {
818
        var matchingPluginData;
819
820
        pluginRegistry.some(function ( pluginData ) {
821
            if ( pluginData.supportsFileExtension(extension) ) {
822
                matchingPluginData = pluginData;
823
                return true;
824
            }
825
            return false;
826
        });
827
828
        return matchingPluginData;
829
    }
830
831
    function estimateTypeByFileExtension( extension ) {
832
        var matchingPluginData = doEstimateTypeByFileExtension(extension)
833
834
        if ( matchingPluginData ) {
835
            console.log('Found plugin by parameter type: ' + extension);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
836
837
            // this is needed for the Multimedia Plugin
838
            window.mimetype = getMimeByExtension(extension);
839
        }
840
841
        return matchingPluginData;
842
    }
843
844
    function estimateTypeByFileExtensionFromPath( documentUrl ) {
845
        // See to get any path from the url and grep what could be a file extension
846
        var documentPath       = documentUrl.split('?')[0],
847
            extension          = documentPath.split('.').pop(),
848
            matchingPluginData = doEstimateTypeByFileExtension(extension)
849
850
        if ( matchingPluginData ) {
851
            console.log('Found plugin by file extension from path: ' + extension);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
852
        }
853
854
        return matchingPluginData;
855
    }
856
857
    function parseSearchParameters( location ) {
858
        var parameters = {},
859
            search     = location.search || "?";
860
861
        search.substr(1).split('&').forEach(function ( q ) {
862
            // skip empty strings
863
            if ( !q ) {
864
                return;
865
            }
866
            // if there is no '=', have it handled as if given key was set to undefined
867
            var s                                = q.split('=', 2);
868
            parameters[decodeURIComponent(s[0])] = decodeURIComponent(s[1]);
869
        });
870
871
        return parameters;
872
    }
873
874
    function getMimeByExtension( ext ) {
875
        var extToMimes = {
876
            'aac':  'audio/aac',
877
            'mp4':  'video/mp4',
878
            'm4a':  'audio/mp4',
879
            'mp3':  'audio/mpeg',
880
            'mpg':  'video/mpeg',
881
            'mpeg': 'video/mpeg',
882
            'ogg':  'video/ogg',
883
            'wav':  'audio/wav',
884
            'webm': 'video/webm',
885
            'm4v':  'video/mp4',
886
            'ogv':  'video/ogg',
887
            'oga':  'audio/ogg',
888
            'mp1':  'audio/mpeg',
889
            'mp2':  'audio/mpeg'
890
        };
891
892
        if ( extToMimes.hasOwnProperty(ext) ) {
893
            return extToMimes[ext];
894
        }
895
        return false;
896
    }
897
898
    window.onload = function () {
899
        var viewer,
900
            documentUrl = document.location.hash.substring(1),
901
            parameters  = parseSearchParameters(document.location),
902
            Plugin;
903
904
        if ( documentUrl ) {
905
            // try to guess the title as filename from the location, if not set by parameter
906
            if ( !parameters.title ) {
907
                parameters.title = documentUrl.replace(/^.*[\\\/]/, '');
908
            }
909
910
            parameters.documentUrl = documentUrl;
911
912
            // trust the server most
913
            estimateTypeByHeaderContentType(documentUrl, function ( pluginData ) {
914
                if ( !pluginData ) {
915
                    if ( parameters.type ) {
916
                        pluginData = estimateTypeByFileExtension(parameters.type);
917
                    } else {
918
                        // last ressort: try to guess from path
919
                        pluginData = estimateTypeByFileExtensionFromPath(documentUrl);
920
                    }
921
                }
922
923
                if ( pluginData ) {
924
                    if ( String(typeof loadPlugin) !== "undefined" ) {
925
                        loadPlugin(pluginData.path, function () {
926
                            Plugin = pluginData.getClass();
927
                            viewer = new Viewer(new Plugin(), parameters);
0 ignored issues
show
Unused Code introduced by
The variable viewer seems to be never used. Consider removing it.
Loading history...
928
                        });
929
                    } else {
930
                        Plugin = pluginData.getClass();
931
                        viewer = new Viewer(new Plugin(), parameters);
0 ignored issues
show
Unused Code introduced by
The variable viewer seems to be never used. Consider removing it.
Loading history...
932
                    }
933
                } else {
934
                    viewer = new Viewer();
935
                }
936
            });
937
        } else {
938
            viewer = new Viewer();
0 ignored issues
show
Unused Code introduced by
The variable viewer seems to be never used. Consider removing it.
Loading history...
939
        }
940
    };
941
942
    /*css = (document.createElementNS(document.head.namespaceURI, 'style'));
943
     css.setAttribute('media', 'screen');
944
     css.setAttribute('type', 'text/css');
945
     css.appendChild(document.createTextNode(viewer_css));
946
     document.head.appendChild(css);
947
948
     css = (document.createElementNS(document.head.namespaceURI, 'style'));
949
     css.setAttribute('media', 'only screen and (max-device-width: 800px) and (max-device-height: 800px)');
950
     css.setAttribute('type', 'text/css');
951
     css.setAttribute('viewerTouch', '1');
952
     css.appendChild(document.createTextNode(viewerTouch_css));
953
     document.head.appendChild(css);
954
     */
955
}());
956