Completed
Push — master ( f65d8f...4f3de5 )
by Pavel
04:14 queued 01:54
created

docstemplate/main.js   F

Complexity

Total Complexity 140
Complexity/F 2.75

Size

Lines of Code 771
Function Count 51

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 0
nc 127401984
dl 0
loc 771
rs 2.1818
c 1
b 0
f 1
wmc 140
mnd 4
bc 82
fnc 51
bpm 1.6077
cpm 2.745
noi 47

How to fix   Complexity   

Complexity

Complex classes like docstemplate/main.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
require.config({
2
    paths: {
3
        bootstrap: './vendor/bootstrap.min',
4
        diffMatchPatch: './vendor/diff_match_patch.min',
5
        handlebars: './vendor/handlebars.min',
6
        handlebarsExtended: './utils/handlebars_helper',
7
        jquery: './vendor/jquery.min',
8
        locales: './locales/locale',
9
        lodash: './vendor/lodash.min',
10
        pathToRegexp: './vendor/path-to-regexp/index',
11
        prettify: './vendor/prettify/prettify',
12
        semver: './vendor/semver.min',
13
        utilsSampleRequest: './utils/send_sample_request',
14
        webfontloader: './vendor/webfontloader',
15
        jsoneditor: './vendor/jsoneditor/jsoneditor'
16
    },
17
    shim: {
18
        bootstrap: {
19
            deps: ['jquery']
20
        },
21
        diffMatchPatch: {
22
            exports: 'diff_match_patch'
23
        },
24
        handlebars: {
25
            exports: 'Handlebars'
26
        },
27
        handlebarsExtended: {
28
            deps: ['jquery', 'handlebars'],
29
            exports: 'Handlebars'
30
        },
31
        prettify: {
32
            exports: 'prettyPrint'
33
        }
34
    },
35
    urlArgs: 'v=' + (new Date()).getTime(),
36
    waitSeconds: 15
37
});
38
39
require([
40
    'jquery',
41
    'lodash',
42
    'locales',
43
    'handlebarsExtended',
44
    './api_project.js',
45
    './api_data.js',
46
    'prettify',
47
    'utilsSampleRequest',
48
    'semver',
49
    'webfontloader',
50
    'jsoneditor',
51
    'bootstrap',
52
    'pathToRegexp'
53
], function($, _, locale, Handlebars, apiProject, apiData, prettyPrint, sampleRequest, semver, WebFont, JSONEditor) {
54
55
    // load google web fonts
56
    loadGoogleFontCss();
57
58
    var api = apiData.api;
59
60
    var jsonEditors = {};
61
62
    Handlebars.registerHelper("log", function(optionalValue) {
63
        if (optionalValue) {
64
            console.log(optionalValue);
65
        }
66
    });
67
68
    //
69
    // Templates
70
    //
71
    var templateHeader         = Handlebars.compile( $('#template-header').html() );
72
    var templateFooter         = Handlebars.compile( $('#template-footer').html() );
73
    var templateArticle        = Handlebars.compile( $('#template-article').html() );
74
    var templateCompareArticle = Handlebars.compile( $('#template-compare-article').html() );
75
    var templateGenerator      = Handlebars.compile( $('#template-generator').html() );
76
    var templateProject        = Handlebars.compile( $('#template-project').html() );
77
    var templateSections       = Handlebars.compile( $('#template-sections').html() );
78
    var templateSidenav        = Handlebars.compile( $('#template-sidenav').html() );
79
80
    //
81
    // apiProject defaults
82
    //
83
    if ( ! apiProject.template)
84
        apiProject.template = {};
85
86
    if (apiProject.template.withCompare == null)
87
        apiProject.template.withCompare = true;
88
89
    if (apiProject.template.withGenerator == null)
90
        apiProject.template.withGenerator = true;
91
92
    if (apiProject.template.forceLanguage)
93
        locale.setLanguage(apiProject.template.forceLanguage);
94
95
    // Setup jQuery Ajax
96
    $.ajaxSetup(apiProject.template.jQueryAjaxSetup);
97
98
    //
99
    // Data transform
100
    //
101
    // grouped by group
102
    var apiByGroup = _.groupBy(api, function(entry) {
103
        return entry.group;
104
    });
105
106
    // grouped by group and name
107
    var apiByGroupAndName = {};
108
    $.each(apiByGroup, function(index, entries) {
109
        apiByGroupAndName[index] = _.groupBy(entries, function(entry) {
110
            return entry.name;
111
        });
112
    });
113
114
    //
115
    // sort api within a group by title ASC and custom order
116
    //
117
    var newList = [];
118
    var umlauts = { 'ä': 'ae', 'ü': 'ue', 'ö': 'oe', 'ß': 'ss' }; // TODO: remove in version 1.0
119
    $.each (apiByGroupAndName, function(index, groupEntries) {
120
        // get titles from the first entry of group[].name[] (name has versioning)
121
        var titles = [];
122
        $.each (groupEntries, function(titleName, entries) {
123
            var title = entries[0].title;
124
            if(title !== undefined) {
125
                title.toLowerCase().replace(/[äöüß]/g, function($0) { return umlauts[$0]; });
126
                titles.push(title + '#~#' + titleName); // '#~#' keep reference to titleName after sorting
127
            }
128
        });
129
        // sort by name ASC
130
        titles.sort();
131
132
        // custom order
133
        if (apiProject.order)
134
            titles = sortByOrder(titles, apiProject.order, '#~#');
135
136
        // add single elements to the new list
137
        titles.forEach(function(name) {
138
            var values = name.split('#~#');
139
            var key = values[1];
140
            groupEntries[key].forEach(function(entry) {
141
                newList.push(entry);
142
            });
143
        });
144
    });
145
    // api overwrite with ordered list
146
    api = newList;
147
148
    //
149
    // Group- and Versionlists
150
    //
151
    var apiGroups = {};
152
    var apiGroupTitles = {};
153
    var apiVersions = {};
154
    apiVersions[apiProject.version] = 1;
155
156
    $.each(api, function(index, entry) {
157
        apiGroups[entry.group] = 1;
158
        apiGroupTitles[entry.group] = entry.groupTitle || entry.group;
159
        apiVersions[entry.version] = 1;
160
    });
161
162
    // sort groups
163
    apiGroups = Object.keys(apiGroups);
164
    apiGroups.sort();
165
166
    // custom order
167
    if (apiProject.order)
168
        apiGroups = sortByOrder(apiGroups, apiProject.order);
169
170
    // sort versions DESC
171
    apiVersions = Object.keys(apiVersions);
172
    apiVersions.sort(semver.compare);
173
    apiVersions.reverse();
174
175
    //
176
    // create Navigationlist
177
    //
178
    var nav = [];
179
    apiGroups.forEach(function(group) {
180
        // Mainmenu entry
181
        nav.push({
182
            group: group,
183
            isHeader: true,
184
            title: apiGroupTitles[group]
185
        });
186
187
        // Submenu
188
        var oldName = '';
189
        api.forEach(function(entry) {
190
            if (entry.group === group) {
191
                if (oldName !== entry.name) {
192
                    nav.push({
193
                        title: entry.title,
194
                        group: group,
195
                        name: entry.name,
196
                        type: entry.type,
197
                        version: entry.version
198
                    });
199
                } else {
200
                    nav.push({
201
                        title: entry.title,
202
                        group: group,
203
                        hidden: true,
204
                        name: entry.name,
205
                        type: entry.type,
206
                        version: entry.version
207
                    });
208
                }
209
                oldName = entry.name;
210
            }
211
        });
212
    });
213
214
    // Mainmenu Header entry
215
    if (apiProject.header) {
216
        nav.unshift({
217
            group: '_',
218
            isHeader: true,
219
            title: (apiProject.header.title == null) ? locale.__('General') : apiProject.header.title,
220
            isFixed: true
221
        });
222
    }
223
224
    // Mainmenu Footer entry
225
    if (apiProject.footer && apiProject.footer.title != null) {
226
        nav.push({
227
            group: '_footer',
228
            isHeader: true,
229
            title: apiProject.footer.title,
230
            isFixed: true
231
        });
232
    }
233
234
    // render pagetitle
235
    var title = apiProject.title ? apiProject.title : 'apiDoc: ' + apiProject.name + ' - ' + apiProject.version;
236
    $(document).attr('title', title);
237
238
    // remove loader
239
    $('#loader').remove();
240
241
    // render sidenav
242
    var fields = {
243
        nav: nav
244
    };
245
    $('#sidenav').append( templateSidenav(fields) );
246
247
    // render Generator
248
    $('#generator').append( templateGenerator(apiProject) );
249
250
    // render Project
251
    _.extend(apiProject, { versions: apiVersions});
252
    $('#project').append( templateProject(apiProject) );
253
254
    // render apiDoc, header/footer documentation
255
    if (apiProject.header)
256
        $('#header').append( templateHeader(apiProject.header) );
257
258
    if (apiProject.footer)
259
        $('#footer').append( templateFooter(apiProject.footer) );
260
261
    //
262
    // Render Sections and Articles
263
    //
264
    var articleVersions = {};
265
    var content = '';
266
    apiGroups.forEach(function(groupEntry) {
267
        var articles = [];
268
        var oldName = '';
269
        var fields = {};
270
        var title = groupEntry;
271
        var description = '';
272
        articleVersions[groupEntry] = {};
273
274
        // render all articles of a group
275
        api.forEach(function(entry) {
276
            if(groupEntry === entry.group) {
277
                if (oldName !== entry.name) {
278
                    // determine versions
279
                    api.forEach(function(versionEntry) {
280
                        if (groupEntry === versionEntry.group && entry.name === versionEntry.name) {
281
                            if ( ! articleVersions[entry.group].hasOwnProperty(entry.name) ) {
282
                                articleVersions[entry.group][entry.name] = [];
283
                            }
284
                            articleVersions[entry.group][entry.name].push(versionEntry.version);
285
                        }
286
                    });
287
                    fields = {
288
                        article: entry,
289
                        versions: articleVersions[entry.group][entry.name]
290
                    };
291
                } else {
292
                    fields = {
293
                        article: entry,
294
                        hidden: true,
295
                        versions: articleVersions[entry.group][entry.name]
296
                    };
297
                }
298
299
                // add prefix URL for endpoint
300
                if (apiProject.url)
301
                    fields.article.url = apiProject.url + fields.article.url;
302
303
                addArticleSettings(fields, entry);
304
305
                if (entry.groupTitle)
306
                    title = entry.groupTitle;
307
308
                // TODO: make groupDescription compareable with older versions (not important for the moment)
309
                if (entry.groupDescription)
310
                    description = entry.groupDescription;
311
312
                articles.push({
313
                    article: templateArticle(fields),
314
                    group: entry.group,
315
                    name: entry.name
316
                });
317
                oldName = entry.name;
318
            }
319
        });
320
321
        // render Section with Articles
322
        var fields = {
323
            group: groupEntry,
324
            title: title,
325
            description: description,
326
            articles: articles
327
        };
328
        content += templateSections(fields);
329
    });
330
    $('#sections').append( content );
331
332
    // Bootstrap Scrollspy
333
    $(this).scrollspy({ target: '#scrollingNav', offset: 18 });
334
335
    // Content-Scroll on Navigation click.
336
    $('.sidenav').find('a').on('click', function(e) {
337
        e.preventDefault();
338
        var id = $(this).attr('href');
339
        if ($(id).length > 0)
340
            $('html,body').animate({ scrollTop: parseInt($(id).offset().top) }, 400);
341
        window.location.hash = $(this).attr('href');
342
    });
343
344
    // Quickjump on Pageload to hash position.
345
    if(window.location.hash) {
346
        var id = window.location.hash;
347
        if ($(id).length > 0)
348
            $('html,body').animate({ scrollTop: parseInt($(id).offset().top) }, 0);
349
    }
350
351
    /**
352
     * Check if Parameter (sub) List has a type Field.
353
     * Example: @apiSuccess          varname1 No type.
354
     *          @apiSuccess {String} varname2 With type.
355
     *
356
     * @param {Object} fields
357
     */
358
    function _hasTypeInFields(fields) {
359
        var result = false;
360
        $.each(fields, function(name) {
361
            if (_.any(fields[name], function(item) { return item.type; }) )
362
                result = true;
363
        });
364
        return result;
365
    }
366
367
    /**
368
     * On Template changes, recall plugins.
369
     */
370
    function initDynamic(jsonEditors) {
371
        // bootstrap popover
372
        $('a[data-toggle=popover]')
373
            .popover()
374
            .click(function(e) {
375
                e.preventDefault();
376
            })
377
        ;
378
379
        var version = $('#version strong').html();
380
        $('#sidenav li').removeClass('is-new');
381
        if (apiProject.template.withCompare) {
382
            $('#sidenav li[data-version=\'' + version + '\']').each(function(){
383
                var group = $(this).data('group');
384
                var name = $(this).data('name');
385
                var length = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').length;
386
                var index  = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').index($(this));
387
                if (length === 1 || index === (length - 1))
388
                    $(this).addClass('is-new');
389
            });
390
        }
391
392
        // tabs
393
        $('.nav-tabs-examples a').click(function (e) {
394
            e.preventDefault();
395
            $(this).tab('show');
396
        });
397
        $('.nav-tabs-examples').find('a:first').tab('show');
398
399
        // sample request switch
400
        $('.sample-request-switch').click(function (e) {
401
            var name = '.' + $(this).attr('name') + '-fields';
402
            $(name).addClass('hide');
403
            $(this).parent().next(name).removeClass('hide');
404
        });
405
406
        // call scrollspy refresh method
407
        $(window).scrollspy('refresh');
408
409
        // init modules
410
        sampleRequest.initDynamic(jsonEditors);
411
    }
412
    initDynamic(jsonEditors);
413
414
    // Pre- / Code-Format
415
    prettyPrint();
416
417
    //
418
    // HTML-Template specific jQuery-Functions
419
    //
420
    // Change Main Version
421
    $('#versions li.version a').on('click', function(e) {
422
        e.preventDefault();
423
424
        var selectedVersion = $(this).html();
425
        $('#version strong').html(selectedVersion);
426
427
        // hide all
428
        $('article').addClass('hide');
429
        $('#sidenav li:not(.nav-fixed)').addClass('hide');
430
431
        // show 1st equal or lower Version of each entry
432
        $('article[data-version]').each(function(index) {
433
            var group = $(this).data('group');
434
            var name = $(this).data('name');
435
            var version = $(this).data('version');
436
437
            if (version <= selectedVersion) {
438
                if ($('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible').length === 0) {
439
                    // enable Article
440
                    $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide');
441
                    // enable Navigation
442
                    $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide');
443
                    $('#sidenav li.nav-header[data-group=\'' + group + '\']').removeClass('hide');
444
                }
445
            }
446
        });
447
448
449
        // show 1st equal or lower Version of each entry
450
        $('article[data-version]').each(function(index) {
451
            var group = $(this).data('group');
452
            $('section#api-' + group).removeClass('hide');
453
            if ($('section#api-' + group + ' article:visible').length === 0) {
454
                $('section#api-' + group).addClass('hide');
455
            } else {
456
                $('section#api-' + group).removeClass('hide');
457
            }
458
        });
459
460
        initDynamic(jsonEditors);
461
        return;
462
    });
463
464
    // compare all article with their predecessor
465
    $('#compareAllWithPredecessor').on('click', changeAllVersionCompareTo);
466
467
    // change version of an article
468
    $('article .versions li.version a').on('click', changeVersionCompareTo);
469
470
    // compare url-parameter
471
    $.urlParam = function(name) {
472
        var results = new RegExp('[\\?&amp;]' + name + '=([^&amp;#]*)').exec(window.location.href);
473
        return (results && results[1]) ? results[1] : null;
474
    };
475
476
    if ($.urlParam('compare')) {
477
        // URL Paramter ?compare=1 is set
478
        $('#compareAllWithPredecessor').trigger('click');
479
480
        if (window.location.hash) {
481
            var id = window.location.hash;
482
            $('html,body').animate({ scrollTop: parseInt($(id).offset().top) - 18 }, 0);
483
        }
484
    }
485
486
    /**
487
     * Change version of an article to compare it to an other version.
488
     */
489
    function changeVersionCompareTo(e) {
490
        e.preventDefault();
491
492
        var $root = $(this).parents('article');
493
        var selectedVersion = $(this).html();
494
        var $button = $root.find('.version');
495
        var currentVersion = $button.find('strong').html();
496
        $button.find('strong').html(selectedVersion);
497
498
        var group = $root.data('group');
499
        var name = $root.data('name');
500
        var version = $root.data('version');
501
502
        var compareVersion = $root.data('compare-version');
503
504
        if (compareVersion === selectedVersion)
505
            return;
506
507
        if ( ! compareVersion && version == selectedVersion)
508
            return;
509
510
        if (compareVersion && articleVersions[group][name][0] === selectedVersion || version === selectedVersion) {
511
            // the version of the entry is set to the highest version (reset)
512
            resetArticle(group, name, version);
513
        } else {
514
            var $compareToArticle = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + selectedVersion + '\']');
515
516
            var sourceEntry = {};
517
            var compareEntry = {};
518
            $.each(apiByGroupAndName[group][name], function(index, entry) {
519
                if (entry.version === version)
520
                    sourceEntry = entry;
521
                if (entry.version === selectedVersion)
522
                    compareEntry = entry;
523
            });
524
525
            var fields = {
526
                article: sourceEntry,
527
                compare: compareEntry,
528
                versions: articleVersions[group][name]
529
            };
530
531
            // add unique id
532
            // TODO: replace all group-name-version in template with id.
533
            fields.article.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version;
534
            fields.article.id = fields.article.id.replace(/\./g, '_');
535
536
            fields.compare.id = fields.compare.group + '-' + fields.compare.name + '-' + fields.compare.version;
537
            fields.compare.id = fields.compare.id.replace(/\./g, '_');
538
539
            var entry = sourceEntry;
540
            if (entry.parameter && entry.parameter.fields)
541
                fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields);
542
543
            if (entry.error && entry.error.fields)
544
                fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields);
545
546
            if (entry.success && entry.success.fields)
547
                fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields);
