1var connectApiBasePath = window.__connectApiAssetBasePath || '/connect_api/'; 2var connectApiDataBasePath = window.__connectApiBasePath || connectApiBasePath; 3 4if (connectApiBasePath.slice(-1) !== '/') { 5 connectApiBasePath += '/'; 6} 7 8if (connectApiDataBasePath.slice(-1) !== '/') { 9 connectApiDataBasePath += '/'; 10} 11 12function connectApiAsset(path) { 13 return connectApiBasePath + path; 14} 15 16function connectApiDataAsset(path) { 17 return connectApiDataBasePath + path; 18} 19 20require.config({ 21 paths: { 22 bootstrap: connectApiAsset('vendor/bootstrap.min'), 23 diffMatchPatch: connectApiAsset('vendor/diff_match_patch.min'), 24 handlebars: connectApiAsset('vendor/handlebars.min'), 25 handlebarsExtended: connectApiAsset('utils/handlebars_helper'), 26 jquery: connectApiAsset('vendor/jquery.min'), 27 locales: connectApiAsset('locales/locale'), 28 lodash: connectApiAsset('vendor/lodash.custom.min'), 29 pathToRegexp: connectApiAsset('vendor/path-to-regexp/index'), 30 prettify: connectApiAsset('vendor/prettify/prettify'), 31 semver: connectApiAsset('vendor/semver.min'), 32 utilsSampleRequest: connectApiAsset('utils/send_sample_request'), 33 webfontloader: connectApiAsset('vendor/webfontloader'), 34 list: connectApiAsset('vendor/list.min') 35 }, 36 shim: { 37 bootstrap: { 38 deps: ['jquery'] 39 }, 40 diffMatchPatch: { 41 exports: 'diff_match_patch' 42 }, 43 handlebars: { 44 exports: 'Handlebars' 45 }, 46 handlebarsExtended: { 47 deps: ['jquery', 'handlebars'], 48 exports: 'Handlebars' 49 }, 50 prettify: { 51 exports: 'prettyPrint' 52 } 53 }, 54 urlArgs: window.__apiDocsAssetVersion || 'v=20260714-api-docs-v5', 55 waitSeconds: 15 56}); 57 58require([ 59 'jquery', 60 'lodash', 61 'locales', 62 'handlebarsExtended', 63 connectApiDataAsset('api_project.js'), 64 connectApiDataAsset('api_data.js'), 65 'prettify', 66 'utilsSampleRequest', 67 'semver', 68 'webfontloader', 69 'bootstrap', 70 'pathToRegexp', 71 'list' 72], function($, _, locale, Handlebars, apiProject, apiData, prettyPrint, sampleRequest, semver, WebFont) { 73 74 var initialScrollLock = window.__apiDocsInitialScrollLock; 75 var setApiDocsLoadingProgress = window.__apiDocsSetLoadingProgress || function() {}; 76 var initialAnchorHash = window.location.hash || window.__apiDocsInitialHash || ''; 77 var shouldResetInitialScroll = !!document.querySelector('.api-docs-page') && (!initialAnchorHash || initialAnchorHash === '#top'); 78 var initialScrollResetStartedAt = Date.now(); 79 var initialScrollResetDuration = 3000; 80 var initialScrollResetReleased = false; 81 var sampleRequestInitQueued = false; 82 83 function debounceApiDocs(fn, wait) { 84 var timeout; 85 86 return function() { 87 var context = this; 88 var args = arguments; 89 90 window.clearTimeout(timeout); 91 timeout = window.setTimeout(function() { 92 fn.apply(context, args); 93 }, wait); 94 }; 95 } 96 var exampleTabsResizeBound = false; 97 98 setApiDocsLoadingProgress(68); 99 100 if (shouldResetInitialScroll && 'scrollRestoration' in window.history) { 101 window.history.scrollRestoration = 'manual'; 102 } 103 104 if (shouldResetInitialScroll) { 105 ['wheel', 'touchstart', 'mousedown', 'keydown'].forEach(function(eventName) { 106 window.addEventListener(eventName, function() { 107 initialScrollResetReleased = true; 108 }, { once: true, passive: true }); 109 }); 110 } 111 112 function resetInitialScrollPosition() { 113 if ( 114 shouldResetInitialScroll && 115 !initialScrollResetReleased && 116 Date.now() - initialScrollResetStartedAt < initialScrollResetDuration 117 ) { 118 window.scrollTo(0, 0); 119 if (initialScrollLock && typeof initialScrollLock.reset === 'function') { 120 initialScrollLock.reset(); 121 } 122 } 123 } 124 125 function holdInitialScrollPosition() { 126 resetInitialScrollPosition(); 127 128 if ( 129 shouldResetInitialScroll && 130 !initialScrollResetReleased && 131 Date.now() - initialScrollResetStartedAt < initialScrollResetDuration 132 ) { 133 window.requestAnimationFrame(holdInitialScrollPosition); 134 } 135 } 136 137 if (shouldResetInitialScroll) { 138 window.addEventListener('load', function() { 139 window.setTimeout(resetInitialScrollPosition, 0); 140 window.setTimeout(resetInitialScrollPosition, 500); 141 window.setTimeout(resetInitialScrollPosition, 1200); 142 }); 143 window.addEventListener('pageshow', function() { 144 window.setTimeout(resetInitialScrollPosition, 0); 145 window.setTimeout(resetInitialScrollPosition, 500); 146 }); 147 } 148 149 holdInitialScrollPosition(); 150 151 // load google web fonts 152 loadGoogleFontCss(); 153 154 function schedulePostRenderWork(callback, timeout) { 155 window.setTimeout(function() { 156 if (window.requestIdleCallback) { 157 window.requestIdleCallback(callback, { timeout: timeout || 1200 }); 158 } else { 159 window.setTimeout(callback, 0); 160 } 161 }, 0); 162 } 163 164 function scheduleSampleRequestInit() { 165 if (sampleRequestInitQueued) { 166 return; 167 } 168 169 sampleRequestInitQueued = true; 170 schedulePostRenderWork(function() { 171 sampleRequestInitQueued = false;
172 sampleRequest.initDynamic(); 173 }, 1000); 174 } 175 176 function revealApiDocsPage() { 177 var reveal = function() { 178 setApiDocsLoadingProgress(100); 179 settleCurrentHashPosition(0); 180 window.setTimeout(function() { 181 settleCurrentHashPosition(0); 182 }, 150); 183 window.setTimeout(function() { 184 settleCurrentHashPosition(0); 185 $('.api-docs-page').removeClass('api-docs-is-loading'); 186 }, 300); 187 }; 188 189 if (window.requestAnimationFrame) { 190 window.requestAnimationFrame(function() { 191 window.requestAnimationFrame(reveal); 192 }); 193 } else { 194 window.setTimeout(reveal, 0); 195 } 196 } 197 198 var api = apiData.api; 199 200 // 201 // Templates 202 // 203 var templateHeader = Handlebars.compile( $('#template-header').html() ); 204 var templateFooter = Handlebars.compile( $('#template-footer').html() ); 205 var templateArticle = Handlebars.compile( $('#template-article').html() ); 206 var templateCompareArticle = Handlebars.compile( $('#template-compare-article').html() ); 207 var templateGenerator = Handlebars.compile( $('#template-generator').html() ); 208 var templateProject = Handlebars.compile( $('#template-project').html() ); 209 var templateSections = Handlebars.compile( $('#template-sections').html() ); 210 var templateSidenav = Handlebars.compile( $('#template-sidenav').html() ); 211 212 // 213 // apiProject defaults 214 // 215 if ( ! apiProject.template) 216 apiProject.template = {}; 217 218 if (apiProject.template.withCompare == null) 219 apiProject.template.withCompare = true; 220 221 if (window.__apiDocsReleaseVersions) 222 apiProject.template.withCompare = false; 223 224 if (apiProject.template.withGenerator == null) 225 apiProject.template.withGenerator = true; 226 227 if (apiProject.template.forceLanguage) 228 locale.setLanguage(apiProject.template.forceLanguage); 229 230 // Setup jQuery Ajax 231 $.ajaxSetup(apiProject.template.jQueryAjaxSetup); 232 233 // 234 // Data transform 235 // 236 // grouped by group 237 var apiByGroup = _.groupBy(api, function(entry) { 238 return entry.group; 239 }); 240 241 // grouped by group and name 242 var apiByGroupAndName = {}; 243 $.each(apiByGroup, function(index, entries) { 244 apiByGroupAndName[index] = _.groupBy(entries, function(entry) { 245 return entry.name; 246 }); 247 }); 248 249 // 250 // sort api within a group by title ASC and custom order 251 // 252 var newList = []; 253 var umlauts = { 'ä': 'ae', 'ü': 'ue', 'ö': 'oe', 'Ã': 'ss' }; // TODO: remove in version 1.0 254 $.each (apiByGroupAndName, function(index, groupEntries) { 255 // get titles from the first entry of group[].name[] (name has versioning) 256 var titles = []; 257 $.each (groupEntries, function(titleName, entries) { 258 var title = entries[0].title; 259 if(title !== undefined) { 260 title.toLowerCase().replace(/[äöüÃ]/g, function($0) { return umlauts[$0]; }); 261 titles.push(title + '#~#' + titleName); // '#~#' keep reference to titleName after sorting 262 } 263 }); 264 // sort by name ASC 265 titles.sort(); 266 267 // custom order 268 if (apiProject.order) 269 titles = sortByOrder(titles, apiProject.order, '#~#'); 270 271 // add single elements to the new list
272 titles.forEach(function(name) { 273 var values = name.split('#~#'); 274 var key = values[1]; 275 groupEntries[key].forEach(function(entry) { 276 newList.push(entry); 277 }); 278 }); 279 }); 280 // api overwrite with ordered list 281 api = newList; 282 283 // 284 // Group- and Versionlists 285 // 286 var apiGroups = {}; 287 var apiGroupTitles = {}; 288 var apiVersions = {}; 289 apiVersions[apiProject.version] = 1; 290 291 $.each(api, function(index, entry) { 292 apiGroups[entry.group] = 1; 293 apiGroupTitles[entry.group] = entry.groupTitle || entry.group; 294 apiVersions[entry.version] = 1; 295 }); 296 297 // sort groups 298 apiGroups = Object.keys(apiGroups); 299 apiGroups.sort(); 300 301 // custom order 302 if (apiProject.order) 303 apiGroups = sortByOrder(apiGroups, apiProject.order); 304 305 // sort versions DESC 306 apiVersions = Object.keys(apiVersions); 307 apiVersions.sort(semver.compare); 308 apiVersions.reverse(); 309 310 // 311 // create Navigationlist 312 // 313 var nav = []; 314 apiGroups.forEach(function(group) { 315 // Mainmenu entry 316 nav.push({ 317 group: group, 318 isHeader: true, 319 title: apiGroupTitles[group] 320 }); 321 322 // Submenu 323 var oldName = ''; 324 api.forEach(function(entry) { 325 if (entry.group === group) { 326 if (oldName !== entry.name) { 327 nav.push({ 328 title: entry.title, 329 group: group, 330 name: entry.name, 331 type: entry.type, 332 version: entry.version 333 }); 334 } else { 335 nav.push({ 336 title: entry.title, 337 group: group, 338 hidden: true, 339 name: entry.name, 340 type: entry.type, 341 version: entry.version 342 }); 343 } 344 oldName = entry.name; 345 } 346 }); 347 }); 348 349 /** 350 * Add navigation items by analyzing the HTML content and searching for h1 and h2 tags 351 * @param nav Object the navigation array 352 * @param content string the compiled HTML content 353 * @param index where to insert items 354 * @return boolean true if any good-looking (i.e. with a group identifier) <h1> tag was found 355 */ 356 function add_nav(nav, content, index) { 357 var found_level1 = false; 358 if ( ! content) { 359 return found_level1; 360 } 361 var topics = content.match(/<h(1|2).*?>(.+?)<\/h(1|2)>/gi); 362 if ( topics ) { 363 topics.forEach(function(entry) { 364 var level = entry.substring(2,3); 365 var title = entry.replace(/<.+?>/g, ''); // Remove all HTML tags for the title 366 var entry_tags = entry.match(/id="api-([^\-]+)(?:-(.+))?"/); // Find the group and name in the id property 367 var group = (entry_tags ? entry_tags[1] : null); 368 var name = (entry_tags ? entry_tags[2] : null); 369 if (level==1 && title && group) { 370 nav.splice(index, 0, { 371 group: group, 372 isHeader: true, 373 title: title, 374 isFixed: true 375 }); 376 index++; 377 found_level1 = true; 378 } 379 if (level==2 && title && group && name) { 380 nav.splice(index, 0, { 381 group: group, 382 name: name, 383 isHeader: false, 384 title: title, 385 isFixed: false, 386 version: '1.0' 387 }); 388 index++; 389 } 390 }); 391 } 392 return found_level1; 393 } 394 395 // Mainmenu Header entry 396 if (apiProject.header) { 397 var found_level1 = add_nav(nav, apiProject.header.content, 0); // Add level 1 and 2 titles 398 if (!found_level1) { // If no Level 1 tags were found, make a title 399 nav.unshift({ 400 group: '_', 401 isHeader: true, 402 title: (apiProject.header.title == null) ? locale.__('General') : apiProject.header.title, 403 isFixed: true 404 }); 405 } 406 } 407 408 // Mainmenu Footer entry 409 if (apiProject.footer) { 410 var last_nav_index = nav.length; 411 var found_level1 = add_nav(nav, apiProject.footer.content, nav.length); // Add level 1 and 2 titles 412 if (!found_level1 && apiProject.footer.title != null) { // If no Level 1 tags were found, make a title 413 nav.splice(last_nav_index, 0, { 414 group: '_footer', 415 isHeader: true, 416 title: apiProject.footer.title, 417 isFixed: true 418 }); 419 } 420 } 421 422 // render pagetitle 423 var title = apiProject.title ? apiProject.title : 'apiDoc: ' + apiProject.name + ' - ' + apiProject.version; 424 if (!$('.api-docs-page').length) { 425 $(document).attr('title', title); 426 } 427 428 // remove loader 429 $('#loader').remove(); 430 431 // render sidenav 432 var fields = { 433 nav: nav 434 }; 435 $('#sidenav').append( templateSidenav(fields) ); 436 setApiDocsLoadingProgress(72); 437 438 // render Generator 439 $('#generator').append( templateGenerator(apiProject) ); 440 441 // render Project 442 _.extend(apiProject, { versions: apiVersions}); 443 $('#project').append( templateProject(apiProject) ); 444 445 // render apiDoc, header/footer documentation 446 if (apiProject.header) 447 $('#header').append( templateHeader(apiProject.header) ); 448 449 if (apiProject.footer) 450 $('#footer').append( templateFooter(apiProject.footer) ); 451 452 // 453 // Render Sections and Articles 454 // 455 var articleVersions = {}; 456 var content = ''; 457 apiGroups.forEach(function(groupEntry) { 458 var articles = []; 459 var oldName = ''; 460 var fields = {}; 461 var title = groupEntry; 462 var description = ''; 463 articleVersions[groupEntry] = {}; 464 465 // render all articles of a group 466 api.forEach(function(entry) { 467 if(groupEntry === entry.group) { 468 if (oldName !== entry.name) { 469 // determine versions 470 api.forEach(function(versionEntry) { 471 if (groupEntry === versionEntry.group && entry.name === versionEntry.name) { 472 if ( ! articleVersions[entry.group].hasOwnProperty(entry.name) ) { 473 articleVersions[entry.group][entry.name] = []; 474 } 475 articleVersions[entry.group][entry.name].push(versionEntry.version); 476 } 477 }); 478 fields = { 479 article: entry, 480 versions: articleVersions[entry.group][entry.name] 481 }; 482 } else { 483 fields = { 484 article: entry, 485 hidden: true, 486 versions: articleVersions[entry.group][entry.name] 487 }; 488 } 489 490 // add prefix URL for endpoint 491 if (apiProject.url) 492 fields.article.url = apiProject.url + fields.article.url; 493 494 addArticleSettings(fields, entry); 495 496 if (entry.groupTitle) 497 title = entry.groupTitle; 498 499 // TODO: make groupDescription compareable with older versions (not important for the moment) 500 if (entry.groupDescription) 501 description = entry.groupDescription; 502 503 articles.push({ 504 article: templateArticle(fields), 505 group: entry.group, 506 name: entry.name 507 }); 508 oldName = entry.name; 509 } 510 }); 511 512 // render Section with Articles 513 var fields = { 514 group: groupEntry, 515 title: title, 516 description: description, 517 articles: articles 518 }; 519 content += templateSections(fields); 520 }); 521 $('#sections').append( content ); 522 setApiDocsLoadingProgress(84); 523 resetInitialScrollPosition(); 524 525 // Account for the fixed site header plus a small cushion so linked headings stay visible. 526 function getTopOverlayBottom() { 527 var bottom = 0; 528 var selectors = [ 529 '#resilio-news-bar', 530 '[data-resilio-header-2026-v1].s-navbar-block', 531 '[data-resilio-main-header="1"]', 532 '.s-navbar-block', 533 'header', 534 '[role="banner"]' 535 ]; 536
537 selectors.forEach(function(selector) { 538 $(selector).each(function() { 539 var styles = window.getComputedStyle ? window.getComputedStyle(this) : null; 540 var position = styles ? styles.position : ''; 541 var rect = this.getBoundingClientRect ? this.getBoundingClientRect() : null; 542 var isPinnedToTop; 543 544 if (!rect || rect.height <= 0) { 545 return; 546 } 547 548 if (styles && (styles.display === 'none' || styles.visibility === 'hidden')) { 549 return; 550 } 551 552 isPinnedToTop = rect.top <= 4 && rect.bottom > 0 && rect.bottom < window.innerHeight * 0.6; 553 554 if (position === 'fixed' || position === 'sticky' || position === '-webkit-sticky' || isPinnedToTop) { 555 bottom = Math.max(bottom, rect.bottom); 556 } 557 }); 558 }); 559 560 return bottom; 561 } 562 563 function getAnchorOffset() { 564 var rootStyles = window.getComputedStyle ? window.getComputedStyle(document.documentElement) : null; 565 var headerHeight = rootStyles ? parseFloat(rootStyles.getPropertyValue('--resilio-header-h')) : 0; 566 var newsbarOffset = rootStyles ? parseFloat(rootStyles.getPropertyValue('--resilio-newsbar-visible-offset')) : 0; 567 var cssOffset = (headerHeight || 72) + (newsbarOffset || 0); 568 return Math.ceil(Math.max(cssOffset, getTopOverlayBottom())) + 25; 569 } 570 571 function getAnchorTarget(id) { 572 var targetId = id.charAt(0) === '#' ? id.slice(1) : id; 573 var element = document.getElementById(targetId); 574 575 return element ? $(element) : $(); 576 } 577 578 function getAnchorTargetTop(id) { 579 var $target = getAnchorTarget(id); 580 581 if ($target.length === 0) { 582 return 0; 583 } 584 585 var $heading = $target.is('h1,h2,h3,h4') ? $target : $target.find('> h1, > article:visible h1:first, article:visible h1:first, h1:first').first(); 586 587 return $heading.length > 0 ? $heading.offset().top : $target.offset().top; 588 } 589 590 function getAnchorScrollTop(id) { 591 return Math.max(0, parseInt(getAnchorTargetTop(id), 10) - getAnchorOffset()); 592 } 593 594 function getPreCopyText(pre) { 595 return $(pre).text(); 596 } 597 598 function copyTextWithTextarea(text) { 599 var textarea = document.createElement('textarea'); 600 textarea.value = text; 601 textarea.setAttribute('readonly', ''); 602 textarea.style.position = 'fixed'; 603 textarea.style.top = '-9999px'; 604 textarea.style.left = '-9999px'; 605 document.body.appendChild(textarea); 606 textarea.focus(); 607 textarea.select(); 608 textarea.setSelectionRange(0, textarea.value.length); 609 610 try { 611 document.execCommand('copy'); 612 } finally { 613 document.body.removeChild(textarea); 614 } 615 616 return $.Deferred().resolve().promise(); 617 } 618 619 function copyTextToClipboard(text) { 620 if (navigator.clipboard && navigator.clipboard.writeText) { 621 var clipboardResult = navigator.clipboard.writeText(text); 622 623 if (clipboardResult && clipboardResult.then) { 624 return clipboardResult.catch(function() { 625 return copyTextWithTextarea(text); 626 }); 627 } 628 629 return $.Deferred().resolve().promise(); 630 } 631 632 return copyTextWithTextarea(text); 633 } 634 635 function enhancePreCopyButtons($root) { 636 $root.find('pre').each(function() { 637 var $pre = $(this); 638 var $wrapper; 639 640 $pre.find('> .api-copy-button').remove(); 641 642 if ($pre.parent('.api-pre-wrapper').length > 0) { 643 return; 644 } 645 646 $pre.wrap('<div class="api-pre-wrapper"></div>'); 647 $wrapper = $pre.parent(); 648 $wrapper.append('<button type="button" class="api-copy-button" aria-label="Copy code" title="Copy code"><img src="/images/copy-01.svg" alt="" aria-hidden="true"></button><span class="api-copy-message" aria-live="polite"></span>'); 649 }); 650 } 651 652 var anchorScrollAnimation; 653 654 function easeInOutGentle(progress) { 655 return progress < 0.5 ? 656 16 * Math.pow(progress, 5) : 657 1 - Math.pow(-2 * progress + 2, 6) / 2; 658 } 659 660 function getScrollDuration(distance, duration) { 661 if (typeof duration === 'number') { 662 return duration; 663 } 664 665 return Math.min(980, Math.max(400, distance * 0.38)); 666 } 667 668 function scrollToTop(endTop, duration, getFinalTop, onComplete) { 669 var startTop = window.pageYOffset || document.documentElement.scrollTop || 0; 670 var distance = Math.abs(endTop - startTop); 671 var scrollDuration = getScrollDuration(distance, duration); 672 var prefersReducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; 673 var getResolvedFinalTop = typeof getFinalTop === 'function' ? getFinalTop : function() { 674 return endTop; 675 }; 676 677 if (anchorScrollAnimation) { 678 window.cancelAnimationFrame(anchorScrollAnimation); 679 } 680 681 if (scrollDuration === 0 || prefersReducedMotion || distance < 2) { 682 window.scrollTo(0, endTop); 683 window.setTimeout(function() { 684 window.scrollTo(0, getResolvedFinalTop()); 685 if (typeof onComplete === 'function') { 686 onComplete(); 687 } 688 }, 0); 689 690 return; 691 } 692 693 var startTime = window.performance && window.performance.now ? window.performance.now() : Date.now(); 694 695 function step(timestamp) {
696 var elapsed = timestamp - startTime; 697 var progress = Math.min(elapsed / scrollDuration, 1); 698 var easedProgress = easeInOutGentle(progress); 699 700 window.scrollTo(0, startTop + (endTop - startTop) * easedProgress); 701 702 if (progress < 1) { 703 anchorScrollAnimation = window.requestAnimationFrame(step); 704 } else { 705 anchorScrollAnimation = null; 706 window.setTimeout(function() { 707 window.scrollTo(0, getResolvedFinalTop()); 708 if (typeof onComplete === 'function') { 709 onComplete(); 710 } 711 }, 120); 712 } 713 } 714 715 anchorScrollAnimation = window.requestAnimationFrame(step); 716 } 717 718 function scrollToAnchor(id, duration, onComplete) { 719 scrollToTop(getAnchorScrollTop(id), duration, function() { 720 return getAnchorScrollTop(id); 721 }, onComplete); 722 } 723 724 window.__apiDocsScrollToAnchor = scrollToAnchor; 725 726 function revealInitialAnchorLoad() { 727 document.documentElement.classList.remove('api-docs-anchor-loading'); 728 } 729 730 function settleInitialHashPosition(onComplete) { 731 settleCurrentHashPosition(0, onComplete); 732 } 733 734 function settleCurrentHashPosition(duration, onComplete) { 735 var id = window.location.hash || window.__apiDocsInitialHash; 736 737 if (!id) { 738 if (typeof onComplete === 'function') { 739 onComplete(); 740 } 741 return; 742 } 743 744 if (id === '#top') { 745 scrollToTop(0, duration, function() { 746 return 0; 747 }, function() { 748 if (typeof onComplete === 'function') { 749 onComplete(); 750 } 751 }); 752 return; 753 } 754 755 if (getAnchorTarget(id).length > 0) { 756 scrollToAnchor(id, duration, function() { 757 if (!window.location.hash && window.history && window.history.replaceState) { 758 window.history.replaceState(null, '', window.location.pathname + window.location.search + id); 759 } 760 if (typeof onComplete === 'function') { 761 onComplete(); 762 } 763 }); 764 return; 765 } 766 767 if (typeof onComplete === 'function') { 768 onComplete(); 769 } 770 } 771 772 window.__apiDocsSettleCurrentHash = settleCurrentHashPosition; 773 774 function getElementScrollTop($element, extraOffset) { 775 if ($element.length === 0) { 776 return 0; 777 } 778 779 return Math.max(0, parseInt($element.offset().top, 10) - getAnchorOffset() - (extraOffset || 0)); 780 } 781 782 function scrollToElement($element, duration, extraOffset) { 783 if ($element.length === 0) { 784 return; 785 } 786 787 scrollToTop(getElementScrollTop($element, extraOffset), duration, function() { 788 return getElementScrollTop($element, extraOffset); 789 }); 790 } 791 792 function scrollTabIntoView($tabs, tab) { 793 if ($tabs.length === 0 || !tab) { 794 return; 795 } 796 797 var tabs = $tabs[0]; 798 var tabRect = tab.getBoundingClientRect(); 799 var tabsRect = tabs.getBoundingClientRect(); 800 var buffer = 20; 801 802 if (tabRect.left < tabsRect.left + buffer) { 803 tabs.scrollLeft -= tabsRect.left + buffer - tabRect.left; 804 } else if (tabRect.right > tabsRect.right - buffer) { 805 tabs.scrollLeft += tabRect.right - (tabsRect.right - buffer); 806 } 807 808 updateExampleTabsOverflow($tabs.closest('.api-tabs-overflow')); 809 } 810 811 function updateExampleTabsOverflow($wrap) { 812 var tabs = $wrap.find('> .nav-tabs-examples')[0]; 813 var contentWidth = 0; 814 var hasOverflow; 815 var maxScroll; 816 var scrollLeft; 817 818 if (!tabs) { 819 return; 820 } 821 822 $wrap.find('> .nav-tabs-examples > li').each(function() { 823 contentWidth += $(this).outerWidth(true); 824 }); 825 hasOverflow = contentWidth + 20 > $wrap.width() + 2; 826 $wrap.toggleClass('has-overflow', hasOverflow); 827 828 maxScroll = Math.max(0, tabs.scrollWidth - tabs.clientWidth); 829 scrollLeft = Math.max(0, Math.min(tabs.scrollLeft, maxScroll)); 830 831 $wrap 832 .toggleClass('can-scroll-left', hasOverflow && scrollLeft > 2) 833 .toggleClass('can-scroll-right', hasOverflow && scrollLeft < maxScroll - 2); 834 } 835 836 function scrollExampleTabs($wrap, direction) { 837 var tabs = $wrap.find('> .nav-tabs-examples')[0]; 838 var distance; 839 840 if (!tabs) { 841 return; 842 } 843 844 distance = Math.max(160, tabs.clientWidth * 0.75) * direction; 845 846 if (tabs.scrollBy) { 847 tabs.scrollBy({ left: distance, behavior: 'smooth' }); 848 } else { 849 tabs.scrollLeft += distance; 850 } 851 852 window.setTimeout(function() { 853 updateExampleTabsOverflow($wrap); 854 }, 260); 855 } 856 857 function enhanceExampleTabs($root) { 858 $root.find('.nav-tabs-examples').each(function() { 859 var $tabs = $(this); 860 var $wrap = $tabs.closest('.api-tabs-overflow'); 861 862 if ($wrap.length === 0) { 863 $tabs.wrap('<div class="api-tabs-overflow"></div>'); 864 $wrap = $tabs.parent(); 865 $wrap.prepend('<button type="button" class="api-tabs-arrow api-tabs-arrow--left" aria-label="Scroll tabs left"><img src="/images/square-arrow-left-02-sharp.svg" alt="" aria-hidden="true"></button>'); 866 $wrap.append('<button type="button" class="api-tabs-arrow api-tabs-arrow--right" aria-label="Scroll tabs right"><img src="/images/square-arrow-right-02-sharp.svg" alt="" aria-hidden="true"></button>'); 867 $tabs.on('scroll.apiTabsOverflow', function() { 868 updateExampleTabsOverflow($wrap); 869 }); 870 $wrap.on('click.apiTabsOverflow', '.api-tabs-arrow', function(e) { 871 e.preventDefault(); 872 scrollExampleTabs($wrap, $(this).hasClass('api-tabs-arrow--left') ? -1 : 1); 873 }); 874 } 875 876 updateExampleTabsOverflow($wrap); 877 }); 878 879 if (!exampleTabsResizeBound) { 880 exampleTabsResizeBound = true; 881 $(window).on('resize.apiTabsOverflow', debounceApiDocs(function() { 882 $('.api-tabs-overflow').each(function() { 883 updateExampleTabsOverflow($(this)); 884 }); 885 }, 120)); 886 } 887 } 888 889 // Bootstrap Scrollspy 890 $(this).scrollspy({ target: '#scrollingNav', offset: getAnchorOffset() }); 891 892 function handleApiAnchorClick(e) { 893 e.preventDefault(); 894 895 var id = this.hash || $(this).attr('href'); 896 897 if (id.indexOf('#api-') !== 0) { 898 return true; 899 } 900 901 if (getAnchorTarget(id).length > 0) { 902 scrollToAnchor(id); 903 if (window.history && window.history.pushState) { 904 window.history.pushState(null, '', id); 905 } 906 } 907 908 return false;
909 } 910 911 // Content-Scroll on API anchor click. 912 $('#scrollingNav').on('click', '.sidenav a[href^="#"]', handleApiAnchorClick); 913 $('#connectApiContainer').on('click', 'a[href^="#api-"]', handleApiAnchorClick); 914 915 // Quickjump on page load, including hashes preserved while async docs render. 916 if(initialAnchorHash) { 917 settleInitialHashPosition(revealInitialAnchorLoad); 918 } else { 919 revealInitialAnchorLoad(); 920 } 921 922 /** 923 * Check if Parameter (sub) List has a type Field. 924 * Example: @apiSuccess varname1 No type. 925 * @apiSuccess {String} varname2 With type. 926 * 927 * @param {Object} fields 928 */ 929 function _hasTypeInFields(fields) { 930 var result = false; 931 $.each(fields, function(name) { 932 result = result || _.some(fields[name], function(item) { return item.type; }); 933 }); 934 return result; 935 } 936 937 /** 938 * On Template changes, recall plugins. 939 */ 940 function activateFirstExampleTabs($root) { 941 $root.find('.nav-tabs-examples').each(function() { 942 var $tabs = $(this); 943 var hasActiveTab = $tabs.find('li.active, a.active').length > 0; 944 945 if (!hasActiveTab) 946 $tabs.find('a:first').tab('show'); 947 }); 948 } 949 950 function initDynamic() { 951 setApiDocsLoadingProgress(88); 952 // Bootstrap popover 953 $('button[data-toggle="popover"]').popover().click(function(e) { 954 e.preventDefault(); 955 }); 956 957 var version = $('#version strong').html(); 958 $('#sidenav li').removeClass('is-new'); 959 if (apiProject.template.withCompare) { 960 $('#sidenav li[data-version=\'' + version + '\']').each(function(){ 961 var group = $(this).data('group'); 962 var name = $(this).data('name'); 963 var length = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').length; 964 var index = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').index($(this)); 965 if (length === 1 || index === (length - 1)) 966 $(this).addClass('is-new'); 967 }); 968 } 969 970 // tabs 971 activateFirstExampleTabs($('#connectMCApi')); 972 enhanceExampleTabs($('#connectMCApi')); 973 974 // sample request switch 975 $('.sample-request-switch').click(function (e) { 976 var name = '.' + $(this).attr('name') + '-fields'; 977 $(name).addClass('hide'); 978 $(this).parent().next(name).removeClass('hide'); 979 }); 980 981 // call scrollspy refresh method 982 $(window).scrollspy('refresh'); 983 984 // init non-critical sample request handlers after the initial docs render path. 985 scheduleSampleRequestInit(); 986 } 987 initDynamic(); 988 resetInitialScrollPosition(); 989 990 function runPostRenderEnhancements() { 991 // Run layout-affecting code-block enhancements behind the loader to avoid visible shifts. 992 prettyPrint(); 993 enhancePreCopyButtons($('#connectMCApi')); 994 $(window).scrollspy('refresh'); 995 setApiDocsLoadingProgress(96); 996 } 997 998 runPostRenderEnhancements(); 999 settleInitialHashPosition(function() { 1000 revealInitialAnchorLoad(); 1001 revealApiDocsPage(); 1002 }); 1003 1004 window.setTimeout(resetInitialScrollPosition, 0); 1005 window.setTimeout(resetInitialScrollPosition, 250); 1006 window.setTimeout(resetInitialScrollPosition, 750); 1007 window.setTimeout(resetInitialScrollPosition, 1200); 1008 window.setTimeout(resetInitialScrollPosition, 2500); 1009 1010 $('#connectMCApi').on('click', '.nav-tabs-examples a[href^="#"]', function(e) { 1011 var $tab = $(this); 1012 var $tabs = $tab.closest('.nav-tabs-examples'); 1013 var wasActive = $tab.parent('li').hasClass('active'); 1014 var scrollToTabs = function() { 1015 scrollTabIntoView($tabs, $tab[0]); 1016 scrollToElement($tabs.length > 0 ? $tabs : $tab); 1017 }; 1018 1019 e.preventDefault(); 1020 e.stopImmediatePropagation(); 1021 1022 if (!wasActive) 1023 $tab.one('shown.bs.tab', scrollToTabs); 1024 1025 $tab.tab('show'); 1026 1027 if (wasActive) 1028 window.setTimeout(scrollToTabs, 0); 1029 }); 1030 1031 $('#connectMCApi').on('click', '.api-copy-button', function(e) { 1032 e.preventDefault(); 1033 e.stopPropagation(); 1034 1035 var button = this; 1036 var $button = $(button); 1037 var $wrapper = $button.closest('.api-pre-wrapper'); 1038 var $message = $wrapper.find('> .api-copy-message'); 1039 var text = getPreCopyText($wrapper.find('> pre')[0]); 1040 var resetCopyButton = function() { 1041 $button.removeClass('is-copied'); 1042 $message.removeClass('is-visible').text(''); 1043 button.setAttribute('aria-label', 'Copy code'); 1044 button.setAttribute('title', 'Copy code'); 1045 }; 1046 var activeTimeout = $button.data('copyTimeout'); 1047 1048 if (activeTimeout) { 1049 window.clearTimeout(activeTimeout); 1050 } 1051 1052 $button.addClass('is-copied'); 1053 $message.text('Copied!').addClass('is-visible'); 1054 button.setAttribute('aria-label', 'Copied'); 1055 button.setAttribute('title', 'Copied'); 1056 1057 copyTextToClipboard(text); 1058 1059 $button.data('copyTimeout', window.setTimeout(resetCopyButton, 3000)); 1060 }); 1061 1062 // 1063 // HTML-Template specific jQuery-Functions 1064 // 1065 // Change Main Version
1066 $('#versions li.version a').on('click', function(e) { 1067 e.preventDefault(); 1068 1069 var selectedVersion = $(this).html(); 1070 $('#version strong').html(selectedVersion); 1071 1072 // hide all 1073 $('article').addClass('hide'); 1074 $('#sidenav li:not(.nav-fixed)').addClass('hide'); 1075 1076 // show 1st equal or lower Version of each entry 1077 $('article[data-version]').each(function(index) { 1078 var group = $(this).data('group'); 1079 var name = $(this).data('name'); 1080 var version = $(this).data('version'); 1081 1082 if (semver.lte(version, selectedVersion)) { 1083 if ($('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible').length === 0) { 1084 // enable Article 1085 $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide'); 1086 // enable Navigation 1087 $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide'); 1088 $('#sidenav li.nav-header[data-group=\'' + group + '\']').removeClass('hide'); 1089 } 1090 } 1091 }); 1092 1093 // show 1st equal or lower Version of each entry 1094 $('article[data-version]').each(function(index) { 1095 var group = $(this).data('group'); 1096 $('section#api-' + group).removeClass('hide'); 1097 if ($('section#api-' + group + ' article:visible').length === 0) { 1098 $('section#api-' + group).addClass('hide'); 1099 } else { 1100 $('section#api-' + group).removeClass('hide'); 1101 } 1102 }); 1103 1104 initDynamic(); 1105 return; 1106 }); 1107 1108 // compare all article with their predecessor 1109 $('#compareAllWithPredecessor').on('click', changeAllVersionCompareTo); 1110 1111 // change version of an article 1112 $('article .versions li.version a').on('click', changeVersionCompareTo); 1113 1114 // compare url-parameter 1115 $.urlParam = function(name) { 1116 var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href); 1117 return (results && results[1]) ? results[1] : null; 1118 }; 1119 1120 if ($.urlParam('compare')) { 1121 // URL Paramter ?compare=1 is set 1122 $('#compareAllWithPredecessor').trigger('click'); 1123 1124 if (window.location.hash) { 1125 var id = window.location.hash; 1126 scrollToAnchor(id, 0); 1127 } 1128 } 1129 1130 /** 1131 * Initialize search 1132 */ 1133 var options = { 1134 valueNames: [ 'nav-list-item' ] 1135 }; 1136 var endpointsList = new List('scrollingNav', options); 1137 var $sidebarSearch = $('#scrollingNav .sidenav-search input.search'); 1138 var $searchReset = $('#scrollingNav span.search-reset'); 1139 var $sidebarList = $('#scrollingNav .sidenav'); 1140 var keyboardResultIndex = -1; 1141 1142 $sidebarList.attr('id', 'api-docs-sidenav-results'); 1143 $sidebarSearch.attr({ 1144 'role': 'combobox', 1145 'aria-autocomplete': 'list', 1146 'aria-controls': 'api-docs-sidenav-results', 1147 'aria-expanded': 'true' 1148 }); 1149 1150 $searchReset 1151 .empty() 1152 .append('<img src="/images/cancel-circle.svg" alt="" aria-hidden="true">') 1153 .attr({ 1154 'aria-label': 'Clear filter', 1155 'role': 'button', 1156 'tabindex': '0', 1157 'title': 'Clear filter' 1158 }); 1159 1160 var $sidebarEmptyState = $('<li class="api-docs-empty-state" aria-live="polite"><div class="api-docs-empty-state__title">No items found for the current filters.</div><div class="api-docs-empty-state__subhead">Consider changing your filter options to see more results.</div></li>'); 1161 1162 function getVisibleSidebarResults() { 1163 return $sidebarList.children('li:visible').not('.api-docs-empty-state').children('a:visible'); 1164 } 1165 1166 function clearKeyboardResult() { 1167 keyboardResultIndex = -1; 1168 $sidebarList.children('li').removeClass('api-docs-keyboard-active'); 1169 $sidebarSearch.removeAttr('aria-activedescendant'); 1170 } 1171 1172 function focusSidebarSearchWithoutScrolling() { 1173 var input = $sidebarSearch.get(0); 1174 1175 if (!input) { 1176 return; 1177 } 1178
1179 try { 1180 input.focus({ preventScroll: true }); 1181 } catch (error) { 1182 input.focus(); 1183 } 1184 } 1185 1186 function keepKeyboardResultVisible(link) { 1187 var list = $sidebarList.get(0); 1188 var linkRect; 1189 var listRect; 1190 1191 if (!list || !link) { 1192 return; 1193 } 1194 1195 linkRect = link.getBoundingClientRect(); 1196 listRect = list.getBoundingClientRect(); 1197 1198 if (linkRect.top < listRect.top) { 1199 list.scrollTop -= listRect.top - linkRect.top; 1200 } else if (linkRect.bottom > listRect.bottom) { 1201 list.scrollTop += linkRect.bottom - listRect.bottom; 1202 } 1203 } 1204 1205 function selectKeyboardResult(index) { 1206 var $results = getVisibleSidebarResults(); 1207 var resultCount = $results.length; 1208 var $result; 1209 var resultId; 1210 1211 if (!resultCount) { 1212 clearKeyboardResult(); 1213 return; 1214 } 1215 1216 keyboardResultIndex = (index + resultCount) % resultCount; 1217 $sidebarList.children('li').removeClass('api-docs-keyboard-active'); 1218 $result = $results.eq(keyboardResultIndex); 1219 $result.parent().addClass('api-docs-keyboard-active'); 1220 resultId = $result.attr('id') || 'api-docs-filter-result-' + String($result.attr('href') || keyboardResultIndex).replace(/[^a-z0-9_-]+/gi, '-'); 1221 $result.attr('id', resultId); 1222 $sidebarSearch.attr('aria-activedescendant', resultId); 1223 keepKeyboardResultVisible($result.get(0)); 1224 } 1225 1226 document.getElementById('scrollingNav').addEventListener('keydown', function(e) { 1227 var link = e.target.closest('.sidenav a[href^="#"]'); 1228 var $results; 1229 var linkIndex; 1230 var selectedLink; 1231 1232 if (!link) { 1233 return; 1234 } 1235 1236 if (e.key === 'Enter' || e.keyCode === 13) { 1237 if (link.parentElement.classList.contains('api-docs-keyboard-active')) { 1238 e.preventDefault(); 1239 link.click(); 1240 $sidebarList.children('li').removeClass('api-docs-keyboard-active'); 1241 $sidebarSearch.removeAttr('aria-activedescendant'); 1242 } 1243 return; 1244 } 1245 1246 if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp' && e.keyCode !== 40 && e.keyCode !== 38) { 1247 return; 1248 } 1249 1250 $results = getVisibleSidebarResults(); 1251 linkIndex = $results.index(link); 1252 1253 if (linkIndex < 0) { 1254 return; 1255 } 1256 1257 e.preventDefault(); 1258 keyboardResultIndex = linkIndex; 1259 selectKeyboardResult(linkIndex + ((e.key === 'ArrowUp' || e.keyCode === 38) ? -1 : 1)); 1260 selectedLink = getVisibleSidebarResults().eq(keyboardResultIndex).get(0); 1261 1262 if (selectedLink) { 1263 try { 1264 selectedLink.focus({ preventScroll: true }); 1265 } catch (error) { 1266 selectedLink.focus(); 1267 } 1268 } 1269 }, true); 1270 1271 function updateSidebarEmptyState() { 1272 var hasQuery = $.trim($sidebarSearch.val()).length > 0; 1273 var hasMatches = endpointsList.matchingItems.length > 0; 1274 var shouldShowEmptyState = hasQuery && !hasMatches; 1275 1276 if (!$sidebarEmptyState.parent().length) { 1277 $sidebarList.append($sidebarEmptyState); 1278 } 1279 1280 $sidebarEmptyState 1281 .toggleClass('is-visible', shouldShowEmptyState) 1282 .toggle(shouldShowEmptyState); 1283 $sidebarSearch.attr('aria-expanded', hasMatches ? 'true' : 'false'); 1284 } 1285 1286 if (endpointsList.on) { 1287 endpointsList.on('updated', function() { 1288 updateSidebarEmptyState(); 1289 }); 1290 } 1291 1292 /** 1293 * Detect ESC key to reset search 1294 */ 1295 $(document).keyup(function(e) { 1296 if (e.keyCode === 27) $searchReset.click(); 1297 }); 1298 1299 $sidebarSearch.on('input', clearKeyboardResult); 1300 1301 $sidebarSearch.on('input keyup', function() { 1302 window.setTimeout(updateSidebarEmptyState, 0); 1303 }); 1304 1305 $sidebarSearch.on('keydown', function(e) { 1306 var $results; 1307 1308 if (e.key === 'ArrowDown' || e.keyCode === 40) { 1309 e.preventDefault(); 1310 selectKeyboardResult(keyboardResultIndex + 1); 1311 return; 1312 } 1313 1314 if (e.key === 'ArrowUp' || e.keyCode === 38) { 1315 e.preventDefault(); 1316 $results = getVisibleSidebarResults(); 1317 selectKeyboardResult(keyboardResultIndex < 0 ? $results.length - 1 : keyboardResultIndex - 1); 1318 return; 1319 } 1320 1321 if (e.key === 'Enter' || e.keyCode === 13) { 1322 $results = getVisibleSidebarResults(); 1323 1324 if (!$results.length) { 1325 return; 1326 } 1327 1328 e.preventDefault(); 1329 if (keyboardResultIndex < 0) { 1330 selectKeyboardResult(0); 1331 $results = getVisibleSidebarResults(); 1332 } 1333 $results.eq(keyboardResultIndex).trigger('click'); 1334 $sidebarList.children('li').removeClass('api-docs-keyboard-active'); 1335 $sidebarSearch.removeAttr('aria-activedescendant'); 1336 focusSidebarSearchWithoutScrolling(); 1337 } 1338 }); 1339 1340 /** 1341 * Search reset 1342 */ 1343 $searchReset.on('click', function() { 1344 $sidebarSearch 1345 .val("") 1346 .focus() 1347 ; 1348 endpointsList.search(); 1349 updateSidebarEmptyState(); 1350 clearKeyboardResult(); 1351 }); 1352 1353 $searchReset.on('keydown', function(e) { 1354 if (e.keyCode === 13 || e.keyCode === 32) { 1355 e.preventDefault(); 1356 $searchReset.click(); 1357 } 1358 }); 1359 1360 /** 1361 * Change version of an article to compare it to an other version. 1362 */ 1363 function changeVersionCompareTo(e) { 1364 e.preventDefault(); 1365 1366 var $root = $(this).parents('article'); 1367 var selectedVersion = $(this).html(); 1368 var $button = $root.find('.version'); 1369 var currentVersion = $button.find('strong').html(); 1370 $button.find('strong').html(selectedVersion); 1371 1372 var group = $root.data('group'); 1373 var name = $root.data('name'); 1374 var version = $root.data('version'); 1375 1376 var compareVersion = $root.data('compare-version'); 1377 1378 if (compareVersion === selectedVersion) 1379 return; 1380 1381 if ( ! compareVersion && version == selectedVersion) 1382 return; 1383 1384 if (compareVersion && articleVersions[group][name][0] === selectedVersion || version === selectedVersion) { 1385 // the version of the entry is set to the highest version (reset) 1386 resetArticle(group, name, version); 1387 } else { 1388 var $compareToArticle = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + selectedVersion + '\']'); 1389 1390 var sourceEntry = {}; 1391 var compareEntry = {}; 1392 $.each(apiByGroupAndName[group][name], function(index, entry) { 1393 if (entry.version === version) 1394 sourceEntry = entry; 1395 if (entry.version === selectedVersion) 1396 compareEntry = entry; 1397 }); 1398 1399 var fields = { 1400 article: sourceEntry, 1401 compare: compareEntry, 1402 versions: articleVersions[group][name] 1403 }; 1404 1405 // add unique id 1406 // TODO: replace all group-name-version in template with id.
1407 fields.article.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version; 1408 fields.article.id = fields.article.id.replace(/\./g, '_'); 1409 1410 fields.compare.id = fields.compare.group + '-' + fields.compare.name + '-' + fields.compare.version; 1411 fields.compare.id = fields.compare.id.replace(/\./g, '_'); 1412 1413 var entry = sourceEntry; 1414 if (entry.parameter && entry.parameter.fields) 1415 fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); 1416 1417 if (entry.error && entry.error.fields) 1418 fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); 1419 1420 if (entry.success && entry.success.fields) 1421 fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); 1422 1423 if (entry.info && entry.info.fields) 1424 fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); 1425 1426 var entry = compareEntry; 1427 if (fields._hasTypeInParameterFields !== true && entry.parameter && entry.parameter.fields) 1428 fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); 1429 1430 if (fields._hasTypeInErrorFields !== true && entry.error && entry.error.fields) 1431 fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); 1432 1433 if (fields._hasTypeInSuccessFields !== true && entry.success && entry.success.fields) 1434 fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); 1435 1436 if (fields._hasTypeInInfoFields !== true && entry.info && entry.info.fields) 1437 fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); 1438 1439 var content = templateCompareArticle(fields); 1440 $root.after(content); 1441 var $content = $root.next(); 1442 1443 // Event on.click re-assign 1444 $content.find('.versions li.version a').on('click', changeVersionCompareTo); 1445 1446 // select navigation 1447 $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + currentVersion + '\']').addClass('has-modifications'); 1448 1449 $root.remove(); 1450 // TODO: on change main version or select the highest version re-render 1451 } 1452 1453 initDynamic(); 1454 } 1455 1456 /** 1457 * Compare all currently selected Versions with their predecessor. 1458 */ 1459 function changeAllVersionCompareTo(e) { 1460 e.preventDefault(); 1461 $('article:visible .versions').each(function(){ 1462 var $root = $(this).parents('article'); 1463 var currentVersion = $root.data('version'); 1464 var $foundElement = null; 1465 $(this).find('li.version a').each(function() { 1466 var selectVersion = $(this).html(); 1467 if (selectVersion < currentVersion && ! $foundElement) 1468 $foundElement = $(this); 1469 }); 1470 1471 if($foundElement) 1472 $foundElement.trigger('click'); 1473 }); 1474 initDynamic(); 1475 } 1476 1477 /** 1478 * Sort the fields. 1479 */ 1480 function sortFields(fields_object) { 1481 $.each(fields_object, function (key, fields) { 1482 1483 var reversed = fields.slice().reverse() 1484 1485 var max_dot_count = Math.max.apply(null, reversed.map(function (item) { 1486 return item.field.split(".").length - 1; 1487 })) 1488 1489 for (var dot_count = 1; dot_count <= max_dot_count; dot_count++) { 1490 reversed.forEach(function (item, index) { 1491 var parts = item.field.split("."); 1492 if (parts.length - 1 == dot_count) { 1493 var fields_names = fields.map(function (item) { return item.field; }); 1494 if (parts.slice(1).length >= 1) { 1495 var prefix = parts.slice(0, parts.length - 1).join("."); 1496 var prefix_index = fields_names.indexOf(prefix); 1497 if (prefix_index > -1) { 1498 fields.splice(fields_names.indexOf(item.field), 1); 1499 fields.splice(prefix_index + 1, 0, item); 1500 } 1501 } 1502 } 1503 }); 1504 } 1505 }); 1506 } 1507 1508 /** 1509 * Add article settings. 1510 */ 1511 function addArticleSettings(fields, entry) { 1512 // add unique id 1513 // TODO: replace all group-name-version in template with id. 1514 fields.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version; 1515 fields.id = fields.id.replace(/\./g, '_'); 1516 1517 if (entry.header && entry.header.fields) { 1518 sortFields(entry.header.fields); 1519 fields._hasTypeInHeaderFields = _hasTypeInFields(entry.header.fields); 1520 } 1521 1522 if (entry.parameter && entry.parameter.fields) { 1523 sortFields(entry.parameter.fields); 1524 fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); 1525 } 1526 1527 if (entry.error && entry.error.fields) { 1528 sortFields(entry.error.fields); 1529 fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); 1530 } 1531 1532 if (entry.success && entry.success.fields) { 1533 sortFields(entry.success.fields); 1534 fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); 1535 } 1536 1537 if (entry.info && entry.info.fields) { 1538 sortFields(entry.info.fields); 1539 fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); 1540 } 1541 1542 // add template settings 1543 fields.template = apiProject.template; 1544 } 1545 1546 /**
1547 * Render Article. 1548 */ 1549 function renderArticle(group, name, version) { 1550 var entry = {}; 1551 $.each(apiByGroupAndName[group][name], function(index, currentEntry) { 1552 if (currentEntry.version === version) 1553 entry = currentEntry; 1554 }); 1555 var fields = { 1556 article: entry, 1557 versions: articleVersions[group][name] 1558 }; 1559 1560 addArticleSettings(fields, entry); 1561 1562 return templateArticle(fields); 1563 } 1564 1565 /** 1566 * Render original Article and remove the current visible Article. 1567 */ 1568 function resetArticle(group, name, version) { 1569 var $root = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible'); 1570 var content = renderArticle(group, name, version); 1571 1572 $root.after(content); 1573 var $content = $root.next(); 1574 1575 // Event on.click muss neu zugewiesen werden (sollte eigentlich mit on automatisch funktionieren... sollte) 1576 $content.find('.versions li.version a').on('click', changeVersionCompareTo); 1577 enhancePreCopyButtons($content); 1578 activateFirstExampleTabs($content); 1579 scheduleSampleRequestInit(); 1580 1581 $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('has-modifications'); 1582 1583 $root.remove(); 1584 return; 1585 } 1586 1587 /** 1588 * Load google fonts. 1589 */ 1590 function loadGoogleFontCss() { 1591 WebFont.load({ 1592 active: function() { 1593 // Update scrollspy 1594 $(window).scrollspy('refresh') 1595 }, 1596 google: { 1597 families: ['Source Code Pro', 'Source Sans Pro:n4,n6,n7'] 1598 } 1599 }); 1600 } 1601 1602 /** 1603 * Return ordered entries by custom order and append not defined entries to the end. 1604 * @param {String[]} elements 1605 * @param {String[]} order 1606 * @param {String} splitBy 1607 * @return {String[]} Custom ordered list. 1608 */ 1609 function sortByOrder(elements, order, splitBy) { 1610 var results = []; 1611 order.forEach (function(name) { 1612 if (splitBy) 1613 elements.forEach (function(element) { 1614 var parts = element.split(splitBy); 1615 var key = parts[1]; // reference keep for sorting 1616 if (key == name) 1617 results.push(element); 1618 }); 1619 else 1620 elements.forEach (function(key) { 1621 if (key == name) 1622 results.push(name); 1623 }); 1624 }); 1625 // Append all other entries that ar not defined in order 1626 elements.forEach(function(element) { 1627 if (results.indexOf(element) === -1) 1628 results.push(element); 1629 }); 1630 return results; 1631 } 1632 1633}, function(error) { 1634 // Let the host page recover when a selected release does not publish API-doc assets. 1635 if (typeof window.__apiDocsHandleLoadError === 'function') { 1636 window.__apiDocsHandleLoadError(error); 1637 return; 1638 } 1639 1640 throw error; 1641});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.