548
549
            if (entry.info && entry.info.fields)
550
                fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields);
551
552
            var entry = compareEntry;
553
            if (fields._hasTypeInParameterFields !== true && entry.parameter && entry.parameter.fields)
554
                fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields);
555
556
            if (fields._hasTypeInErrorFields !== true && entry.error && entry.error.fields)
557
                fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields);
558
559
            if (fields._hasTypeInSuccessFields !== true && entry.success && entry.success.fields)
560
                fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields);
561
562
            if (fields._hasTypeInInfoFields !== true && entry.info && entry.info.fields)
563
                fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields);
564
565
            var content = templateCompareArticle(fields);
566
            $root.after(content);
567
            var $content = $root.next();
568
569
            // Event on.click re-assign
570
            $content.find('.versions li.version a').on('click', changeVersionCompareTo);
571
572
            // select navigation
573
            $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + currentVersion + '\']').addClass('has-modifications');
574
575
            $root.remove();
576
            // TODO: on change main version or select the highest version re-render
577
        }
578
579
        initDynamic(jsonEditors);
580
    }
581
582
    /**
583
     * Compare all currently selected Versions with their predecessor.
584
     */
585
    function changeAllVersionCompareTo(e) {
586
        e.preventDefault();
587
        $('article:visible .versions').each(function(){
588
            var $root = $(this).parents('article');
589
            var currentVersion = $root.data('version');
590
            var $foundElement = null;
591
            $(this).find('li.version a').each(function() {
592
                var selectVersion = $(this).html();
593
                if (selectVersion < currentVersion && ! $foundElement)
594
                    $foundElement = $(this);
595
            });
596
597
            if($foundElement)
598
                $foundElement.trigger('click');
599
        });
600
        initDynamic(jsonEditors);
601
    }
602
603
    /**
604
     * Sort the fields.
605
     */
606
    function sortFields(fields_object) {
607
        $.each(fields_object, function (key, fields) {
608
609
            var reversed = fields.slice().reverse()
610
611
            var max_dot_count = Math.max.apply(null, reversed.map(function (item) {
612
                return item.field.split(".").length - 1;
613
            }))
614
615
            for (var dot_count = 1; dot_count <= max_dot_count; dot_count++) {
616
                reversed.forEach(function (item, index) {
617
                    var parts = item.field.split(".");
618
                    if (parts.length - 1 == dot_count) {
619
                        var fields_names = fields.map(function (item) { return item.field; });
620
                        if (parts.slice(1).length  >= 1) {
621
                            var prefix = parts.slice(0, parts.length - 1).join(".");
622
                            var prefix_index = fields_names.indexOf(prefix);
623
                            if (prefix_index > -1) {
624
                                fields.splice(fields_names.indexOf(item.field), 1);
625
                                fields.splice(prefix_index + 1, 0, item);
626
                            }
627
                        }
628
                    }
629
                });
630
            }
631
        });
632
    }
633
634
    /**
635
     * Add article settings.
636
     */
637
    function addArticleSettings(fields, entry) {
638
        // add unique id
639
        // TODO: replace all group-name-version in template with id.
640
        fields.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version;
641
        fields.id = fields.id.replace(/\./g, '_');
642
643
        if (entry.header && entry.header.fields) {
644
            sortFields(entry.header.fields);
645
            fields._hasTypeInHeaderFields = _hasTypeInFields(entry.header.fields);
646
        }
647
648
        if (entry.parameter && entry.parameter.fields) {
649
            sortFields(entry.parameter.fields);
650
            fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields);
651
        }
652
653
        if (entry.error && entry.error.fields) {
654
            sortFields(entry.error.fields);
655
            fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields);
656
        }
657
658
        if (entry.success && entry.success.fields) {
659
            sortFields(entry.success.fields);
660
            fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields);
661
        }
662
663
        if (entry.info && entry.info.fields) {
664
            sortFields(entry.info.fields);
665
            fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields);
666
        }
667
668
        // add template settings
669
        fields.template = apiProject.template;
670
    }
671
672
    /**
673
     * Render Article.
674
     */
675
    function renderArticle(group, name, version) {
676
        var entry = {};
677
        $.each(apiByGroupAndName[group][name], function(index, currentEntry) {
678
            if (currentEntry.version === version)
679
                entry = currentEntry;
680
        });
681
        var fields = {
682
            article: entry,
683
            versions: articleVersions[group][name]
684
        };
685
686
        addArticleSettings(fields, entry);
687
688
        return templateArticle(fields);
689
    }
690
691
    /**
692
     * Render original Article and remove the current visible Article.
693
     */
694
    function resetArticle(group, name, version) {
695
        var $root = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible');
696
        var content = renderArticle(group, name, version);
697
698
        $root.after(content);
699
        var $content = $root.next();
700
701
        // Event on.click muss neu zugewiesen werden (sollte eigentlich mit on automatisch funktionieren... sollte)
702
        $content.find('.versions li.version a').on('click', changeVersionCompareTo);
703
704
        $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('has-modifications');
705
706
        $root.remove();
707
        return;
708
    }
709
710
    /**
711
     * Load google fonts.
712
     */
713
    function loadGoogleFontCss() {
714
        WebFont.load({
715
            active: function() {
716
                // Update scrollspy
717
                $(window).scrollspy('refresh')
718
            },
719
            google: {
720
                families: ['Source Code Pro', 'Source Sans Pro:n4,n6,n7']
721
            }
722
        });
723
    }
724
725
    /**
726
     * Return ordered entries by custom order and append not defined entries to the end.
727
     * @param  {String[]} elements
728
     * @param  {String[]} order
729
     * @param  {String}   splitBy
730
     * @return {String[]} Custom ordered list.
731
     */
732
    function sortByOrder(elements, order, splitBy) {
733
        var results = [];
734
        order.forEach (function(name) {
735
            if (splitBy)
736
                elements.forEach (function(element) {
737
                    var parts = element.split(splitBy);
738
                    var key = parts[1]; // reference keep for sorting
739
                    if (key == name)
740
                        results.push(element);
741
                });
742
            else
743
                elements.forEach (function(key) {
744
                    if (key == name)
745
                        results.push(name);
746
                });
747
        });
748
        // Append all other entries that ar not defined in order
749
        elements.forEach(function(element) {
750
            if (results.indexOf(element) === -1)
751
                results.push(element);
752
        });
753
        return results;
754
    }
755
756
    $('.jsoneditor').each(function(){
757
        var container = document.getElementById($(this).attr('id'));
758
        var key = $(this).data('jsoneditor-key');
759
        var json = $(this).text();
760
        $(this).text('');
761
        var options = {
762
            modes: ['text'],
763
            mode: 'text',
764
            search: false
765
        };
766
        jsonEditors[key] = new JSONEditor(container, options, JSON.parse(json));
767
    });
768
769
    initDynamic(jsonEditors);
770
771
});
772