diff --git a/.sass-cache/3566244f41d72698175d1ae4f088bd2e3dff2559/main.scssc b/.sass-cache/3566244f41d72698175d1ae4f088bd2e3dff2559/main.scssc new file mode 100644 index 0000000000..76fc24b01a Binary files /dev/null and b/.sass-cache/3566244f41d72698175d1ae4f088bd2e3dff2559/main.scssc differ diff --git a/404.md b/404.md index c04bcce824..cd0bcb203a 100644 --- a/404.md +++ b/404.md @@ -1,10 +1,9 @@ --- -layout: page +layout: fourofour title: Page Not Found description: hide: true --- -
-

404 - The page you're looking for does not exist.

-
+ + diff --git a/Install-Package b/Install-Package new file mode 100644 index 0000000000..e69de29bb2 diff --git a/README.md b/README.md index 9ba72e6b8b..cd697658d1 100755 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ Please see the sections below for more information. + [License](#license) + [Prerequisites](#prerequisites) + [Running Jekyll Locally](#running-jekyll-locally) -+ [Alphabetization of Bidder Adapters](#alphabetization-of-bidder-adaptors) + [The Downloads Page](#the-downloads-page) + [Thanks](#thanks) @@ -81,24 +80,6 @@ Configuration file: /Users/rloveland/Dropbox/Code/prebid.github.io/_config.yml Open the `Server address` URL in your browser, and you should see a locally running copy of the site. - - -## Alphabetization of Bidder Adaptors - -Please don't alphabetize the lists of adapters in your PR, either on the home page or the downloads page. - -The adapters are not listed in alphabetical order, they're listed in the order in which they were added to the Prebid.js repo, using (approximately) this command in `src/adapters`: - -``` -for file in `ls | grep -f <(git ls-files)`; do - HASH=`git rev-list HEAD $file | tail -n 1`; - DATE=`git show -s --format="%ci" $HASH --`; - printf "%-35s %-35s %s\n" $file "$DATE" $HASH; -done | sort -d -k 2 -``` - - - ## The Downloads Page Please don't submit PRs to the Prebid.org downloads page. That page gets updated in tandem with the Prebid.js release process. @@ -117,70 +98,3 @@ This means an adaptor is not available to download from Prebid.org as soon as th ## Thanks Many thanks to the following people who have submitted content to Prebid.org. We really appreciate the help! - -In alphabetical order: - -+ Alejandro Villanueva -+ Andrew Bowman -+ Andy Stocker -+ Artem Dmitriev -+ Bart van Bragt -+ Bret Gorsline -+ Carson Banov -+ Casper van Wezel -+ Chris Hepner -+ Christopher Allene -+ Dan Harton -+ David -+ David M -+ Ilya Pirogov -+ Itay Ovits -+ Jackson Faddis -+ Jonny Greenspan -+ Joseph Frazer -+ Julien Delhommeau -+ Kir Apukhtin -+ Kizzard -+ Lin Rubo -+ Matan Arbel -+ Mats Attnas -+ Matt Jacobson -+ Matt Jacobson -+ Matt Kendall -+ Matt Kendall -+ Matt Lane -+ Mordhak -+ Nate Guisinger -+ Niksok -+ Paul -+ Paul Yang -+ Paul Young -+ Pavlos Kalogiannidis -+ Prebid-Team -+ Raffael Vogler -+ Rich Loveland -+ Rich Loveland -+ Ronald Berner -+ Sahagun, Manny -+ Tiffany Wu -+ Vladimir Marteev -+ astudnicky -+ bjorn-wo -+ bjorna -+ christopher-allene-piximedia -+ devmusings -+ dlogachev -+ eyal -+ lntho -+ lukian -+ naegelin -+ ncozi -+ onaydenov -+ prebid -+ prebid -+ protonate -+ rizhang -+ rml -+ ronenst -+ sberry -+ studnicky diff --git a/_config.yml b/_config.yml index dc54398678..c6b572922c 100755 --- a/_config.yml +++ b/_config.yml @@ -58,109 +58,28 @@ facebook: # Build settings markdown: kramdown -nav_sections: - - top_nav: beta - code: current - name: CURRENT BETA - - top_nav: beta - code: past - name: PAST BETA - - - top_nav: dev_docs - code: quick-start - name: DEVELOPER QUICK START - - top_nav: dev_docs - code: prebid-multi-format - name: PREBID MULTI-FORMAT (BETA) - - top_nav: dev_docs - code: prebid-video - name: PREBID VIDEO - - top_nav: dev_docs - code: prebid-native - name: PREBID NATIVE - - top_nav: dev_docs - code: prebid-server - name: PREBID SERVER - - top_nav: dev_docs - code: prebid-amp - name: PREBID FOR AMP (BETA) - - top_nav: dev_docs - code: troubleshooting - name: TROUBLESHOOTING - - top_nav: dev_docs - code: reference - name: REFERENCE - - top_nav: dev_docs - code: features - name: FEATURES - - top_nav: dev_docs - code: adapters - name: ADAPTERS - - top_nav: dev_docs - code: interfaces - name: EXTERNAL INTERFACES - - - top_nav: overview - code: intro - name: INTRO - - top_nav: overview - code: postbid - name: POST-BID - - top_nav: overview - code: analytics - name: ANALYTICS - - top_nav: overview - code: studies - name: LATEST STUDIES - - # - top_nav: beta - # code: BETA PRODUCTS - - - top_nav: adops - code: tutorials - name: AD OPS TUTORIALS - - top_nav: adops - code: reference - name: REFERENCE - - - top_nav: support - code: support - name: SUPPORT - - - top_nav: videos - code: videos - name: VIDEOS - - - top_nav: principles - code: principles - name: PRINCIPLES - - - top_nav: download - code: download - name: DOWNLOAD - - - top_nav: modules - code: modules - name: MODULES - - - top_nav: prebid-mobile - code: prebid-mobile - name: PREBID MOBILE - #- top_nav: prebid-mobile - #code: prebid-mobile-pbs - #name: PREBID SERVER - - top_nav: prebid-mobile - code: prebid-mobile-ios - name: FOR IOS - - top_nav: prebid-mobile - code: prebid-mobile-android - name: FOR ANDROID - - top_nav: prebid-mobile - code: prebid-mobile-adops - name: FOR ADOPS - - top_nav: prebid-mobile - code: prebid-mobile-contributors - name: FOR CONTRIBUTORS +highlighter: rouge + +kramdown: + input: GFM + # https://github.com/jekyll/jekyll/pull/4090 + syntax_highlighter: rouge + + # Rouge Highlighter in Kramdown › http://kramdown.gettalong.org/syntax_highlighter/rouge.html + # span, block element options fall back to global + syntax_highlighter_opts: + # Rouge Options › https://github.com/jneen/rouge#full-options + css_class: 'highlight' + #line_numbers: true # bad idea, spans don't need linenos and would inherit this option + span: + line_numbers: false + block: + line_numbers: false + start_line: 1 + +# Collections +collections: + - bidders port: 8080 diff --git a/_data/dropdown_v2.yml b/_data/dropdown_v2.yml new file mode 100644 index 0000000000..78d68243b6 --- /dev/null +++ b/_data/dropdown_v2.yml @@ -0,0 +1,375 @@ +#-----------Overview--------------- + +- sectionId: 0 + sectionName: Overview + link: + isHeader: 1 + hasSubMenus: 1 + submenus: + + - subsectionId: 0 + sectionId: 0 + sectionName: Overview + title: What is Prebid? + link: /overview/intro.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 0 + sectionId: 0 + sectionName: Overview + title: Project Principles + link: /principles.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 0 + sectionName: Overview + title: Contributing + link: /contributing/contribute.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 0 + sectionName: Overview + title: About Prebid.Org + link: /overview/what-is-prebid-org.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 0 + sectionName: Overview + title: Members and Partners + link: /partners/partners.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 0 + sectionName: Overview + title: Privacy Policy + link: /privacy.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 0 + sectionName: Overview + title: Events + link: /prebid/events.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + +#----------Product SubNav------------ + +- sectionId: 1 + sectionName: Product + link: + isHeader: 1 + hasSubMenus: 1 + submenus: + + - subsectionId: 0 + sectionId: 1 + sectionName: Product + title: Prebid.js + link: /prebid/prebidjs.html + needsDivider: 0 + isHeader: 0 + isSubHeader: 1 + isSubSectionStart: 1 + nbCollapseId: prebidjs + + - subsectionId: 0 + sectionId: 1 + sectionName: Product + title: Analytics + link: /overview/analytics.html + needsDivider: 0 + isHeader: 0 + isSubHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 1 + sectionName: Product + title: Modules + link: /dev-docs/modules/index.html + needsDivider: 0 + isHeader: 0 + isSubHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 1 + sectionName: Product + title: Publisher API + link: /dev-docs/publisher-api-reference.html + needsDivider: 0 + isHeader: 0 + isSubHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 1 + sectionName: Product + title: Bidder Params + link: /dev-docs/bidders.html + needsDivider: 0 + isHeader: 0 + isSubHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 0 + sectionId: 1 + sectionName: Product + title: Plugins + link: /dev-docs/plugins/index.html + needsDivider: 1 + isHeader: 0 + isSubHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 1 + sectionId: 1 + sectionName: Product + title: Prebid Server + link: /prebid-server/prebid-server-overview.html + needsDivider: 1 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 2 + sectionId: 1 + sectionName: Product + title: Prebid Mobile + link: /prebid-mobile/prebid-mobile.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 2 + sectionId: 1 + sectionName: Product + title: iOS + link: /prebid-mobile/pbm-api/ios/code-integration-ios.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 2 + sectionId: 1 + sectionName: Product + title: Android + link: /prebid-mobile/pbm-api/android/code-integration-android.html + needsDivider: 1 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 3 + sectionId: 1 + sectionName: Product + title: Formats + link: /formats/formats.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 3 + sectionId: 1 + sectionName: Product + title: Display + link: /formats/display.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 3 + sectionId: 1 + sectionName: Product + title: Video + link: /formats/video.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 3 + sectionId: 1 + sectionName: Product + title: Native + link: /formats/native.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 3 + sectionId: 1 + sectionName: Product + title: AMP + link: /formats/amp.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 3 + sectionId: 0 + sectionName: Product + title: Multi-Format + link: /formats/multiformat.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + +#-------------_Support Section--------------- + +- sectionId: 2 + sectionName: Support + link: + isHeader: 1 + hasSubMenus: 1 + submenus: + + - subsectionId: 0 + sectionId: 2 + sectionName: Support + title: Ad Ops + link: /adops/before-you-start.html + needsDivider: 1 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 1 + sectionId: 2 + sectionName: Support + title: Developers + link: /developers.html + needsDivider: 1 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 2 + sectionId: 2 + sectionName: Support + title: Help + link: /support/index.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 2 + sectionId: 2 + sectionName: Support + title: Troubleshooting + link: /troubleshooting/troubleshooting.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 2 + sectionId: 2 + sectionName: Support + title: Training Videos + link: /videos/index.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 2 + sectionId: 2 + sectionName: Support + title: Debugging Extension + link: /debugging/debugging.html + needsDivider: 1 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 3 + sectionId: 2 + sectionName: Support + title: FAQ + link: /faq/faq.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 3 + sectionId: 2 + sectionName: Support + title: Prebid.js + link: /dev-docs/faq.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 3 + sectionId: 2 + sectionName: Support + title: Prebid Server + link: /faq/prebid-server-faq.html + needsDivider: 1 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 4 + sectionId: 2 + sectionName: Support + title: Blog + link: /blog.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 1 + +#-----------_Downloads--------------- + +- sectionId: 3 + sectionName: Download + link: + isHeader: 1 + hasSubMenus: 1 + submenus: + + - subsectionId: 0 + sectionId: 3 + sectionName: Download + title: Prebid.js + link: /download.html + needsDivider: 1 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 1 + sectionId: 3 + sectionName: Download + title: Prebid Mobile + link: /prebid-mobile/download.html + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 1 + + - subsectionId: 1 + sectionId: 3 + sectionName: Download + title: iOS + link: https://github.com/prebid/prebid-mobile-ios + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 + + - subsectionId: 1 + sectionId: 3 + sectionName: Download + title: Android + link: https://github.com/prebid/prebid-mobile-android + needsDivider: 0 + isHeader: 0 + isSubSectionStart: 0 diff --git a/_data/message.yml b/_data/message.yml new file mode 100644 index 0000000000..0ee957e410 --- /dev/null +++ b/_data/message.yml @@ -0,0 +1,4 @@ +#-------------Message---------------- +- messageId: 1 + messageText: Prebid Meetup and Leadership Summit in San Francisco on Oct 24th 2019!
Prebid.js 3.0 Major Release Announcement + messageCreateDt: 10_07_2019 diff --git a/_data/partners.yml b/_data/partners.yml new file mode 100644 index 0000000000..8956a0b809 --- /dev/null +++ b/_data/partners.yml @@ -0,0 +1,94 @@ +- company: AppNexus + link: https://www.appnexus.com/en/publishers/header-bidding + imgURL: /assets/images/partners/founders/appnexus.png + type: founder + +- company: Rubicon + link: https://rubiconproject.com/header-bidding-for-publishers/ + imgURL: /assets/images/partners/founders/rubicon.png + type: founder + +- company: OpenX + link: https://www.openx.com/ + imgURL: /assets/images/partners/leader/openx.png + type: leader + +- company: Pubmatic + link: https://pubmatic.com/products/header-bidding/ + imgURL: /assets/images/partners/leader/pubmatic.png + type: leader + +- company: SpotX + link: https://spotx.tv + imgURL: /assets/images/partners/leader/spotx_logo.png + type: leader + +- company: Criteo + link: https://www.criteo.com/for-publishers/products/criteo-direct-bidder/ + imgURL: /assets/images/partners/tech/criteo.png + type: technology + +- company: Marfeel + link: https://www.marfeel.com/ + imgURL: /assets/images/partners/tech/marfeel.png + type: technology + +- company: Oath + link: https://www.oath.com/advertising/platforms/ + imgURL: /assets/images/partners/tech/oath.png + type: technology + +- company: PubNative + link: https://pubnative.net/ + imgURL: /assets/images/partners/tech/Pubnative-RGB-Logo.png + type: technology + +- company: Sortable + link: https://www.sortable.com/ + imgURL: /assets/images/partners/tech/sortable.png + type: technology + +- company: StreamAMP + link: https://streamamp.com/ + imgURL: /assets/images/partners/tech/StreamAMP_logo.png + type: technology + +- company: CafeMedia + link: http://www.cafemedia.com/ + imgURL: /assets/images/partners/publisher/cafemedia.png + type: publisher + +- company: Mediavine + link: https://www.mediavine.com/ + imgURL: /assets/images/partners/publisher/mediavine-sq-teal-navy-pn-RGB.png + type: publisher + +- company: News Corp + link: https://newscorp.com/ + imgURL: /assets/images/partners/publisher/News_Corp_logo.png + type: publisher + +- company: CHEQ + link: https://www.cheq.ai/ + imgURL: /assets/images/partners/community/CHEQ_Logo.png + type: community + +- company: GoBrowsi + link: https://gobrowsi.com + imgURL: /assets/images/partners/community/Browsi-Logo.png + type: community + +- company: ID5 + link: https://id5.io + imgURL: /assets/images/partners/community/ID5-Logo.png + type: community + +- company: Publica + link: https://getpublica.com + imgURL: /assets/images/partners/community/Publica-Logo.png + type: community + +- company: PubWise + link: https://pubwise.io + imgURL: /assets/images/partners/community/Pubwise-logo.png + type: community diff --git a/_data/pb-api b/_data/pb-api new file mode 100644 index 0000000000..9059909e04 --- /dev/null +++ b/_data/pb-api @@ -0,0 +1,5 @@ +- api + - element: getAdserverTargeting + - endpoint: .getAdserverTargeting() + - element: getAdserverTargetingForAdUnitCode + - endpoint: .getAdserverTargetingForAdUnitCode(adUnitCode) \ No newline at end of file diff --git a/_data/pb-api.yml b/_data/pb-api.yml new file mode 100644 index 0000000000..3060020670 --- /dev/null +++ b/_data/pb-api.yml @@ -0,0 +1,18 @@ + +- catId: 0 + catName: About + +- catId: 1 + catName: Configuration + +- catId: 2 + catName: Bids + +- catId: 3 + catName: Server + +- catId: 4 + catName: Targeting + +- catId: 5 + catName: AdUnit diff --git a/_data/sidebar.yml b/_data/sidebar.yml new file mode 100644 index 0000000000..c5fdf4a9fe --- /dev/null +++ b/_data/sidebar.yml @@ -0,0 +1,1858 @@ +#--------------Overview--------------| + +- sbSecId: 0 + title: + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 1 + sectionTitle: Overview + sectionId: overview + subgroup: 1000 + sbCollapseId: overview + + +- sbSecId: 0 + title: General + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: general + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: What is Prebid? + link: /overview/intro.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Project Principles + link: /principles.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Contributing + link: /contributing/contribute.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: About Prebid.org + link: /overview/what-is-prebid-org.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Members and Partners + link: /partners/partners.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Prebid Management Committees + link: /overview/prebid-management-committees.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Header Bidding Wrapper Code of Conduct + link: /wrapper_code_of_conduct.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Community Code of Conduct + link: /overview/community-code-of-conduct.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + subgroup: 0 + +- sbSecId: 0 + title: Developers + link: /developers.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + subgroup: 0 + +- sbSecId: 0 + title: Prebid.org IP Policy + link: /overview/ip-policy.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Privacy Policy + link: /privacy.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 0 + title: Cookies + link: /cookies.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + subgroup: 0 + +- sbSecId: 0 + title: Managed Services + link: /prebid/managed.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + subgroup: 0 + +#--------------Prebid.js--------------| + +- sbSecId: 1 + title: + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 1 + sectionTitle: Prebid.js + sectionId: prebidjs + subgroup: 1000 + sbCollapseId: prebidjs + +- sbSecId: 1 + title: Developer Quick Start + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: devquickstart + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + sbCollapseId: 1 + +- sbSecId: 1 + title: What is Prebid.js + link: /prebid/prebidjs.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 1 + title: Getting Started + link: /dev-docs/getting-started.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 1 + title: Examples + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: pbjsexamples + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 1 + title: Basic Example + link: /dev-docs/examples/basic-example.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 1 + title: Multi-Format Ads + link: /dev-docs/examples/multi-format-example.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 1 + title: Individual Ad Unit Refresh/Infinite Scroll + link: /dev-docs/examples/adunit-refresh.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 1 + title: Using Prebid.js with AppNexus Publisher Ad Server + link: /dev-docs/examples/use-prebid-with-appnexus-ad-server.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 1 + title: Postbid Example + link: /dev-docs/examples/postbid.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 1 + title: Custom Price Granularity Buckets + link: /dev-docs/examples/custom-price-buckets.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 1 + title: Filter Sizes Dynamically with Labels + link: /dev-docs/examples/size-mapping.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 1 + title: Troubleshooting + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: troubleshooting + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 1 + title: Prebid.js FAQ + link: /dev-docs/faq.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 1 + title: Troubleshooting Guide + link: /troubleshooting/troubleshooting-guide.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 1 + title: Common Issues + link: /dev-docs/common-issues.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 1 + title: Browser Extension for Debugging + link: /debugging/debugging.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 1 + title: Reference + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: reference + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 1 + title: Publisher API Reference + link: /dev-docs/publisher-api-reference.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 1 + title: Ad Unit Reference + link: /dev-docs/adunit-reference.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 1 + title: Bidder Params + link: /dev-docs/bidders.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 1 + title: Prebid.js Releases + link: /prebid/prebidjsReleases.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 1 + title: Prebid 1.0 Publisher API Changes + link: /dev-docs/prebid-1.0-API.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 1 + title: Adding an Adapter + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: adapters + isSectionHeader: 0 + sectionTitle: + subgroup: 4 + +- sbSecId: 1 + title: How to Add a Bidder Adapter + link: /dev-docs/bidder-adaptor.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 4 + +- sbSecId: 1 + title: How to Add an Analytics Adapter + link: /dev-docs/integrate-with-the-prebid-analytics-api.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 4 + +- sbSecId: 1 + title: Prebid Modules + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: pbjsmodules + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Module Overview + link: /dev-docs/modules/ + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Currency + link: /dev-docs/modules/currency.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Google Ad Manager Express + link: /dev-docs/modules/dfp_express.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: GPDR Consent Management + link: /dev-docs/modules/consentManagement.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Supply Chain Object + link: /dev-docs/modules/schain.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: User ID + link: /dev-docs/modules/userId.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Server To Server Testing + link: /dev-docs/modules/s2sTesting.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Google Ad Manager Video + link: /dev-docs/modules/dfp_video.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Freewheel Module + link: /dev-docs/modules/freewheel.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Ad Pod Module + link: /dev-docs/modules/adpod.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Category Translation + link: /dev-docs/modules/categoryTranslation.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: Konduit Accelerate Module + link: /dev-docs/modules/konduit.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 1 + title: External Interfaces + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: external + isSectionHeader: 0 + sectionTitle: + subgroup: 6 + +- sbSecId: 1 + title: Plugins + link: /dev-docs/plugins/ + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 6 + +- sbSecId: 1 + title: Analytics + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: analytics + isSectionHeader: 0 + sectionTitle: + subgroup: 7 + +- sbSecId: 1 + title: Analytics For Prebid + link: /overview/analytics.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 7 + +- sbSecId: 1 + title: Prebid Analytics for GA + link: /overview/ga-analytics.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 7 + +- sbSecId: 1 + title: Features + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: features + isSectionHeader: 0 + sectionTitle: + subgroup: 8 + +- sbSecId: 1 + title: Native Ads + link: /dev-docs/show-native-ads.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 8 + +- sbSecId: 1 + title: Multi-Format Ads + link: /dev-docs/show-multi-format-ads.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 8 + +- sbSecId: 1 + title: Conditional Ad Units + link: /dev-docs/conditional-ad-units.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 8 + +- sbSecId: 1 + title: Post-Bid + link: /overview/what-is-post-bid.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 8 + + +#--------------Prebid Mobile--------------| + +- sbSecId: 2 + title: + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 1 + sectionTitle: Prebid Mobile + sectionId: prebid-mobile + subgroup: 1000 + sbCollapseId: prebid-mobile + +- sbSecId: 2 + title: General + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: general + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 2 + title: Overview + link: /prebid-mobile/prebid-mobile.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 2 + title: Getting Started With Prebid Mobile + link: /prebid-mobile/prebid-mobile-pbs.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 2 + title: Prebid AMP + link: /dev-docs/show-prebid-ads-on-amp-pages.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 2 + title: GDPR and Mobile + link: /prebid-mobile/gdpr.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 2 + title: Download + link: /prebid-mobile/download.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 2 + title: For iOS + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: ios + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: Code Integration + link: /prebid-mobile/pbm-api/ios/code-integration-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: iOS Mobile API + link: /prebid-mobile/pbm-api/ios/pbm-api-iOS.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: Ad Unit + link: /prebid-mobile/pbm-api/ios/pbm-adunit-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: Banner Ad Unit + link: /prebid-mobile/pbm-api/ios/pbm-banneradunit-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: Interstitial Ad Unit + link: /prebid-mobile/pbm-api/ios/pbm-interstitialadunit-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: Targeting Parameters + link: /prebid-mobile/pbm-api/ios/pbm-targeting-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: Result Codes + link: /prebid-mobile/pbm-api/ios/pbm-api-result-codes-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: Prebid Mobile Object + link: /prebid-mobile/pbm-api/ios/prebidmobile-object-ios.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 2 + title: Prebid Utilities + link: /prebid-mobile/pbm-api/ios/pbm-util-ios.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + + +- sbSecId: 2 + title: For Android + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: android + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Code Integration + link: /prebid-mobile/pbm-api/android/code-integration-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Android Mobile API + link: /prebid-mobile/pbm-api/android/pbm-api-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Ad Unit + link: /prebid-mobile/pbm-api/android/pbm-adunit-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Banner Ad Unit + link: /prebid-mobile/pbm-api/android/pbm-banneradunit-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Interstitial Ad Unit + link: /prebid-mobile/pbm-api/android/pbm-interstitialadunit-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Targeting Parameters + link: /prebid-mobile/pbm-api/android/pbm-targeting-params-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Result Codes + link: /prebid-mobile/pbm-api/android/pbm-api-result-codes-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Prebid Mobile Object + link: /prebid-mobile/pbm-api/android/prebidmobile-object-android.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: Prebid Utility Functions + link: /prebid-mobile/pbm-api/android/pbm-util-android.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 2 + title: For Ad Ops + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: foradops + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 2 + title: Setup Line items For Google Ad Manager + link: /prebid-mobile/adops-line-item-setup-dfp.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 2 + title: Setup Line Items For MoPub + link: /prebid-mobile/adops-line-item-setup-mopub.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 2 + title: Price Granularity + link: /prebid-mobile/adops-price-granularity.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + +- sbSecId: 2 + title: Dr. Prebid Validation App + link: /prebid-mobile/dr-prebid.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 3 + + +- sbSecId: 2 + title: For Contributors + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: forcontributors + isSectionHeader: 0 + sectionTitle: + subgroup: 4 + +- sbSecId: 2 + title: Add an Ad Server Adapter + link: /prebid-mobile/add-an-ad-server-adapter.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 4 + +- sbSecId: 2 + title: Legacy API + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: legacyapi + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 2 + title: Code Integration - iOS + link: /prebid-mobile/legacy/ios/code-integration-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 2 + title: Targeting Parameters - iOS + link: /prebid-mobile/legacy/ios/targeting-params-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 2 + title: Logging and Troubleshooting - iOS + link: /prebid-mobile/legacy/ios/logging-troubleshooting-ios.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 2 + title: Code Integration - Android + link: /prebid-mobile/legacy/android/code-integration-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 2 + title: Targeting Parameters - Android + link: /prebid-mobile/legacy/android/targeting-params-android.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +- sbSecId: 2 + title: Logging and Troubleshooting - Android + link: /prebid-mobile/legacy/android/logging-troubleshooting-android.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 5 + +#--------------Ad Ops--------------| + +- sbSecId: 3 + title: + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 1 + sectionTitle: Ad Ops + sectionId: ad-ops + subgroup: 1000 + sbCollapseId: ad-ops + +- sbSecId: 3 + title: Ad Ops Tutorials + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: adopstuts + isSectionHeader: 0 + sectionTitle: Ad Ops + subgroup: 0 + +- sbSecId: 3 + title: AdOps View of Prebid + link: /adops/before-you-start.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Prebid Universal Creative + link: /overview/prebid-universal-creative.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Guide to Google Ad Manager Setup + link: /adops/step-by-step.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Send All Bids to the Ad Server + link: /adops/send-all-bids-adops.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Setting up Prebid for AMP in Google Ad Manager + link: /adops/setting-up-prebid-for-amp-in-dfp.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Setting up Prebid Multi-Format in Google Ad Manager + link: /adops/setting-up-prebid-multi-format-in-dfp.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Setting up Prebid Native in Google Ad Manager (Alpha) + link: /adops/setting-up-prebid-native-in-dfp.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Setting up Prebid Video in Google Ad Manager + link: /adops/setting-up-prebid-video-in-dfp.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Setting up Prebid Long-Form Video in FreeWheel + link: /adops/setting-up-prebid-video-in-freewheel.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Setting up Prebid Long-Form Video in Google Ad Manager + link: /adops/setting-up-prebid-ott-video-in-gam.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Setting up Prebid with the AppNexus Publisher Ad Server + link: /adops/setting-up-prebid-with-the-appnexus-ad-server.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Setting up Prebid.js with Smart Ad Server + link: /adops/setting-up-prebidjs-with-Smart-Ad-Server.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Enable Deals + link: /adops/deals.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 3 + title: Studies + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: studies + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 3 + title: Optimize Header Bidding Setup + link: /overview/how-many-bidders-for-header-bidding.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 3 + title: Optimal Header Bidding Setup + link: /overview/optimal-header-bidding-setup.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 3 + title: How To Reduce The Latency of Header Bidding With Prebid.js + link: /overview/how-to-reduce-latency-of-header-bidding.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 3 + title: How to Simplify Line Item Setup + link: /overview/how-to-simplify-line-item-setup.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +#--------------Prebid Video--------------| + +- sbSecId: 4 + title: + link: + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 1 + sectionTitle: Prebid Video + sectionId: prebid-video + subgroup: 1000 + sbCollapseId: prebid-video + +- sbSecId: 4 + title: Overview + link: + isLastSubSectionItem: 1 + isHeader: 1 + headerId: vidoverview + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 4 + title: Prebid.js for Video Overview + link: /prebid-video/video-overview.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 4 + title: Getting Started with Video for Prebid.js + link: /prebid-video/video-getting-started.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 4 + title: Getting Started with Long Form Video for Prebid.js + link: /prebid-video/video-long-form.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + + +- sbSecId: 4 + title: Show Video Ads with Google Ad Manager + link: /dev-docs/show-video-with-a-dfp-video-tag.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 4 + title: Show OTT Video Ads with Prebid + link: /dev-docs/show-long-form-video-with-gam.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 4 + title: Outstream Video Ads + link: /dev-docs/show-outstream-video-ads.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 4 + title: Training Videos + link: /videos/prebid-video.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 4 + title: Examples + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: videxamples + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: Prebid.js Video Examples + link: /examples/video/ + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + isCatHeader: 1 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: "Instream" + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + isCatHeader: 1 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Brid' + link: /examples/video/instream/brid/pb-ve-brid.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Brightcove' + link: /examples/video/instream/brightcove/pb-ve-brightcove.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Flowplayer' + link: /examples/video/instream/flowplayer/pb-ve-flowplayer.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  JW Player (Platform)' + link: /examples/video/instream/jwplayer/pb-ve-jwplayer-platform.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  JW Player (Hosted)' + link: /examples/video/instream/jwplayer/pb-ve-jwplayer-hosted.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  JW Player (Playlist)' + link: /examples/video/instream/jwplayer/pb-ve-jwplayer-playlist.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Kaltura' + link: /examples/video/instream/kaltura/pb-ve-kaltura.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Ooyala' + link: /examples/video/instream/ooyala/pb-ve-ooyala.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  VideoJS' + link: /examples/video/instream/videojs/pb-ve-videojs.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: "Prebid Server" + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + isCatHeader: 1 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Brid' + link: /examples/video/server/brid/pbs-ve-brid.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  JW Player (Platform)' + link: /examples/video/server/jwplayer/pbs-ve-jwplayer-platform.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  JW Player (Hosted)' + link: /examples/video/server/jwplayer/pbs-ve-jwplayer-hosted.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  JW Player (Playlist)' + link: /examples/video/server/jwplayer/pbs-ve-jwplayer-playlist.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  JW Player (Player 7)' + link: /examples/video/server/jwplayer/pbs-ve-jwplayer-jwplayer7.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Kaltura' + link: /examples/video/server/kaltura/pbs-ve-kaltura.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Ooyala' + link: /examples/video/server/ooyala/pbs-ve-ooyala.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  VideoJS' + link: /examples/video/server/videojs/pbs-ve-videojs.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: "Outstream" + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + isCatHeader: 1 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Google Ad Manager' + link: /examples/video/outstream/pb-ve-outstream-dfp.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  No Server' + link: /examples/video/outstream/pb-ve-outstream-no-server.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: "Long-Form (Ad Pods)" + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + isCatHeader: 1 + sectionTitle: + subgroup: 1 + +- sbSecId: 4 + title: '  Freewheel' + link: /examples/video/long-form/pb-ve-lf-freewheel.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + + + + + +#--------------Prebid Server--------------| + +- sbSecId: 5 + title: + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 1 + sectionTitle: Prebid Server + sectionId: prebid-server + subgroup: 1000 + sbCollapseId: prebid-server + +- sbSecId: 5 + title: Prebid Server Overview + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: serveroverview + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 5 + title: Overview + link: /prebid-server/prebid-server-overview.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 5 + title: Developers + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: serverdevelopers + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: Add A New Analytics Module + link: /prebid-server/developers/add-new-analytics-module.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: Add A Bidder + link: /prebid-server/developers/add-new-bidder.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: Prebid Server Bidders - Additional Info + link: /prebid-server/developers/pbs-bidder-info.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: Cookie Sync Technical Details + link: /prebid-server/developers/cookie-syncs.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: COPPA Compliance + link: /prebid-server/developers/coppa.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: Currency Converter + link: /prebid-server/developers/currency-converter.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: Default Request + link: /prebid-server/developers/default-request.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: GDPR Mechanics + link: /prebid-server/developers/gdpr.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: Stored Requests + link: /prebid-server/developers/stored-requests.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 1 + +- sbSecId: 5 + title: Endpoints + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: endpoints + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Info - Bidders + link: /prebid-server/endpoints/info/bidders.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Info - Bidder Name + link: /prebid-server/endpoints/info/bidders/bidderName.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Bidders - Params + link: /prebid-server/endpoints/bidders/params.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Starting Cookie Sync + link: /prebid-server/endpoints/cookieSync.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Prebid Server Auction + link: /prebid-server/endpoints/openrtb2/auction.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Prebid Server AMP + link: /prebid-server/endpoints/openrtb2/amp.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Prebid Server Video + link: /prebid-server/endpoints/openrtb2/video.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Saving User Syncs + link: /prebid-server/endpoints/setuid.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Get User Syncs + link: /prebid-server/endpoints/getuids.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +- sbSecId: 5 + title: Get Status + link: /prebid-server/endpoints/status.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 2 + +#--------------Formats--------------| + +- sbSecId: 6 + title: + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 1 + sectionTitle: Formats + sectionId: formats + subgroup: 1000 + sbCollapseId: formats + +- sbSecId: 6 + title: General + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: general + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 6 + title: Overview + link: /formats/formats.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 6 + title: Display + link: /formats/display.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 6 + title: Video + link: /prebid-video/video-overview.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 6 + title: Native + link: /dev-docs/show-native-ads.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 6 + title: AMP + link: /formats/amp.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 6 + title: Multi-Format + link: /dev-docs/show-multi-format-ads.html + isLastSubSectionItem: 1 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + + #-------------- Support --------------| + +- sbSecId: 7 + title: + link: + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 1 + sectionTitle: Support + sectionId: support + subgroup: 1000 + sbCollapseId: support + +- sbSecId: 7 + title: Overview + link: + isLastSubSectionItem: 0 + isHeader: 1 + headerId: supportoverview + isSectionHeader: + sectionTitle: + subgroup: 0 + +- sbSecId: 7 + title: Help + link: /support/ + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 7 + title: Troubleshooting + link: /troubleshooting/troubleshooting.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 7 + title: Training Videos + link: /videos/ + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 7 + title: FAQs + link: /faq/faq.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 + +- sbSecId: 7 + title: Blog + link: /blog.html + isLastSubSectionItem: 0 + isHeader: 0 + isSectionHeader: 0 + sectionTitle: + subgroup: 0 diff --git a/_includes/alerts/alert_important.html b/_includes/alerts/alert_important.html new file mode 100644 index 0000000000..420906f82f --- /dev/null +++ b/_includes/alerts/alert_important.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_includes/alerts/alert_note.html b/_includes/alerts/alert_note.html new file mode 100644 index 0000000000..39d6e9e6ac --- /dev/null +++ b/_includes/alerts/alert_note.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_includes/alerts/alert_tip.html b/_includes/alerts/alert_tip.html new file mode 100644 index 0000000000..6fd7ae535c --- /dev/null +++ b/_includes/alerts/alert_tip.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_includes/alerts/alert_warning.html b/_includes/alerts/alert_warning.html new file mode 100644 index 0000000000..beb041e08d --- /dev/null +++ b/_includes/alerts/alert_warning.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_includes/api/pb-api-search-results.html b/_includes/api/pb-api-search-results.html new file mode 100644 index 0000000000..9a4bd393ac --- /dev/null +++ b/_includes/api/pb-api-search-results.html @@ -0,0 +1,125 @@ + + + + +
+
Searching...
+
+ + + + + + + + diff --git a/_includes/api/pb-api-template.html b/_includes/api/pb-api-template.html new file mode 100644 index 0000000000..2e09e305fe --- /dev/null +++ b/_includes/api/pb-api-template.html @@ -0,0 +1,55 @@ + + + +
+ +
Endpoint Title
+
This is the endpoint description
+
+

endpoint

+
pbjs.setConfig({ debug: true });
+
+ +
+
Arguments:
+
+
    +
  • + arg1: string +

    String indicating some value that has to be passed as a string type.

    +
  • +
  • + arg2: number +

    Number indicating some value that has to be passed as a number type.

    +
  • +
+
+
+ +
+ +
Response
+
Response Description
+
+

endpoint response

+
{ response: example }
+
+ +
+
    +
  • + param1: string +

    String indicating some value that has to be passed as a string type.

    +
  • +
  • + param2: number +

    Number indicating some value that has to be passed as a number type.

    +
    Note: This number should be between 0 and infinity.
    +
  • +
+
+
+ + +
+ diff --git a/_includes/api/pb-api-test.html b/_includes/api/pb-api-test.html new file mode 100644 index 0000000000..eb0e2fbe54 --- /dev/null +++ b/_includes/api/pb-api-test.html @@ -0,0 +1,173 @@ + + + + + +
+ +
+ {% assign arrCategories = site.data.pb-api %} + + +
+ + + +
+ + +
+ +
+

Select a category to see API endpoints related to that category.

+
+ +
+ +
+ +
+
+
Sample Bid Response
+
+
+ +
+
Bid Response Parameters
+
+
+
+ +
+ + \ No newline at end of file diff --git a/_includes/dev-docs/amp-creative.md b/_includes/dev-docs/amp-creative.md deleted file mode 100644 index 74455d4682..0000000000 --- a/_includes/dev-docs/amp-creative.md +++ /dev/null @@ -1,29 +0,0 @@ -{% highlight html %} - - - - -{% endhighlight %} \ No newline at end of file diff --git a/_includes/disqus_addon.html b/_includes/disqus_addon.html index 265bc30bd6..0a6d69eaab 100644 --- a/_includes/disqus_addon.html +++ b/_includes/disqus_addon.html @@ -2,16 +2,4 @@
- - diff --git a/_includes/foot.html b/_includes/foot.html deleted file mode 100644 index 0e98d9c212..0000000000 --- a/_includes/foot.html +++ /dev/null @@ -1,117 +0,0 @@ -
-
-
-
    - - {% if site.githubButton.user and site.githubButton.repo %} -
  • - -
  • -
  • - -
  • - {% endif %} - - {% if site.twitter.enabled %} -
  • - -
  • - {% endif %} - - {% if site.twitter.account %} -
  • - -
  • - {% endif %} - - {% if site.facebook.enabled %} -
  • -
    -
  • - {% endif %} - - {% if site.facebook.profileUrl %} -
  • -
    -
  • - {% endif %} - -
-
- -

- All demos, instructions, documentation and code included on the Prebid.org website are released under the {{site.license}}. -

- -

- Documentation template by the Bootstrap team, generated with Jekyll Bootstrap Doc. -

- - -
-
- - -{% if site.header.trianglify %} - - - -{% endif %} - -{% if site.twitter.enabled or site.twitter.account %} - -{% endif %} - -{% if site.facebook.enabled or site.facebook.profileUrl %} -
- -{% endif %} - -{% if site.analytics.account and site.analytics.domain %} - -{% endif %} - - - - - - \ No newline at end of file diff --git a/_includes/footer.html b/_includes/footer.html new file mode 100644 index 0000000000..668058859f --- /dev/null +++ b/_includes/footer.html @@ -0,0 +1,27 @@ + +
+ +
+ + + + + + + + + + diff --git a/_includes/head.html b/_includes/head.html index c53195880c..6c3ba30b27 100644 --- a/_includes/head.html +++ b/_includes/head.html @@ -7,19 +7,45 @@ - - - + + + + {% if page.head_title %} {{page.head_title}} {% else %} {{page.title}} for Header Bidding {% endif %} - + + + + + + + + + + - + + + + + + + + + + + + + + + - + + + + - \ No newline at end of file + diff --git a/_includes/left_nav.html b/_includes/left_nav.html index 66cc56e26f..273d2cab36 100644 --- a/_includes/left_nav.html +++ b/_includes/left_nav.html @@ -1,43 +1,151 @@ - {% if page.top_nav_section %} - - {% assign left_nav_sections = (site.nav_sections | where: "top_nav", page.top_nav_section) %} - {% assign top_section_pages = (site.pages | where: "top_nav_section", page.top_nav_section) %} - - {% for left_section in left_nav_sections %} - - {% assign section_pages = ((top_section_pages | where: "nav_section", left_section.code) | sort:"pid") %} - -
{{left_section.name}}
- - - {% endfor %} - -{% endif %} \ No newline at end of file + \ No newline at end of file diff --git a/_includes/main_nav.html b/_includes/main_nav.html index a4559adad5..704a9d6a6d 100644 --- a/_includes/main_nav.html +++ b/_includes/main_nav.html @@ -50,6 +50,7 @@
  • Modules
  • +
  • Prebid.js for video
  • Prebid Server
  • Prebid Mobile for apps
  • For Ad Ops
  • diff --git a/_includes/nav.html b/_includes/nav.html new file mode 100644 index 0000000000..87ac95bd8d --- /dev/null +++ b/_includes/nav.html @@ -0,0 +1,138 @@ + + + + diff --git a/_includes/partners.html b/_includes/partners.html new file mode 100644 index 0000000000..511b824dc4 --- /dev/null +++ b/_includes/partners.html @@ -0,0 +1,118 @@ + + +
    + +

    Prebid.org Founding Members

    + + +
    + + +

    Prebid.org Leading Members

    + +
    + + +

    Prebid.org Technology Partner Members

    + +
    + + +

    Prebid.org Publisher Members

    + +
    + + +

    Prebid.org Community Members

    + + +
    + + + +

    Prebid.js Bidding Partners

    + + +
    + +
    diff --git a/_includes/sandbox/pb-api-test.html b/_includes/sandbox/pb-api-test.html new file mode 100644 index 0000000000..9441a19f24 --- /dev/null +++ b/_includes/sandbox/pb-api-test.html @@ -0,0 +1,19 @@ + + + + +
    + + + {% assign arrCategories = site.data.pb-api %} + +
      + {% for thisCat in arrCategories %} + +
    • {{thisCat.catName}}
    • + + {% endfor %} +
    + +
    + diff --git a/_includes/send-all-bids-keyword-targeting.md b/_includes/send-all-bids-keyword-targeting.md index ff6fe88bf0..ff36d33d72 100644 --- a/_includes/send-all-bids-keyword-targeting.md +++ b/_includes/send-all-bids-keyword-targeting.md @@ -1,5 +1,9 @@ -{: .alert.alert-info :} -**Important:** DFP has a key-value key character [limit](https://support.google.com/dfp_premium/answer/1628457?hl=en#Key-values) of up to **20 characters**. Some of the keys without truncation will exceed 20 chars. Prebid.js automatically truncates the key length to 20 characters. For example, `hb_adid_longBidderName` is truncated to `hb_adid_longBidderNa` (`me` is truncated). Note that the key is case-sensitive. To get the exact key-value keys for each bidder, find them at [Bidder Params](/dev-docs/bidders.html). +{% capture infoNote %} +**Important:** Google Ad Manager has a key-value key character [limit](https://support.google.com/dfp_premium/answer/1628457?hl=en#Key-values) of up to **20 characters**. Some of the keys without truncation will exceed 20 chars. Prebid.js automatically truncates the key length to 20 characters. For example, `hb_adid_longBidderName` is truncated to `hb_adid_longBidderNa` (`me` is truncated). Note that the key is case-sensitive. To get the exact key-value keys for each bidder, find them at [Bidder Params](/dev-docs/bidders.html). +{% endcapture %} + +{% include alerts/alert_note.html content=infoNote %} + {: .table .table-bordered .table-striped } | Default Key | Scope | Description | Example | diff --git a/_includes/video/head.html b/_includes/video/head.html new file mode 100644 index 0000000000..0db875e545 --- /dev/null +++ b/_includes/video/head.html @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-bc.html b/_includes/video/pb-is-bc.html new file mode 100644 index 0000000000..cfee94f379 --- /dev/null +++ b/_includes/video/pb-is-bc.html @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-br.html b/_includes/video/pb-is-br.html new file mode 100644 index 0000000000..e393a98d02 --- /dev/null +++ b/_includes/video/pb-is-br.html @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-fp.html b/_includes/video/pb-is-fp.html new file mode 100644 index 0000000000..f3d9ee62f8 --- /dev/null +++ b/_includes/video/pb-is-fp.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-jw01.html b/_includes/video/pb-is-jw01.html new file mode 100644 index 0000000000..1e5df51c45 --- /dev/null +++ b/_includes/video/pb-is-jw01.html @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-jw02.html b/_includes/video/pb-is-jw02.html new file mode 100644 index 0000000000..f271509133 --- /dev/null +++ b/_includes/video/pb-is-jw02.html @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-jw03.html b/_includes/video/pb-is-jw03.html new file mode 100644 index 0000000000..a0acb7d9aa --- /dev/null +++ b/_includes/video/pb-is-jw03.html @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-kl.html b/_includes/video/pb-is-kl.html new file mode 100644 index 0000000000..4245bbc02e --- /dev/null +++ b/_includes/video/pb-is-kl.html @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-ol.html b/_includes/video/pb-is-ol.html new file mode 100644 index 0000000000..43b11adf07 --- /dev/null +++ b/_includes/video/pb-is-ol.html @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-is-vjs.html b/_includes/video/pb-is-vjs.html new file mode 100644 index 0000000000..400c61a54e --- /dev/null +++ b/_includes/video/pb-is-vjs.html @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-lf-fw.html b/_includes/video/pb-lf-fw.html new file mode 100644 index 0000000000..1ae751110a --- /dev/null +++ b/_includes/video/pb-lf-fw.html @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-os-dfp.html b/_includes/video/pb-os-dfp.html new file mode 100644 index 0000000000..d0047fdd13 --- /dev/null +++ b/_includes/video/pb-os-dfp.html @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pb-os-nas.html b/_includes/video/pb-os-nas.html new file mode 100644 index 0000000000..bb86cd0da8 --- /dev/null +++ b/_includes/video/pb-os-nas.html @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pbs-br.html b/_includes/video/pbs-br.html new file mode 100644 index 0000000000..73b7a793c0 --- /dev/null +++ b/_includes/video/pbs-br.html @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pbs-jw01.html b/_includes/video/pbs-jw01.html new file mode 100644 index 0000000000..5aa9e238a7 --- /dev/null +++ b/_includes/video/pbs-jw01.html @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pbs-jw02.html b/_includes/video/pbs-jw02.html new file mode 100644 index 0000000000..cda3eb9dc7 --- /dev/null +++ b/_includes/video/pbs-jw02.html @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pbs-jw03.html b/_includes/video/pbs-jw03.html new file mode 100644 index 0000000000..92a8dcf9d5 --- /dev/null +++ b/_includes/video/pbs-jw03.html @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pbs-jw04.html b/_includes/video/pbs-jw04.html new file mode 100644 index 0000000000..ecbf4ef633 --- /dev/null +++ b/_includes/video/pbs-jw04.html @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pbs-kl.html b/_includes/video/pbs-kl.html new file mode 100644 index 0000000000..4d8ae8d527 --- /dev/null +++ b/_includes/video/pbs-kl.html @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pbs-oy.html b/_includes/video/pbs-oy.html new file mode 100644 index 0000000000..00d9de4430 --- /dev/null +++ b/_includes/video/pbs-oy.html @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/video/pbs-vjs.html b/_includes/video/pbs-vjs.html new file mode 100644 index 0000000000..43d4044dd6 --- /dev/null +++ b/_includes/video/pbs-vjs.html @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + {% if page.head_title %} + {{page.head_title}} + {% else %} + {{page.title}} for Header Bidding + {% endif %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_layouts/bidder.html b/_layouts/bidder.html index fe7b0b761e..bb30c559f1 100644 --- a/_layouts/bidder.html +++ b/_layouts/bidder.html @@ -1,44 +1,106 @@ {% include head.html %} -{% include main_nav.html %} +{% include nav.html %} + +
    + + + +
    + +
    + + + + +
    + + {% if page.is_full_screen %} + {{content}} + {% else %} + +
    + +
    +
    + +

    {{ page.title }}

    + + {% if page.s2s_only == true %} +
    +

    Note:

    This is a S2S adapter only. +
    + {% endif %} + +

    Features

    + + + + + +
    Bidder Code{{ page.biddercode }}Prebid.org Member{% if page.prebid_member == true %}yes{% else %}no{% endif %}
    Media Typesdisplay{% if page.media_types contains 'video' %}, video{% endif %}{% if page.media_types contains 'native' %}, native{% endif %}GDPR Support{% if page.gdpr_supported == true %}yes{% else %}no{% endif %}
    User IDs{% if page.userIds and page.userIds != '' %}{{page.userIds}}{% else %}none{% endif %}COPPA Support{% if page.coppa_supported == true %}yes{% else %}no{% endif %}
    + +

    "Send All Bids" Ad Server Keys

    + +These are the bidder-specific keys that would be targeted within GAM in a Send-All-Bids scenario. GAM truncates keys to 20 characters. + + + + + +
    {{ "hb_pb_" | append: page.biddercode | slice: 0,20 }}{{ "hb_bidder_" | append: page.biddercode | slice: 0,20 }}{{ "hb_adid_" | append: page.biddercode | slice: 0,20 }}
    {{ "hb_size_" | append: page.biddercode | slice: 0,20 }}{{ "hb_source_" | append: page.biddercode | slice: 0,20 }}{{ "hb_format_" | append: page.biddercode | slice: 0,20 }}
    {{ "hb_cache_host_" | append: page.biddercode | slice: 0,20 }}{{ "hb_cache_id_" | append: page.biddercode | slice: 0,20 }}{{ "hb_uuid_" | append: page.biddercode | slice: 0,20 }}
    - {% if page.is_full_screen %} - {{content}} - {% else %} +{% if page.prevBiddercode %} +This bidder previously had a bidder code of `{{ page.prevBiddercode }}`, but prefers new configurations to use `{{ page.biddercode }}`. +{% endif %} -
    +{% if page.bidder_supports_deals != false %} +

    "Deal ID" Ad Server Key

    +{{ "hb_deal_" | append: page.biddercode | slice: 0,20 }} +{% endif %} - {% include left_nav.html %} + {{content}} + +
    + + {% if page.show_disqus %} + {% include disqus_addon.html %} + {% endif %} +
    + +
    + + {% endif %} -
    -
    -

    {{ page.title }}

    +
    -

    Bidder Code

    + +
    + +
    + + +

    +
    - {{ page.biddercode }} - {% if page.biddercode_longer_than_12 != true %} -

    Send All Bids Ad Server Keys

    - hb_pb_{{ page.biddercode }} - hb_adid_{{ page.biddercode }} - hb_size_{{ page.biddercode }} - {% endif %} + {% if page.title != "Credits" %} + {% if page.layout != "home" %} + {% include footer.html %} + {% endif %} + {% endif %} + +
    - {{content}} -
    - {% if page.show_disqus %} - {% include disqus_addon.html %} - {% endif %} + + + -
    -
    - {% endif %} - -{% include foot.html %} \ No newline at end of file diff --git a/_layouts/blog.html b/_layouts/blog.html index 15fb8109ea..8ca7829b8d 100644 --- a/_layouts/blog.html +++ b/_layouts/blog.html @@ -1,5 +1,6 @@ {% include head.html %} -{% include main_nav.html %} + +{% include nav.html %}
    @@ -11,4 +12,4 @@
    -{% include foot.html %} \ No newline at end of file +{% include footer.html %} diff --git a/_layouts/example.html b/_layouts/example.html index b8cba45189..670c1cd7dc 100644 --- a/_layouts/example.html +++ b/_layouts/example.html @@ -1,95 +1,93 @@ {% include head.html %} -{% include main_nav.html %} -
    - -
    - - -
    -
    - {% include left_nav.html %} -
    -
    - - -
    -
    +{% include nav.html %} - -
    -
    - {% include example_tab.html %} -
    -
    +
    + +
    + +
    + + + + - -
    -
    - -

    {{ page.description }}

    - - {% if page.why_link %} -

    Who should use this example:

    - - {% endif %} - -

    This page contains:

    - -

    -

      - {% for about_bullet in page.about %} -
    • {{ about_bullet}}
    • - {% endfor %} -
    -

    - -

    - On the JSFiddle example below, click Result to see the result. -

    - -

    - Click Edit in JSFiddle to open the example in a new tab. -

    - -

    - For tips and troubleshooting info, see: -

    -

    -
    -
    - -
    - -
    - - -
    - {% include dev-docs/build-from-source-warning.md %} -
    - -
    - -
    - - -
    - -
    - -
    - -
    - -
    - -{% include foot.html %} \ No newline at end of file + +
    + + +

    {{ page.description }}

    + + {% if page.why_link %} +

    Who should use this example:

    + + {% endif %} + +

    This page contains:

    + +

    +

      + {% for about_bullet in page.about %} +
    • {{ about_bullet}}
    • + {% endfor %} +
    +

    + +

    + On the JSFiddle example below, click Result to see the result. +

    + +

    + Click Edit in JSFiddle to open the example in a new tab. +

    + +

    + For tips and troubleshooting info, see: +

    +

    + + +
    + + +
    + {% include dev-docs/build-from-source-warning.md %} +
    + +
    + +
    + + +
    +

    (Sorry, jsfiddle code examples aren't available with your cookie privacy settings.)

    +

    Cookie Settings


    + +
    + +
    + +
    + + +
    +
    +
    + + +{% include footer.html %} diff --git a/_layouts/fourofour.html b/_layouts/fourofour.html new file mode 100644 index 0000000000..0b6367ffa1 --- /dev/null +++ b/_layouts/fourofour.html @@ -0,0 +1,11 @@ +{% include head.html %} + +{% include nav.html %} + +
    + +

    404

    +

    The page you are looking for cannot be found or does not exist.

    +

    + +
    \ No newline at end of file diff --git a/_layouts/home.html b/_layouts/home.html old mode 100755 new mode 100644 index 9759972deb..4f6aff783e --- a/_layouts/home.html +++ b/_layouts/home.html @@ -1,32 +1,181 @@ {% include head.html %} -{% include main_nav.html %} -
    -
    -

    {{site.name}}

    +{% include nav.html %} -
    -
    -

    {{page.description}}

    -
    -
    +
    + +
    + +

    {% include footer.html %}

    +
    + +
    + +
    +
    +

    Header bidding unwrapped

    +

    Earn more from your advertising with Prebid, a transparent, open-source solution that increases advertiser demand while maintaining a fast and responsive user experience.

    +
    +
    + + +
    + + + {% assign arrMsgs = site.data.message %} + {% assign lastMsg = arrMsgs.last %} + {% assign lastMsgSize = lastMsg.messageText | size %} +
    + + {% if lastMsgSize > 1 %} +
    + +

    {{lastMsg.messageText}}

    + +
    + {% else %} +
     
    + {% endif %} +
    + + +
    + +

    The Benefits of Using Prebid

    + +
    +
    +
    +
    + +
    +
    +
    Maximize Earnings
    +
    Bring additional advertiser demand into your ad server, ensuring you get the best possible price for your inventory.
    +
    +
    +
    +
    + +
    +
    +
    Use it Everywhere
    +
    Apply header bidding to the most popular platforms and formats, including web, mobile app, video, native, AMP, and server-to-server.
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    Get Started Quickly
    +
    Follow simple step-by-step instructions to download, integrate, and configure header bidding with Prebid.
    +
    +
    +
    +
    + +
    +
    +
    Join The Community
    +
    Become part of our active community of advertising technology experts, where you can quickly resolve issues and contribute to the evolution of the leading header.
    +
    +
    +
    +
    + + +
    + + + + + + +
    + + +
    + + + + + +
    + + - Get Started + + + + + + + - - -
    -
    - -
    -
    -
    - {{content}} -
    - -
    -
    - -{% include foot.html %} \ No newline at end of file + diff --git a/_layouts/page.html b/_layouts/page.html deleted file mode 100644 index 74cab5b6de..0000000000 --- a/_layouts/page.html +++ /dev/null @@ -1,31 +0,0 @@ -{% include head.html %} -{% include main_nav.html %} - -
    - - {% if page.is_full_screen %} - {{content}} - {% else %} - -
    - -
    -
    - {% include left_nav.html %} -
    -
    - -
    - {{content}} -
    -
    - - {% endif %} - - {% if page.show_disqus %} - {% include disqus_addon.html %} - {% endif %} - -
    - -{% include foot.html %} \ No newline at end of file diff --git a/_layouts/page_v2.html b/_layouts/page_v2.html new file mode 100644 index 0000000000..08c97baf8f --- /dev/null +++ b/_layouts/page_v2.html @@ -0,0 +1,61 @@ +{% include head.html %} + +{% include nav.html %} + +
    + +
    + +
    + + + + +
    + + {{ content }} + + {% if page.description == "Partners" %} + {% include partners.html %} + {% endif %} + +
    + +
    + +
    + +
    + +

    +
    + +{% if page.title != "Credits" %} + {% if page.layout != "home" %} + {% include footer.html %} + {% endif %} +{% endif %} + + + + + + + + + + + diff --git a/_layouts/post.html b/_layouts/post.html index 2b26246e1b..a60d357421 100644 --- a/_layouts/post.html +++ b/_layouts/post.html @@ -1,22 +1,20 @@ {% include head.html %} -{% include main_nav.html %} -
    -
    -

    Prebid.org Blog

    -

    A collection of helpful tips for implementing header bidding with.

    -
    -
    +{% include nav.html %}
    -
    -
    -

    {{page.title}}

    +
    +
    +
    +

    {{ page.date | date: '%B %d, %Y' }}

    +
    +

    {{page.title}}

    {{content}} +
    - -
    - - {% include disqus_addon.html %} - -
    - -
    -
    - -
    Related Posts
    - -
    -
    -{% include foot.html %} \ No newline at end of file +{% include footer.html %} diff --git a/_layouts/test.html b/_layouts/test.html new file mode 100644 index 0000000000..945088e888 --- /dev/null +++ b/_layouts/test.html @@ -0,0 +1,89 @@ +{% include head.html %} + +{% include nav.html %} + + +
    + + + +
    + +
    + + + + +
    + + {% if page.is_full_screen %} + {{content}} + {% else %} + +
    + +
    +
    + +

    {{ page.title }}

    + +

    Bidder Code

    + + {% if page.s2s_only == true %} +
    +

    Note:

    This is a S2S adapter only. +
    + {% endif %} + + {{ page.biddercode }} + {% if page.biddercode_longer_than_12 != true %} +

    Send All Bids Ad Server Keys

    + hb_pb_{{ page.biddercode }} + hb_adid_{{ page.biddercode }} + hb_size_{{ page.biddercode }} + {% endif %} + + {{content}} + +
    + + {% if page.show_disqus %} + {% include disqus_addon.html %} + {% endif %} +
    + +
    + + {% endif %} + + +
    + + +
    + +
    + + +

    +
    + + {% if page.title != "Credits" %} + {% if page.layout != "home" %} + {% include footer.html %} + {% endif %} + {% endif %} + +
    + + + + + + + + + + diff --git a/_layouts/video_sample.html b/_layouts/video_sample.html new file mode 100644 index 0000000000..b8163c9c45 --- /dev/null +++ b/_layouts/video_sample.html @@ -0,0 +1,102 @@ +{% if page.videoType == "pb-is-br" %} + {% include /video/pb-is-br.html %} +{% elsif page.videoType == "pb-is-bc" %} + {% include /video/pb-is-bc.html %} +{% elsif page.videoType == "pb-is-fp" %} + {% include /video/pb-is-fp.html %} +{% elsif page.videoType == "pb-is-jw01" %} + {% include /video/pb-is-jw01.html %} +{% elsif page.videoType == "pb-is-jw02" %} + {% include /video/pb-is-jw02.html %} +{% elsif page.videoType == "pb-is-jw03" %} + {% include /video/pb-is-jw03.html %} +{% elsif page.videoType == "pb-is-kl" %} + {% include /video/pb-is-kl.html %} +{% elsif page.videoType == "pb-is-ol" %} + {% include /video/pb-is-ol.html %} +{% elsif page.videoType == "pb-is-vjs" %} + {% include /video/pb-is-vjs.html %} +{% elsif page.videoType == "pbs-br" %} + {% include /video/pbs-br.html %} +{% elsif page.videoType == "pbs-jw01" %} + {% include /video/pbs-jw01.html %} +{% elsif page.videoType == "pbs-jw02" %} + {% include /video/pbs-jw02.html %} +{% elsif page.videoType == "pbs-jw03" %} + {% include /video/pbs-jw03.html %} +{% elsif page.videoType == "pbs-jw04" %} + {% include /video/pbs-jw04.html %} +{% elsif page.videoType == "pbs-kl" %} + {% include /video/pbs-kl.html %} +{% elsif page.videoType == "pbs-oy" %} + {% include /video/pbs-oy.html %} +{% elsif page.videoType == "pbs-vjs" %} + {% include /video/pbs-vjs.html %} +{% elsif page.videoType == "pb-os-dfp" %} + {% include /video/pb-os-dfp.html %} +{% elsif page.videoType == "pb-os-nas" %} + {% include /video/pb-os-nas.html %} +{% elsif page.videoType == "pb-lf-fw" %} + {% include /video/pb-lf-fw.html %} +{% endif %} + + +{% include nav.html %} + +
    + +
    + +
    + + + + +
    + + {{ content }} + + {% if page.description == "Partners" %} + {% include partners.html %} + {% endif %} + +
    + +
    + +
    + +
    + +

    +
    + +{% if page.title != "Credits" %} + {% if page.layout != "home" %} + {% include footer.html %} + {% endif %} +{% endif %} + + + + + + + + + + + diff --git a/_posts/2015-07-20-how-to-simplify-line-items.md b/_posts/2015-07-20-how-to-simplify-line-items.md index 5350bfde31..a8f7edacc4 100644 --- a/_posts/2015-07-20-how-to-simplify-line-items.md +++ b/_posts/2015-07-20-how-to-simplify-line-items.md @@ -9,7 +9,7 @@ permalink: /blog/how-to-simplify-line-item-setup --- -#### Let's do the math: +## Let's do the math: * Per bidder per size: $0.01 increment, capped at $10 => 1000 line items * 10 creative sizes @@ -19,7 +19,7 @@ permalink: /blog/how-to-simplify-line-item-setup
    -#### How to reduce the number of line items for header bidding? +## How to reduce the number of line items for header bidding? > Prebid.js helps you use 1 set of line items for all bidders and all creatives. @@ -33,10 +33,9 @@ By removing the size and bidder dimension, the number of line items now becomes: In this section, we'll learn how to remove the creative size dimension for header bidding. Before, a publisher would have to create different set of line items for different creative sizes. With Prebid.js, a publisher only need to create 1 set of line items for all creative sizes. -Let's first clarify what "different set of line items for different creative sizes" means. In this scenario, a line item's creative is only of one size. In DFP, this looks like: +Let's first clarify what "different set of line items for different creative sizes" means. In this scenario, a line item's creative is only of one size. In Google Ad Manager, this looks like: -{: .pb-md-img :} -![Header Bidding Normal Line Item Creative]({{ site.github.url }}/assets/images/blog/line-item-creative.png) +![Header Bidding Normal Line Item Creative]({{ site.github.url }}/assets/images/blog/line-item-creative.png){: .pb-md-img :} Because a site would have many creative sizes, with this setup you need X number of line item sets for X number of creative sizes. @@ -95,7 +94,7 @@ This simplifies the setup and the right creative (with adId 65432) will get disp #### How about reporting? -It's important to understand the fill rates and CPM from different bidders. Prebid.js therefore passes in `hb_bidder`: bidderCode. This enables DFP to report on query strings. You can therefore run queries like: +It's important to understand the fill rates and CPM from different bidders. Prebid.js therefore passes in `hb_bidder`: bidderCode. This enables Google Ad Manager to report on query strings. You can therefore run queries like: * For bidder X, at what CPM does it fill? * For bidder X, what's the fill rate out of all the winning header bidding bids? diff --git a/_posts/2015-07-25-how-to-reduce-latency-of-header-bidding.md b/_posts/2015-07-25-how-to-reduce-latency-of-header-bidding.md index f36c3f64fd..36d908ddf0 100644 --- a/_posts/2015-07-25-how-to-reduce-latency-of-header-bidding.md +++ b/_posts/2015-07-25-how-to-reduce-latency-of-header-bidding.md @@ -23,7 +23,7 @@ Here're a few screenshots of websites' network calls after implemented header bi ####Blocking Call Screenshot 1 -![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/icons/latency-blocking-1.png) +![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/icons/latency-blocking-1.png){: .pb-lg-img } * All header bidding requests combined took 4 seconds to load! * Users have to wait for 4 seconds of blank space in their web browser before any content can load. @@ -32,7 +32,7 @@ Here're a few screenshots of websites' network calls after implemented header bi ####Blocking Call Screenshot 2 -![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/icons/latency-blocking-2.png) +![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/icons/latency-blocking-2.png){: .pb-lg-img } * All header bidding requests in total took 1 second to load. * However, if all calls are made asynchrnously, latency can be dramatically reduced. @@ -41,7 +41,7 @@ Here're a few screenshots of websites' network calls after implemented header bi ### After prebid.js's acceleration: -![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/icons/latency-concurrent.png) +![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/icons/latency-concurrent.png){: .pb-lg-img } * #####All Pre-bid Calls are made concurrently within 100ms. diff --git a/_posts/2015-08-12-how-many-bidders-for-header-bidding.md b/_posts/2015-08-12-how-many-bidders-for-header-bidding.md index 79dd2919e4..a39d367ddf 100644 --- a/_posts/2015-08-12-how-many-bidders-for-header-bidding.md +++ b/_posts/2015-08-12-how-many-bidders-for-header-bidding.md @@ -22,8 +22,7 @@ Luckily, the publishers using Prebid.js are curious about these questions too. W ### Q1: How is revenue affected by different factors? -{: .pb-lg-img :} -![Prebid Diagram Image]({{ site.github.url }}/assets/images/blog/experiments/revenue.png) +![Prebid Diagram Image]({{ site.github.url }}/assets/images/blog/experiments/revenue.png){: .pb-lg-img :} (_the above data is normalized to CPM = 1 for anonymity_) Revenue is mainly determined by: @@ -51,8 +50,7 @@ Conclusions: ### Q2: How is page content load time affected? -{: .pb-lg-img :} -![Prebid Diagram Image]({{ site.github.url }}/assets/images/blog/experiments/page-load-time.png) +![Prebid Diagram Image]({{ site.github.url }}/assets/images/blog/experiments/page-load-time.png){: .pb-lg-img :} _(The above page has on average 130 HTTP requests, 1.5MB data transferred per refresh)_ @@ -72,8 +70,7 @@ Conclusions: ### Q3: How about ad load time? -{: .pb-lg-img :} -![Prebid Diagram Image]({{ site.github.url }}/assets/images/blog/experiments/ad-load-time.png) +![Prebid Diagram Image]({{ site.github.url }}/assets/images/blog/experiments/ad-load-time.png){: .pb-lg-img :} _(The above page has on average 130 HTTP requests, 1.5MB data transferred per refresh)_ Ad load time measures how long a user has to wait before he/she can see the ad. This is less important than the page's content load time. However, the initial blank space in the ad unit, or the page elements shifting around due to a late ad load, can both demage the user experience. diff --git a/_posts/2015-08-29-what-is-post-bid.md b/_posts/2015-08-29-what-is-post-bid.md index 8edbeeec02..3863258d01 100644 --- a/_posts/2015-08-29-what-is-post-bid.md +++ b/_posts/2015-08-29-what-is-post-bid.md @@ -17,8 +17,7 @@ permalink: /blog/what-is-post-bid In post-bid, the competition among your mediated demand sources compete AFTER your ad server has chosen the winning line item (vs. in header bidding, demand sources compete BEFORE your ad server has seen the impression). In post-bid, your mediated demand sources no longer run daisy chain; they all compete in one single line item based on price. -{: .pb-lg-img :} -![Add Creative to Line Item]({{ site.github.url }}/assets/images/blog/postbid-diagram.png) +![Add Creative to Line Item]({{ site.github.url }}/assets/images/blog/postbid-diagram.png){: .pb-lg-img :} Steps: diff --git a/_posts/2015-10-11-header-bidding-analytics-coming-soon.md b/_posts/2015-10-11-header-bidding-analytics-coming-soon.md index 0252f0b0bf..cc6feb4c02 100644 --- a/_posts/2015-10-11-header-bidding-analytics-coming-soon.md +++ b/_posts/2015-10-11-header-bidding-analytics-coming-soon.md @@ -24,15 +24,15 @@ permalink: /blog/header-bidding-analytics-coming-soon The day starts from making sure the bidders are not generating less revenue: -![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/revenue-by-date.png) +![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/revenue-by-date.png){: .pb-lg-img } Something is not right here - total revenue from yesterday dropped quite a bit. This could be caused by certain bidders were down or experienced technical issues. Let's take a look at the bidder timeout rate: -![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/timeout-by-date.png) +![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/timeout-by-date.png){: .pb-lg-img } Bidder timeout seems okay. The problem might then be caused by bidders' lower bid rate: -![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/bidrate-by-date.png) +![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/bidrate-by-date.png){: .pb-lg-img } Here we go. Bidder 1 and 4 bid much less than usual. You may want to drill down even further - Prebid.js Analytics also provides: @@ -51,7 +51,7 @@ To understand exactly how much time per bidder spent, the Analytics Platform all
    -![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/loadtime-histogram.png) +![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/loadtime-histogram.png){: .pb-lg-img } You might derive: @@ -64,7 +64,7 @@ Similar query for bidders' bid CPM:
    -![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/cpm-histogram.png) +![Blocking Ad Calls 1]({{ site.github.url }}/assets/images/blog/analytics/cpm-histogram.png){: .pb-lg-img } > **Try out the product and explore the demo dashboard here!** This will be the base of your dashboard! diff --git a/_posts/2016-01-11-adjust-bid-price.md b/_posts/2016-01-11-adjust-bid-price.md index 0556d6d42e..502ff0424f 100644 --- a/_posts/2016-01-11-adjust-bid-price.md +++ b/_posts/2016-01-11-adjust-bid-price.md @@ -20,8 +20,7 @@ For example, some bidders returned the bid prices in gross (before any fee is ta This feature allows the publisher to adjust the bidding price before the bids targeting are set on the ad server tag. This is especially relevant for publishers who choose to let prebid.js send only the top winning bid to the ad server, because the price adjustment is done before the top winning bid is chosen. -{: .pb-img.pb-md-img :} -![Prebid.js Adjust Bid Price]({{ site.github.url }}/assets/images/blog/prebid-adjust-price.png) +![Prebid.js Adjust Bid Price]({{ site.github.url }}/assets/images/blog/prebid-adjust-price.png){: .pb-md-img :}
    diff --git a/_posts/2016-03-18-ui-customize-prebid-with-selected-adaptors.md b/_posts/2016-03-18-ui-customize-prebid-with-selected-adaptors.md index 253e6c10f8..f077e912f9 100644 --- a/_posts/2016-03-18-ui-customize-prebid-with-selected-adaptors.md +++ b/_posts/2016-03-18-ui-customize-prebid-with-selected-adaptors.md @@ -9,7 +9,7 @@ permalink: /blog/ui-customize-prebid-with-selected-adaptors ### Background -Since we introduced Prebid.js 8 months ago with only 4 adaptors, more than 15 SSPs have started contributing and maintaining their adaptors through Github. The number of demand adaptors Prebid.js supports has now grown to 17! (more are coming) +Since we introduced Prebid.js 8 months ago with only 4 adaptors, more than 15 SSPs have started contributing and maintaining their adaptors through GitHub. The number of demand adaptors Prebid.js supports has now grown to 17! (more are coming) The average number of adaptors publishers use are between 3 to 8. It makes more sense now for publishers to choose and pick the adaptors they would like prebid.js to include. @@ -29,7 +29,7 @@ A [new UI](/download.html) to customize Prebid.js with the adaptor you choose:
    -![Prebid.js Customize Download UI]({{ site.github.url }}/assets/images/blog/prebid-download-ui.png) +![Prebid.js Customize Download UI]({{ site.github.url }}/assets/images/blog/prebid-download-ui.png){: .pb-lg-img }
    diff --git a/_posts/2016-05-10-dfp-instant-load.md b/_posts/2016-05-10-dfp-instant-load.md deleted file mode 100644 index bc2888daef..0000000000 --- a/_posts/2016-05-10-dfp-instant-load.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -layout: post -title: Load DFP Lightning Fast with Prebid - -description: New way to load DFP lightning fast with Prebid for header bidding. - -permalink: /blog/dfp-instant-load - ---- - -Prebid is introducing a new way of loading GPT and sending GPT requests. Compared to the previous mechanism, the new method has the below advantages. - -
    - -#### Benefits: - -- **Further reduces latency**: the new method loads ads **40-80ms** faster than the old method on fast Internet connections, and more (go up to **150ms** faster) on slower Internet connections, such as those of mobile cellular. Reasons: - - - The new method requires no need to delay the loading of the GPT library. The GPT library can be loaded upfront. - - - Instantly send out ad server ad requests when bids are ready or timeout is hit. No need to wait until the GPT library finishes loading. - -- **Easier implementation and maintenance**: The new method requires no change to your pages' original GPT implementation. It's a simple code snippet insertion now. This can be done by the ad ops teams within a tag management system. - -**Example:** - -GPT Instant Load (right) sends GPT ad requests about 100ms faster than the previous method (left): - -![Prebid Instant Load Benefits]({{ site.github.url }}/assets/images/blog/instant-load/prebid-instant-load.png) - -
    - -#### What is GPT Instant Load? - -GPT Instant Load leverages the `googletag.pubads().disableInitialLoad()`call to disable GPT from sending out ad requests out immediately. This call informs GPT to wait until the first `googletag.pubads().refresh()` is executed. GPT Instant Load triggers the `refresh()` call when all requested bids are back, or when timeout is hit, whichever happens faster. - -{% highlight js %} - -googletag.pubads().disableInitialLoad(); - -pbjs.requestBids({ - bidsBackHandler: function() { - pbjs.setTargetingForGPTAsync(); - googletag.pubads().refresh(); - } -}); - -{% endhighlight %} - -
    - -#### How to implement it? - -Please follow the line by line code example [documented here](/dev-docs/examples/basic-example.html). - -
    - -#### Credits - -Credits to [Bart Van Bragt](https://github.com/BartVB) in the [Github suggestion](https://github.com/prebid/Prebid.js/issues/276). diff --git a/_posts/2016-06-21-enable-deals.md b/_posts/2016-06-21-enable-deals.md index 2f6f7021ee..665496f4d9 100644 --- a/_posts/2016-06-21-enable-deals.md +++ b/_posts/2016-06-21-enable-deals.md @@ -8,7 +8,7 @@ permalink: /blog/enable-deals --- -Prebid is making it easier for publishers to run deals in header bidding! +Prebid is making it easier for publishers to run deals in header bidding!
    @@ -26,6 +26,6 @@ In order to enable deals for prebid, the ad ops setup are slightly different fro + From the ad ops side, you'll create separate orders and line items that target the deal ID key-values. These line items will be at different priorities than your standard header bidding line items. Follow the step by step [Deals Ad Ops Guide](/adops/deals.html) to implement. -+ From the dev side, if your page is using the standard prebid.js key-values, no change is required. ++ From the dev side, if your page is using the standard prebid.js key-values, no change is required. -Note that the initial list of bidders that support deals are: Pubmatic, TripleLift, AppNexus, bRealTime. More bidder adaptors are implementing deals currently. If you'd like to check progress on a bidder, create a [Github issue](https://github.com/prebid/Prebid.js/issues). +Note that the initial list of bidders that support deals are: Pubmatic, TripleLift, AppNexus, bRealTime. More bidder adaptors are implementing deals currently. If you'd like to check progress on a bidder, create a [GitHub issue](https://github.com/prebid/Prebid.js/issues). diff --git a/_posts/2016-08-31-one-year-of-prebid-js.md b/_posts/2016-08-31-one-year-of-prebid-js.md index 08a3e9477c..b8ca0e824f 100644 --- a/_posts/2016-08-31-one-year-of-prebid-js.md +++ b/_posts/2016-08-31-one-year-of-prebid-js.md @@ -6,8 +6,6 @@ description: Looking back on the first year of Prebid.js development permalink: /blog/happy-birthday-prebid-js --- -(_This post originally appeared on the [AppNexus blog](http://blog.appnexus.com/2016/prebid-js-a-year-in-the-life-of-an-open-sourced-ad-tech-project/). It has been edited slightly for clarity._) - ## The Beginning About a year ago, the publisher engineering team at AppNexus began noticing a common problem with some of our forward-looking publishers: many of their websites were taking a long time to load. @@ -30,11 +28,11 @@ And - gulp! - we sent our baby out into the world. ## The Response -The first week after the launch of [Prebid.js](https://github.com/prebid/Prebid.js) we started receiving Github responses from publishers. The responses were positive - several key metrics were telling us publishers were deeply engaged with this product, even from day 1 with the minimum viable product. For example, users on average spent over 5 minutes on the site, and over 35% of the users came back to the [Prebid.org](http://prebid.org) site almost every day during the week - a sign suggesting they were reading and implementing [Prebid.js](https://github.com/prebid/Prebid.js). +The first week after the launch of [Prebid.js](https://github.com/prebid/Prebid.js) we started receiving GitHub responses from publishers. The responses were positive - several key metrics were telling us publishers were deeply engaged with this product, even from day 1 with the minimum viable product. For example, users on average spent over 5 minutes on the site, and over 35% of the users came back to the [Prebid.org](http://prebid.org) site almost every day during the week - a sign suggesting they were reading and implementing [Prebid.js](https://github.com/prebid/Prebid.js). -And the power of open source started kicking in. On Github, publishers started posting comments, fixing bugs, and contributing code, big chunks of code! For example, our first version of [Prebid.js](https://github.com/prebid/Prebid.js) didn't have a popular header bidding partner implemented. Within a week, we received 3 versions of it, submitted by 3 different publishers! +And the power of open source started kicking in. On GitHub, publishers started posting comments, fixing bugs, and contributing code, big chunks of code! For example, our first version of [Prebid.js](https://github.com/prebid/Prebid.js) didn't have a popular header bidding partner implemented. Within a week, we received 3 versions of it, submitted by 3 different publishers! -To date, [our Github repo](https://github.com/prebid/Prebid.js) has received over 485 tickets (we closed 452 of them), 1600 comments, 237 pull requests, 173 forks, and 59 contributors. Over 25 companies have submitted their header bidding adaptors, making [Prebid.js](https://github.com/prebid/Prebid.js) one of the most collaborative ad tech projects. Over 2100 people have given us their emails to stay up to date with the latest news on [Prebid.js](https://github.com/prebid/Prebid.js). In June 2016 alone, we've had over 350 downloads of the custom built version of [Prebid.js](https://github.com/prebid/Prebid.js)! +To date, [our GitHub repo](https://github.com/prebid/Prebid.js) has received over 485 tickets (we closed 452 of them), 1600 comments, 237 pull requests, 173 forks, and 59 contributors. Over 25 companies have submitted their header bidding adaptors, making [Prebid.js](https://github.com/prebid/Prebid.js) one of the most collaborative ad tech projects. Over 2100 people have given us their emails to stay up to date with the latest news on [Prebid.js](https://github.com/prebid/Prebid.js). In June 2016 alone, we've had over 350 downloads of the custom built version of [Prebid.js](https://github.com/prebid/Prebid.js)! We are also happy to see the fast growing adoption of [Prebid.js](https://github.com/prebid/Prebid.js) on publisher pages. According to the third party analytics provider [Builtwith](http://trends.builtwith.com/ads/Prebid), [Prebid.js](https://github.com/prebid/Prebid.js) saw exponential growth in the past year, and has been installed on over 12,000 sites! diff --git a/_posts/2016-12-15-first-open-header-bidding-solution-for-video-now-available-on-prebid-js.md b/_posts/2016-12-15-first-open-header-bidding-solution-for-video-now-available-on-prebid-js.md index 2fcf0d775b..0ac2eeef02 100644 --- a/_posts/2016-12-15-first-open-header-bidding-solution-for-video-now-available-on-prebid-js.md +++ b/_posts/2016-12-15-first-open-header-bidding-solution-for-video-now-available-on-prebid-js.md @@ -14,8 +14,7 @@ The release of PreBid Video marks an important step forward for the open-source In a supply-constrained video ecosystem in which the majority of inventory is monetized via direct sales, PreBid Video offers a programmatic avenue through which publishers can achieve incremental value while still maintaining these guaranteed and/or direct buys. -{: .pb-md-img :} -![PreBid Video Evian]({{ site.github.url }}/assets/images/blog/PreBid-Evian.png) +![PreBid Video Evian]({{ site.github.url }}/assets/images/blog/PreBid-Evian.png){: .pb-md-img :} The true value of an open-sourced project is realized through the ability to incorporate new functionalities, feature development, and bug fixes from a wide contributor network which encompasses diverse expertise and an array of market positions. We encourage and welcome these contributions as we look ahead towards iterative improvement on PreBid Video. With help from the community, we expect to be able to build portfolios of video-capable adapters to match the nearly 40 demand partners integrated today with PreBid display; of video player and adserver integrations with Prebid.js; and, of video-specific formats. diff --git a/_posts/2017-06-08-prebid-releases-outstream-video.md b/_posts/2017-06-08-prebid-releases-outstream-video.md index 55e8b2a4f5..ab466eb97a 100644 --- a/_posts/2017-06-08-prebid-releases-outstream-video.md +++ b/_posts/2017-06-08-prebid-releases-outstream-video.md @@ -10,8 +10,7 @@ permalink: /blog/first-open-header-bidding-solution-for-video-now-available-on-p Late last year, Prebid.js took an important first step beyond traditional display advertising formats with a release of formal [support for instream video](http://productblog.appnexus.com/first-open-header-bidding-solution-for-video-now-available-on-prebid-js/). Today, Prebid.js is doubling down on its focus on formats with the release of outstream video support. -{: .pb-md-img :} -![Outstream Prebid]({{ site.github.url }}/assets/images/blog/outstream-prebid.png) +![Outstream Prebid]({{ site.github.url }}/assets/images/blog/outstream-prebid.png){: .pb-md-img :} Given the high cost of creating true instream video inventory and the inherent constraints that this places on supply, outstream video formats are proving extremely valuable for publishers looking for video monetization alternatives, and for marketers looking for more available video supply. diff --git a/_posts/2017-08-21-prebid-adds-support-for-mobile-app-header-bidding.md b/_posts/2017-08-21-prebid-adds-support-for-mobile-app-header-bidding.md index d429c18619..e446cf98ea 100644 --- a/_posts/2017-08-21-prebid-adds-support-for-mobile-app-header-bidding.md +++ b/_posts/2017-08-21-prebid-adds-support-for-mobile-app-header-bidding.md @@ -8,8 +8,7 @@ permalink: /blog/prebid-adds-support-for-mobile-app-header-bidding Last week, the [prebid-mobile-android](https://github.com/prebid/prebid-mobile-android) and [prebid-mobile-ios](https://github.com/prebid/prebid-mobile-ios) repositories were open-sourced under the Prebid GitHub project. The addition of these libraries marks another milestone for Prebid, representing its first formal steps towards providing an end-to-end open-source header bidding solution for mobile app publishers. -{: .pb-img.pb-md-img :} -![Prebid Mobile - Banner and Interstitial Ads running on iOS]({{site.baseurl}}/assets/images/blog/prebid-mobile-ios-banner-and-interstitial.png) +![Prebid Mobile - Banner and Interstitial Ads running on iOS]({{site.baseurl}}/assets/images/blog/prebid-mobile-ios-banner-and-interstitial.png){: .pb-md-img :} ## Why Should I Be Interested in Prebid Mobile? @@ -25,8 +24,7 @@ Major benefits include: ## How Prebid Mobile Works -{: .pb-img.pb-lg-img :} -![How Prebid Mobile Works]({{site.baseurl}}/assets/images/blog/prebid-mobile-how-it-works.png) +![How Prebid Mobile Works]({{site.baseurl}}/assets/images/blog/prebid-mobile-how-it-works.png){: .pb-lg-img :} ### Initial Setup @@ -34,8 +32,7 @@ Mobile developers register each ad unit with the Prebid Mobile framework (ideall In parallel, the publisher ad ops team will configure Prebid Mobile line items and creatives in the primary ad server targeted to Prebid key/values. This ad ops setup is nearly identical to Prebid.js for web and should be familiar for publishers that have integrated. -{: .pb-img.pb-lg-img :} -![Prebid Server Config Page]({{site.baseurl}}/assets/images/blog/prebid-server-config-page.png) +![Prebid Server Config Page]({{site.baseurl}}/assets/images/blog/prebid-server-config-page.png){: .pb-lg-img :} ### In the App @@ -53,7 +50,7 @@ From there, you can download the Prebid Mobile [Android](https://github.com/preb Moving forward, we will focus on adding additional support in two key areas: -- **Ad types**: The initial Prebid Mobile rollout includes support for banner and interstitial ads running through the DFP and MoPub ad server SDKs. We are working to add support for additional ad types in each of these ad server SDKs, including interstitial video, rewarded video and native ads. +- **Ad types**: The initial Prebid Mobile rollout includes support for banner and interstitial ads running through the Google Ad Manager and MoPub ad server SDKs. We are working to add support for additional ad types in each of these ad server SDKs, including interstitial video, rewarded video and native ads. - **Demand partners**: In parallel, we are working to increase the available set of Prebid Mobile demand partners, focusing initially on mobile-first SSPs as well as the set of demand partners already integrated with Prebid Server for display. diff --git a/_posts/2017-09-11-announcing-prebid-org.md b/_posts/2017-09-11-announcing-prebid-org.md index 4187e419c8..ae8e2d0ffc 100644 --- a/_posts/2017-09-11-announcing-prebid-org.md +++ b/_posts/2017-09-11-announcing-prebid-org.md @@ -6,10 +6,6 @@ description: This week, we're pleased to announce the formation of Prebid.org, a permalink: /blog/announcing-prebid-org --- -(_This post originally appeared on the -[AppNexus blog](http://blog.appnexus.com/2017/prebid-org-explained-interview-michael-richardson/). -It has been lightly edited for clarity._) - This week, we're pleased to announce the formation of [Prebid.org](http://prebid.org/overview/what-is-prebid-org.html): an independent organization dedicated to open source tools that drive @@ -87,8 +83,7 @@ partners can trust that their wrappers are treating them fairly. ## Who is part of Prebid.org? We're launching with [Rubicon Project](https://rubiconproject.com) to -start. They've -[contributed a ton](https://blog.appnexus.com/2017/prebid-expert-series-interview-de-zwart/) +start. They've contributed a ton to Prebid already – some great additions to the project have come from the AppNexus and Rubicon Project teams working together. diff --git a/_posts/2019-01-08-updated-website.md b/_posts/2019-01-08-updated-website.md new file mode 100644 index 0000000000..de8d561b5d --- /dev/null +++ b/_posts/2019-01-08-updated-website.md @@ -0,0 +1,37 @@ +--- +layout: post +title: Prebid.org Website Updated +description: We've given the prebid.org website a new look. +permalink: /blog/updated-website +--- + + +
    + +### Highlights: + +- **Prebid.org is more than Prebid.js**: Prebid.js is likely to remain our most important product, but the new website has placed Prebid SDK and Prebid Server on equal footing with it -- all products are in their own areas now. + +- **Updated Navigation**: The top and left navigation elements have been completely revised. The goal was to have *everything* in the left nav, and the most commonly used pages in the top nav. + +- **Adaptive**: the site should look better than ever on small screens. + +- **Cookie Permission**: you may have noticed already that we have a 'cookie banner' on the bottom asking for permission to set cookies. If you don't grant permission, some content like code examples and videos won't be available. There's also a new [privacy policy](/privacy.html). + +- **New Content**: + - [Prebid Server docs](/prebid-server/prebid-server-overview.html) + - [Product Management Committees](/overview/prebid-management-committees.html) + - [Community Code of Conduct](/overview/community-code-of-conduct.html) + - [Prebid Members and Partners](/partners/partners.html) + - [Prebid Members providing Managed Services](/prebid/managed.html) + - [Format index page](/formats/formats.html) + +### Coming Up: + +We'd like to have your feedback about the changes and any other things you'd like to see. Email us at website@prebid.org. Here's what's on our list so far: + +- Search +- Left nav for blog pages +- Differentiate expanded arrow on left nav +- Clean up extra space at the bottom of the home page + diff --git a/_posts/2019-01-31-prebidjs-2.md b/_posts/2019-01-31-prebidjs-2.md new file mode 100644 index 0000000000..28c81800a2 --- /dev/null +++ b/_posts/2019-01-31-prebidjs-2.md @@ -0,0 +1,21 @@ +--- +layout: post +title: Prebid.js 2.0 Released +description: A minor major version number release +permalink: /blog/pbjs-2 +--- + + +
    + +### Prebid.js 2.0 is a minor major release + +Compared to Prebid.js 1.0, the 2.0 release will be a non-event for most sites. + +The Prebid.js team has adopted a policy of incrementing the major version number whenever there's a 'breaking change' -- a change in behavior we want everyone to be aware of. The idea is that everyone will wonder "what's with the new version", and come looking for blog entries like this. For 2.0, the change is: + +{: .alert.alert-warning :} +The "[limited bid caching](/dev-docs/faq.html#does-prebidjs-cache-bids)" feature is now **off** by default. + +Any publisher that was utilizing this limited form of bid caching may turn it back on. Do this by calling `setConfig()` with the [useBidCache](/dev-docs/publisher-api-reference.html#setConfig-Use-Bid-Cache) option. + diff --git a/_posts/2019-02-12-barcelona.md b/_posts/2019-02-12-barcelona.md new file mode 100644 index 0000000000..88725c280e --- /dev/null +++ b/_posts/2019-02-12-barcelona.md @@ -0,0 +1,32 @@ +--- +layout: post +title: Prebid Leadership Summit in Barcelona on Feb 25th 2019 +description: +permalink: /blog/barcelona-2019 +--- + + +
    + +### Prebid Leadership Summit in Barcelona on Feb 25th 2019 + +Prebid.org invites you to the first Prebid Leadership Summit of the year, taking place in Barcelona during Mobile World Congress on 25 February. The event will take place at [Marfeel’s office](https://goo.gl/maps/4pxcDAaZVk82), from 3:00PM – 6:00PM CET, followed by cocktails until 8:30PM. + +[REGISTER NOW](https://www.eventbrite.com/e/prebid-leadership-summit-mwc-tickets-55547775893) + +**What to expect:** + +The Prebid Leadership Summit is an educational event including overviews, deep dives and conversations about Prebid and its evolution. It’s a chance to explore the latest Prebid solutions and how they work for different kinds of publishers. In particular: + +* Insights from member organizations and premium publishers into current best practices and future plans for Prebid +* Panel discussions on the expansion of header bidding into emerging formats, such as video and native +* Networking opportunities for publishers and Prebid members +* And more! + +**Who should attend?** + +The audience is meant to be Product, Engineering, and AdOps from the Publisher side, so people close to the technology. Space is limited, so be sure to register by 18 February. Feel free to forward to your colleagues. + +Please email event-committee@prebid.org if you have any questions. + +We look forward to seeing you on 25 February! diff --git a/_posts/2019-03-05-marfeel-event.md b/_posts/2019-03-05-marfeel-event.md new file mode 100644 index 0000000000..de40176866 --- /dev/null +++ b/_posts/2019-03-05-marfeel-event.md @@ -0,0 +1,70 @@ +--- +layout: post +title: 4 Ideas from the Barcelona Prebid Summit +description: +permalink: /blog/marfeel-event-2019 +--- + + +
    + +(Originally [posted on Marfeel's site](https://www.marfeel.com/blog/prebid-leadership-summit-2019/), slightly edited for clarity.) + +![Barcelona Summit](/assets/images/blog/2019-03-05-marfeel-event-1.jpg){: .pb-lg-img :} + +As Mobile World Congress has brought the digital publishing world to us this week, we welcomed our industry partner Prebid.org to the Marfeel’s offices to host their third ever Prebid Leadership Summit. Led by the Chair of Prebid, Alexandra Smith, the mission of the day was to understand the changes leading the header bidding industry, and the role of the Prebid organization in driving these changes. + +We were also joined by Remi Boudard from AppNexus, Enrique Blanc from Grupo Zeta, and Lucas Isern and Xavi Beumala from Marfeel, discussing the rise and challenges of adopting server-side header bidding. + +To recap the key points for those that weren’t able to attend, we’ve collated everything publishers need to know. + +Here are the key takeaways: + +## 1. Header Bidding is still in the early-adopter phase, especially for Server Side + +In Europe in 2017, 10-15% of display impressions were generated using header bidding. By the end of 2018, it was closer to 50%. Client-side is still the dominant method of implementation. + +Client-side header bidding was always supposed to be a temporary phenomenon before a rapid migration to server-side. This was due to the impact of page-load on the user experience and the efficiency gains provided by server-side. + +But, there are still limitations that prevent server-side from being rolled out across advertisers. One of the main challenges for adoption is user identification. When you add an additional step for cookie matching, match rates can go down and in turn, impact monetization. Buyers only bid high when they know who the user is, so losing match rates can severely impact monetization for many. Until universal ID solutions come to fruition, the industry is hindered. + +Whats more, web publishers already have working systems for display. There is not currently enough incentive to apply wholesale changes to their approach. They don’t want to spend time and money shifting to a system that will be more advanced and more rigorously industry-tested in a year or so. + +Publishers are waiting for companies and organizations such as Marfeel and Prebid to solve these issues before fully committing to server-side. + +To bridge this gap, Marfeel has a dedicated team that has built our own header bidding solution, now incorporated into the Prebid open-source platform. Working alongside our publishers and the Prebid organization has allowed us to create one of the industry’s first server-side header bidding solutions, that is live across our publishers now. + +## 2. Mobile will be the driving force for mass-adoption + +Most major publishers operate with a hybrid solution, across their formats, such as web, mobile, app, and video. But, running different ad logic for every format is costly and difficult, as is running many SDKs. + +However, mass-adoption of server-side header bidding will require a catalyst that proves its value and utility. For publishers, this revolution will start with mobile, since the Prebid Mobile SDK works hand in hand with Prebid Server. Since Prebid Mobile relies on Prebid Server, publishers will begin to adopt it and consider its use-case for web traffic as well. As more and more publishers adopt, the community will dedicate more time and energy to its development. + +Once mobile proves the market for server-side header bidding, publishers will start to migrate towards it, making Prebid Server become a unified header bidding solution across all formats and devices. + +## 3. Hybrid Models will dominate 2019 but after that… + +No-one at the event was expecting server-side header bidding to be universally adopted by all publishers, across all formats this year. However, the increasing value of this technology and the rise of header bidding in mobile will lead to some major changes. + +It’s expected that, with the adoption of EB (Google’s Exchange Bidding) and Prebid Server that SSPs will eventually become commoditized. This may force them to shift into more technology and service-focused companies, helping publishers navigate the complexities of the ecosystem and providing them with the latest developments. + +Until this mass-migration to Server, publishers are able to incorporate different Prebid implementations to maximize their revenue, which is where the beauty of the platform lies. However, client-side will gradually evolve to be replaced by server-side header bidding and is likely to spread across all formats after a successful initial implementation across mobile. + +## 4. Header Bidding and Machine Learning = Intelligent Ads + +Finally, the results of mass-adoption—though the proving ground of mobile—will enable the development of more advanced systems of header bidding. + +The combination of a unified platform like Prebid Server, alongside machine learning, will allow advertisers to break down impressions and revenue by demand partner, ad format, inventory, and region. Publishers and advertisers will be able to track deal performance across multiple exchanges with a single report to see who is winning, where, and be able to infer why. + +Machine-learning powered algorithms will segment data by size, ad format, and Google Ad Manager ad unit. Automated systems will see through the entire monetization funnel to spot bottlenecks and eliminate inefficiencies in real-time. Effective server-side header bidding will help facilitate the development of these intelligent ads. + +Prebid open-source tech: Deeper development through collaboration +The current challenges of Prebid Server go beyond just cookie matching. They stretch to scaling server infrastructure and building creative caching. However, the accelerated development of the Prebid open source tech will create advancements beyond reduced latency, including intelligent ads and ad delivery that comes directly from Prebid server. + +The collaborative Prebid organization creates independent standards that benefit everyone. There is no bias because the technology is not created or operated by a single content provider and anyone can build on it and improve it. This collaboration is helping define a transparent industry standard that will ease the path for the implementation of header bidding into publisher’s platforms. + +Marfeel’s product manager in our monetization department, Lucas Isern summarized what this ethos will help deliver: + +{% highlight bash %} +‘Prebid Server is not just Prebid.js without its latencies. It’s an opening door to many more improvements and making crucial steps towards getting out of the browser.’ +{% endhighlight %} diff --git a/_posts/2019-05-22-nycevent.md b/_posts/2019-05-22-nycevent.md new file mode 100644 index 0000000000..15f50b7a04 --- /dev/null +++ b/_posts/2019-05-22-nycevent.md @@ -0,0 +1,32 @@ +--- +layout: post +title: Prebid Leadership Summit in New York on June 11th 2019 +description: +permalink: /blog/newyork-event-2019 +--- + + +
    + +### Prebid Leadership Summit in New York on June 11th 2019 + +Prebid.org invites you to attend the Prebid Leadership Summit: NYC on June 11th, 2019, at Xandr's Razzle Dazzle space in NYC, from 1– 4.30pm, followed by networking until 6.30pm. + +[REGISTER NOW](https://www.eventbrite.com/e/june-2019-prebid-leadership-summit-nyc-tickets-61926422597) + +**What to expect:** + +The Prebid Leadership Summit is an educational event including overviews, deep dives and conversations about Prebid and its evolution. It’s a chance to explore the latest Prebid solutions and how they work for different kinds of publishers. In particular: + +* Insights from member organizations and premium publishers into current best practices and future plans for Prebid +* Panel discussions on the expansion of header bidding into emerging formats, such as video and native +* Networking opportunities for publishers and Prebid members +* And more! + +**Who should attend?** + +The audience is meant to be Product, Engineering, and AdOps from the Publisher side, so people close to the technology. Space is limited, so be sure to register. Feel free to forward to your colleagues. + +Please email event-committee@prebid.org if you have any questions. + +We look forward to seeing you at the event! diff --git a/_posts/2019-06-19-londonevent.md b/_posts/2019-06-19-londonevent.md new file mode 100644 index 0000000000..45fa106583 --- /dev/null +++ b/_posts/2019-06-19-londonevent.md @@ -0,0 +1,32 @@ +--- +layout: post +title: Prebid Leadership Summit in London on July 11th 2019 +description: +permalink: /blog/london-event-2019 +--- + + +
    + +### Prebid Leadership Summit in London on July 11th 2019 + +Prebid.org invites you to attend the Prebid Leadership Summit in London on July 11th, 2019. It will be held at the IAB UK venue from 1:30–4:30pm, followed by networking until 6:30pm. + +[REGISTER NOW](https://www.eventbrite.com/e/july-2019-prebid-leadership-summit-london-tickets-63441520295) + +**What to expect:** + +The Prebid Leadership Summit is an educational event including overviews, deep dives and conversations about Prebid and its evolution. It’s a chance to explore the latest Prebid solutions and how they work for different kinds of publishers. In particular: + +* Insights from member organizations and premium publishers into current best practices and future plans for Prebid +* Panel discussions on the expansion of header bidding into emerging formats, such as video and native +* Networking opportunities for publishers and Prebid members +* And more! + +**Who should attend?** + +The audience is meant to be Product, Engineering, and AdOps from the Publisher side, so people close to the technology. Space is limited, so be sure to register. Feel free to forward to your colleagues. + +Please email event-committee@prebid.org if you have any questions. + +We look forward to seeing you at the event! diff --git a/_posts/2019-09-17-sfevent.md b/_posts/2019-09-17-sfevent.md new file mode 100644 index 0000000000..f22a02399d --- /dev/null +++ b/_posts/2019-09-17-sfevent.md @@ -0,0 +1,30 @@ +--- +layout: post +title: Prebid Meetup and Leadership Summit in San Francisco on Oct 24th 2019 +permalink: /blog/2019-sf-event +--- + +
    + +### Prebid Meetup and Leadership Summit in San Francisco on Oct 24th 2019 + +Prebid.org invites you to attend a Prebid Meetup and Leadership Summit in +San Francisco on October 24, 2019. Our event will be at the historic +Merchant’s Exchange Club. There will be presentations from 1.30–4.30pm, +followed by networking and socializing over appetizers and drinks until +6.30pm. Space is limited, so [register now](https://www.eventbrite.com/e/prebid-meetup-and-leadership-summit-san-francisco-october-24-2019-registration-72716612345) to reserve your spot! + +**What To Expect** + +The Prebid Meetup and Leadership Summit is an educational event including +overviews, deep dives and conversations about Prebid, its evolution, roadmap +and vision. It’s a chance to get key insights on the latest Prebid solutions +and how they work for different kinds of publishers. Here are a few things you +can expect from this event: + +- Insights from member organizations and premium publishers into current best practices and future plans for Prebid +- Panel discussions on the expansion of header bidding into emerging formats, such as video and native +- Networking opportunities for publishers and Prebid members +- And more! + +We look forward to seeing you at the event! diff --git a/_posts/2019-10-07-prebid-3.0.md b/_posts/2019-10-07-prebid-3.0.md new file mode 100644 index 0000000000..328336a0bc --- /dev/null +++ b/_posts/2019-10-07-prebid-3.0.md @@ -0,0 +1,144 @@ +--- +layout: post +title: Prebid.js 3.0 Major Release Announcement +description: +permalink: /blog/pbjs-3 +--- + + +
    + +The Prebid core team is excited to announce a major release: Prebid.js 3.0! Here are the main items that will be included in this release: + +* Upgrade all bidder adapters to HTTPS all the time. +* Removal of miscellaneous legacy APIs and functions (should be a minor publisher impact). ([Issue 4118](https://github.com/prebid/Prebid.js/issues/4118)) +* Unbundle PubCommon ID and Unified ID from the User ID module build. +* Fix for `getHighestCpmBids` to not return rendered bids. ([Issue 2959](https://github.com/prebid/Prebid.js/issues/2959)) +* Remove the legacy PBS adapter endpoint support. ([Issue 4172](https://github.com/prebid/Prebid.js/issues/4172)) +* Improve caching behavior if enabled. ([Issue 4148](https://github.com/prebid/Prebid.js/issues/4148)) + +[See the full list](https://github.com/prebid/Prebid.js/labels/3.0%20API%20Change) of items that are associated with the 3.0 release. + +### Publisher-facing API Changes + +Review these changes to make sure you're ready to upgrade to 3.0. + +#### 1. AdUnit.sizes can no longer be used + +To upgrade to Prebid.js 3.0, you'll need to make sure that ad sizes are in mediaTypes.banner.sizes. + +For example, instead of including sizes like this: +``` + var adUnits = [ + { + code: 'test-div', + sizes: [[300,250],[300,600]], +``` +You will need to define adUnits sizes like this: +``` + var adUnits = [ + { + code: 'test-div', + mediaTypes: { + banner: { + sizes: [[300,250],[300,600]] + } + }, +``` + +#### 2. The userSync API no longer supports iframeEnabled, pixelEnabled, or enabledBidders + +There has been a much more flexible syntax for userSync available for a long time, and it's what you need to be using now. See the [Publisher API docs](http://prebid.org/dev-docs/publisher-api-reference.html#setConfig-Configure-User-Syncing) for more details, but here's an example of the improved syntax: + +``` +pbjs.setConfig({ + userSync: { + filterSettings: { + iframe: { + bidders: ['def'], // only this bidder is excluded from syncing iframe pixels, all other bidders are allowed + filter: 'exclude' + }, + image: { + bidders: ['abc', 'def', 'xyz'], // only these 3 bidders are allowed to sync image pixels + filter: 'include' + } + }, + syncsPerBidder: 3, // and no more than 3 syncs at a time + syncDelay: 6000, // 6 seconds after the auction + } +}); +``` + +#### 3. Remove legacy protocol support for Prebid Server + +You will need to check the s2sConfig.endpoint defined for Prebid Server. If it's `/auction`, you'll need to change to `/openrtb2/auction`. No other changes are necessary, but you should test the change with your Prebid Server provider. + +#### 4. pbjs.loadScript() is gone + +If you happen to be using this ancient function, you'll need to find an alternative. + +#### 5. Be aware that the getHighestCpmBids() function will no longer return already-rendered bids + +This is a bug that some of you may have implemented workarounds for. More details [here](https://github.com/prebid/Prebid.js/issues/2959). + +#### 6. The 'min' attribute is no longer used on [pricegranularity](http://prebid.org/dev-docs/publisher-api-reference.html#setConfig-Price-Granularity) + +The existence of the 'min' attribute should not harm existing price granularities, but if anyone has defined price granularities with gaps between the buckets, they won't work anymore. + +For example, this is no longer possible. (It's unclear to us why anyone would need this.) + +``` +const customConfigObject = { + "buckets" : [{ + "min" : 0, + "max" : 5, + "increment" : 0.01 + }, + { + "min" : 5.25, // ignore bids between $5 and $5.25 + "max" : 10, + "increment" : 0.05 + }] +}; +``` + +#### 7. Specifically pull PubCommon ID and Unified ID into your build + +In previous versions, PubCommon ID and Unified ID were automatically +included as part of your Prebid.js build when you included the [userId module](/modules/userId.html). + +This is no longer the case; in order for a Prebid.js package to include PubCommon ID and Unified ID, the `gulp build` command will need to specifically include them. + +#### More details + +Implementation details for all Publisher-facing changes are [here]( +https://github.com/prebid/Prebid.js/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3A%22Pub+API+Change%22+label%3A%223.0+API+Change%22+) + +### Adapter Maintainers Action Required + +If you're responsible for any adapters, be sure you've taken the actions outlined here. + +#### 1. Ensure your bidder doesn't use deprecated functions + +**Referrer detection and related code** + +Bidder adapters should review their implementation to see if they are relying on getting referrer information from updated APIs in `utils.js`. If they are, they should instead use the new [referrer methods](http://prebid.org/dev-docs/bidder-adaptor.html#referrers) on the bid request (`bidderRequest.refererInfo`). + +**Important** +If you are using a deprecated function, your bidder adapter will be removed from the 3.0 branch. You will need to re-submit compliant code. Please target re-submission by *November 1, 2019*. This will give enough time for the core team to review and target the release of mid November. + + +#### 2. Verify bidder supports HTTPS + +We ask all bidder adapters to ensure they are compliant with secure requests to their endpoints (HTTPS). It is already a requirement for bidders to support it on secure pages, so hopefully this will not be a big issue. For the 3.0 release the Prebid core team will automatically update all the endpoints to secure if they are not already updated. + +#### 3. Verify adapter reads sizes from mediaTypes.banner.sizes + +We are telling pubs that they need to confirm that their adUnits define sizes in `mediaTypes.banner.sizes` instead of just `sizes`. + +Adapter code and examples must be updated to reflect this change. + + +### Target release date + +**Mid-November, 2019** diff --git a/_sass/main.scss b/_sass/main.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/about.md b/about.md index b9854ee2f4..11ade8a4a2 100644 --- a/about.md +++ b/about.md @@ -1,11 +1,12 @@ --- -layout: page +layout: page_v2 title: About Prebid.js description: How prebid.js was started and what is it about pid: 60 isNew: false hide: true isNavParent: true +sidebarType: 0 --- + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_adops_2.svg b/assets/images/svg/icn_adops_2.svg new file mode 100644 index 0000000000..5b0ab86928 --- /dev/null +++ b/assets/images/svg/icn_adops_2.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_adops_2_on.svg b/assets/images/svg/icn_adops_2_on.svg new file mode 100644 index 0000000000..b9a2684f5e --- /dev/null +++ b/assets/images/svg/icn_adops_2_on.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_bullhorn.svg b/assets/images/svg/icn_bullhorn.svg new file mode 100644 index 0000000000..0b2fa8493e --- /dev/null +++ b/assets/images/svg/icn_bullhorn.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_developers.svg b/assets/images/svg/icn_developers.svg new file mode 100644 index 0000000000..ccb887337b --- /dev/null +++ b/assets/images/svg/icn_developers.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_developers_2.svg b/assets/images/svg/icn_developers_2.svg new file mode 100644 index 0000000000..e7863130e8 --- /dev/null +++ b/assets/images/svg/icn_developers_2.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_developers_2_on.svg b/assets/images/svg/icn_developers_2_on.svg new file mode 100644 index 0000000000..b1537e4d27 --- /dev/null +++ b/assets/images/svg/icn_developers_2_on.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_getstarted.svg b/assets/images/svg/icn_getstarted.svg new file mode 100644 index 0000000000..a6dd202cd5 --- /dev/null +++ b/assets/images/svg/icn_getstarted.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_getstarted_2.svg b/assets/images/svg/icn_getstarted_2.svg new file mode 100644 index 0000000000..4013000f12 --- /dev/null +++ b/assets/images/svg/icn_getstarted_2.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_getstarted_on.svg b/assets/images/svg/icn_getstarted_on.svg new file mode 100644 index 0000000000..4013000f12 --- /dev/null +++ b/assets/images/svg/icn_getstarted_on.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_hourglass.svg b/assets/images/svg/icn_hourglass.svg new file mode 100644 index 0000000000..54d32e4d15 --- /dev/null +++ b/assets/images/svg/icn_hourglass.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_mappin.svg b/assets/images/svg/icn_mappin.svg new file mode 100644 index 0000000000..7c4d640e95 --- /dev/null +++ b/assets/images/svg/icn_mappin.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + diff --git a/assets/images/svg/icn_monetization.svg b/assets/images/svg/icn_monetization.svg new file mode 100644 index 0000000000..df114c70cb --- /dev/null +++ b/assets/images/svg/icn_monetization.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + diff --git a/assets/images/topgraph.png b/assets/images/topgraph.png new file mode 100644 index 0000000000..f7bd5558e8 Binary files /dev/null and b/assets/images/topgraph.png differ diff --git a/assets/images/troubleshooting/googfc.png b/assets/images/troubleshooting/googfc.png new file mode 100644 index 0000000000..88c44c676f Binary files /dev/null and b/assets/images/troubleshooting/googfc.png differ diff --git a/assets/images/troubleshooting/pb-tsg-check-version.png b/assets/images/troubleshooting/pb-tsg-check-version.png new file mode 100644 index 0000000000..84295c9acc Binary files /dev/null and b/assets/images/troubleshooting/pb-tsg-check-version.png differ diff --git a/assets/images/troubleshooting/pbjs-check-adunits.png b/assets/images/troubleshooting/pbjs-check-adunits.png new file mode 100644 index 0000000000..ffa3244372 Binary files /dev/null and b/assets/images/troubleshooting/pbjs-check-adunits.png differ diff --git a/assets/images/troubleshooting/pbjs-check-config.png b/assets/images/troubleshooting/pbjs-check-config.png new file mode 100644 index 0000000000..b243055cd8 Binary files /dev/null and b/assets/images/troubleshooting/pbjs-check-config.png differ diff --git a/assets/images/troubleshooting/pbjs-list-bidders.png b/assets/images/troubleshooting/pbjs-list-bidders.png new file mode 100644 index 0000000000..96aa20ca18 Binary files /dev/null and b/assets/images/troubleshooting/pbjs-list-bidders.png differ diff --git a/assets/images/troubleshooting/pbjs-verify-ad-server-targeting.png b/assets/images/troubleshooting/pbjs-verify-ad-server-targeting.png new file mode 100644 index 0000000000..ddf37a84b2 Binary files /dev/null and b/assets/images/troubleshooting/pbjs-verify-ad-server-targeting.png differ diff --git a/assets/images/troubleshooting/pbjs-verify-ad-unit-setup.png b/assets/images/troubleshooting/pbjs-verify-ad-unit-setup.png new file mode 100644 index 0000000000..76dfbb717c Binary files /dev/null and b/assets/images/troubleshooting/pbjs-verify-ad-unit-setup.png differ diff --git a/assets/images/troubleshooting/pbjs_debug-console-log.png b/assets/images/troubleshooting/pbjs_debug-console-log.png new file mode 100644 index 0000000000..fd5fdc8672 Binary files /dev/null and b/assets/images/troubleshooting/pbjs_debug-console-log.png differ diff --git a/assets/js/OLDBOOTSTRAP/bootstrap.js b/assets/js/OLDBOOTSTRAP/bootstrap.js new file mode 100644 index 0000000000..8a2e99a535 --- /dev/null +++ b/assets/js/OLDBOOTSTRAP/bootstrap.js @@ -0,0 +1,2377 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ + +if (typeof jQuery === 'undefined') { + throw new Error('Bootstrap\'s JavaScript requires jQuery') +} + ++function ($) { + 'use strict'; + var version = $.fn.jquery.split(' ')[0].split('.') + if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) { + throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') + } +}(jQuery); + +/* ======================================================================== + * Bootstrap: transition.js v3.3.7 + * http://getbootstrap.com/javascript/#transitions + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) + // ============================================================ + + function transitionEnd() { + var el = document.createElement('bootstrap') + + var transEndEventNames = { + WebkitTransition : 'webkitTransitionEnd', + MozTransition : 'transitionend', + OTransition : 'oTransitionEnd otransitionend', + transition : 'transitionend' + } + + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { end: transEndEventNames[name] } + } + } + + return false // explicit for ie8 ( ._.) + } + + // http://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false + var $el = this + $(this).one('bsTransitionEnd', function () { called = true }) + var callback = function () { if (!called) $($el).trigger($.support.transition.end) } + setTimeout(callback, duration) + return this + } + + $(function () { + $.support.transition = transitionEnd() + + if (!$.support.transition) return + + $.event.special.bsTransitionEnd = { + bindType: $.support.transition.end, + delegateType: $.support.transition.end, + handle: function (e) { + if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) + } + } + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: alert.js v3.3.7 + * http://getbootstrap.com/javascript/#alerts + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // ALERT CLASS DEFINITION + // ====================== + + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.VERSION = '3.3.7' + + Alert.TRANSITION_DURATION = 150 + + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = $(selector === '#' ? [] : selector) + + if (e) e.preventDefault() + + if (!$parent.length) { + $parent = $this.closest('.alert') + } + + $parent.trigger(e = $.Event('close.bs.alert')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + // detach from parent, fire event then clean up data + $parent.detach().trigger('closed.bs.alert').remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent + .one('bsTransitionEnd', removeElement) + .emulateTransitionEnd(Alert.TRANSITION_DURATION) : + removeElement() + } + + + // ALERT PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') + + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + var old = $.fn.alert + + $.fn.alert = Plugin + $.fn.alert.Constructor = Alert + + + // ALERT NO CONFLICT + // ================= + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + // ALERT DATA-API + // ============== + + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: button.js v3.3.7 + * http://getbootstrap.com/javascript/#buttons + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } + + Button.VERSION = '3.3.7' + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state += 'Text' + + if (data.resetText == null) $el.data('resetText', $el[val]()) + + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + $el[val](data[state] == null ? this.options[state] : data[state]) + + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d).prop(d, true) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d).prop(d, false) + } + }, this), 0) + } + + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked')) changed = false + $parent.find('.active').removeClass('active') + this.$element.addClass('active') + } else if ($input.prop('type') == 'checkbox') { + if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false + this.$element.toggleClass('active') + } + $input.prop('checked', this.$element.hasClass('active')) + if (changed) $input.trigger('change') + } else { + this.$element.attr('aria-pressed', !this.$element.hasClass('active')) + this.$element.toggleClass('active') + } + } + + + // BUTTON PLUGIN DEFINITION + // ======================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.button', (data = new Button(this, options))) + + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + var old = $.fn.button + + $.fn.button = Plugin + $.fn.button.Constructor = Button + + + // BUTTON NO CONFLICT + // ================== + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + // BUTTON DATA-API + // =============== + + $(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { + var $btn = $(e.target).closest('.btn') + Plugin.call($btn, 'toggle') + if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) { + // Prevent double click on radios, and the double selections (so cancellation) on checkboxes + e.preventDefault() + // The target component still receive the focus + if ($btn.is('input,button')) $btn.trigger('focus') + else $btn.find('input:visible,button:visible').first().trigger('focus') + } + }) + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: carousel.js v3.3.7 + * http://getbootstrap.com/javascript/#carousel + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CAROUSEL CLASS DEFINITION + // ========================= + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = null + this.sliding = null + this.interval = null + this.$active = null + this.$items = null + + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) + + this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element + .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) + .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) + } + + Carousel.VERSION = '3.3.7' + + Carousel.TRANSITION_DURATION = 600 + + Carousel.DEFAULTS = { + interval: 5000, + pause: 'hover', + wrap: true, + keyboard: true + } + + Carousel.prototype.keydown = function (e) { + if (/input|textarea/i.test(e.target.tagName)) return + switch (e.which) { + case 37: this.prev(); break + case 39: this.next(); break + default: return + } + + e.preventDefault() + } + + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) + + this.interval && clearInterval(this.interval) + + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + + return this + } + + Carousel.prototype.getItemIndex = function (item) { + this.$items = item.parent().children('.item') + return this.$items.index(item || this.$active) + } + + Carousel.prototype.getItemForDirection = function (direction, active) { + var activeIndex = this.getItemIndex(active) + var willWrap = (direction == 'prev' && activeIndex === 0) + || (direction == 'next' && activeIndex == (this.$items.length - 1)) + if (willWrap && !this.options.wrap) return active + var delta = direction == 'prev' ? -1 : 1 + var itemIndex = (activeIndex + delta) % this.$items.length + return this.$items.eq(itemIndex) + } + + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" + if (activeIndex == pos) return this.pause().cycle() + + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) + } + + Carousel.prototype.pause = function (e) { + e || (this.paused = true) + + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + + this.interval = clearInterval(this.interval) + + return this + } + + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } + + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } + + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || this.getItemForDirection(type, $active) + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var that = this + + if ($next.hasClass('active')) return (this.sliding = false) + + var relatedTarget = $next[0] + var slideEvent = $.Event('slide.bs.carousel', { + relatedTarget: relatedTarget, + direction: direction + }) + this.$element.trigger(slideEvent) + if (slideEvent.isDefaultPrevented()) return + + this.sliding = true + + isCycling && this.pause() + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)]) + $nextIndicator && $nextIndicator.addClass('active') + } + + var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid" + if ($.support.transition && this.$element.hasClass('slide')) { + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .one('bsTransitionEnd', function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { + that.$element.trigger(slidEvent) + }, 0) + }) + .emulateTransitionEnd(Carousel.TRANSITION_DURATION) + } else { + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger(slidEvent) + } + + isCycling && this.cycle() + + return this + } + + + // CAROUSEL PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide + + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + var old = $.fn.carousel + + $.fn.carousel = Plugin + $.fn.carousel.Constructor = Carousel + + + // CAROUSEL NO CONFLICT + // ==================== + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + + // CAROUSEL DATA-API + // ================= + + var clickHandler = function (e) { + var href + var $this = $(this) + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 + if (!$target.hasClass('carousel')) return + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false + + Plugin.call($target, options) + + if (slideIndex) { + $target.data('bs.carousel').to(slideIndex) + } + + e.preventDefault() + } + + $(document) + .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) + .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) + + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + Plugin.call($carousel, $carousel.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: collapse.js v3.3.7 + * http://getbootstrap.com/javascript/#collapse + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + +/* jshint latedef: false */ + ++function ($) { + 'use strict'; + + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + + '[data-toggle="collapse"][data-target="#' + element.id + '"]') + this.transitioning = null + + if (this.options.parent) { + this.$parent = this.getParent() + } else { + this.addAriaAndCollapsedClass(this.$element, this.$trigger) + } + + if (this.options.toggle) this.toggle() + } + + Collapse.VERSION = '3.3.7' + + Collapse.TRANSITION_DURATION = 350 + + Collapse.DEFAULTS = { + toggle: true + } + + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return + + var activesData + var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') + + if (actives && actives.length) { + activesData = actives.data('bs.collapse') + if (activesData && activesData.transitioning) return + } + + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + if (actives && actives.length) { + Plugin.call(actives, 'hide') + activesData || actives.data('bs.collapse', null) + } + + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + .addClass('collapsing')[dimension](0) + .attr('aria-expanded', true) + + this.$trigger + .removeClass('collapsed') + .attr('aria-expanded', true) + + this.transitioning = 1 + + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('collapse in')[dimension]('') + this.transitioning = 0 + this.$element + .trigger('shown.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + var scrollSize = $.camelCase(['scroll', dimension].join('-')) + + this.$element + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) + } + + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return + + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var dimension = this.dimension() + + this.$element[dimension](this.$element[dimension]())[0].offsetHeight + + this.$element + .addClass('collapsing') + .removeClass('collapse in') + .attr('aria-expanded', false) + + this.$trigger + .addClass('collapsed') + .attr('aria-expanded', false) + + this.transitioning = 1 + + var complete = function () { + this.transitioning = 0 + this.$element + .removeClass('collapsing') + .addClass('collapse') + .trigger('hidden.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + this.$element + [dimension](0) + .one('bsTransitionEnd', $.proxy(complete, this)) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION) + } + + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + Collapse.prototype.getParent = function () { + return $(this.options.parent) + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') + .each($.proxy(function (i, element) { + var $element = $(element) + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) + }, this)) + .end() + } + + Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { + var isOpen = $element.hasClass('in') + + $element.attr('aria-expanded', isOpen) + $trigger + .toggleClass('collapsed', !isOpen) + .attr('aria-expanded', isOpen) + } + + function getTargetFromTrigger($trigger) { + var href + var target = $trigger.attr('data-target') + || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + + return $(target) + } + + + // COLLAPSE PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.collapse + + $.fn.collapse = Plugin + $.fn.collapse.Constructor = Collapse + + + // COLLAPSE NO CONFLICT + // ==================== + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + // COLLAPSE DATA-API + // ================= + + $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { + var $this = $(this) + + if (!$this.attr('data-target')) e.preventDefault() + + var $target = getTargetFromTrigger($this) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + + Plugin.call($target, option) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: dropdown.js v3.3.7 + * http://getbootstrap.com/javascript/#dropdowns + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle="dropdown"]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.VERSION = '3.3.7' + + function getParent($this) { + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = selector && $(selector) + + return $parent && $parent.length ? $parent : $this.parent() + } + + function clearMenus(e) { + if (e && e.which === 3) return + $(backdrop).remove() + $(toggle).each(function () { + var $this = $(this) + var $parent = getParent($this) + var relatedTarget = { relatedTarget: this } + + if (!$parent.hasClass('open')) return + + if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return + + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this.attr('aria-expanded', 'false') + $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) + }) + } + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $(document.createElement('div')) + .addClass('dropdown-backdrop') + .insertAfter($(this)) + .on('click', clearMenus) + } + + var relatedTarget = { relatedTarget: this } + $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this + .trigger('focus') + .attr('aria-expanded', 'true') + + $parent + .toggleClass('open') + .trigger($.Event('shown.bs.dropdown', relatedTarget)) + } + + return false + } + + Dropdown.prototype.keydown = function (e) { + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return + + var $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + if (!isActive && e.which != 27 || isActive && e.which == 27) { + if (e.which == 27) $parent.find(toggle).trigger('focus') + return $this.trigger('click') + } + + var desc = ' li:not(.disabled):visible a' + var $items = $parent.find('.dropdown-menu' + desc) + + if (!$items.length) return + + var index = $items.index(e.target) + + if (e.which == 38 && index > 0) index-- // up + if (e.which == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 + + $items.eq(index).trigger('focus') + } + + + // DROPDOWN PLUGIN DEFINITION + // ========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.dropdown') + + if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + var old = $.fn.dropdown + + $.fn.dropdown = Plugin + $.fn.dropdown.Constructor = Dropdown + + + // DROPDOWN NO CONFLICT + // ==================== + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + // APPLY TO STANDARD DROPDOWN ELEMENTS + // =================================== + + $(document) + .on('click.bs.dropdown.data-api', clearMenus) + .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: modal.js v3.3.7 + * http://getbootstrap.com/javascript/#modals + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // MODAL CLASS DEFINITION + // ====================== + + var Modal = function (element, options) { + this.options = options + this.$body = $(document.body) + this.$element = $(element) + this.$dialog = this.$element.find('.modal-dialog') + this.$backdrop = null + this.isShown = null + this.originalBodyPad = null + this.scrollbarWidth = 0 + this.ignoreBackdropClick = false + + if (this.options.remote) { + this.$element + .find('.modal-content') + .load(this.options.remote, $.proxy(function () { + this.$element.trigger('loaded.bs.modal') + }, this)) + } + } + + Modal.VERSION = '3.3.7' + + Modal.TRANSITION_DURATION = 300 + Modal.BACKDROP_TRANSITION_DURATION = 150 + + Modal.DEFAULTS = { + backdrop: true, + keyboard: true, + show: true + } + + Modal.prototype.toggle = function (_relatedTarget) { + return this.isShown ? this.hide() : this.show(_relatedTarget) + } + + Modal.prototype.show = function (_relatedTarget) { + var that = this + var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) + + this.$element.trigger(e) + + if (this.isShown || e.isDefaultPrevented()) return + + this.isShown = true + + this.checkScrollbar() + this.setScrollbar() + this.$body.addClass('modal-open') + + this.escape() + this.resize() + + this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) + + this.$dialog.on('mousedown.dismiss.bs.modal', function () { + that.$element.one('mouseup.dismiss.bs.modal', function (e) { + if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true + }) + }) + + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + if (!that.$element.parent().length) { + that.$element.appendTo(that.$body) // don't move modals dom position + } + + that.$element + .show() + .scrollTop(0) + + that.adjustDialog() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + that.enforceFocus() + + var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) + + transition ? + that.$dialog // wait for modal to slide in + .one('bsTransitionEnd', function () { + that.$element.trigger('focus').trigger(e) + }) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + that.$element.trigger('focus').trigger(e) + }) + } + + Modal.prototype.hide = function (e) { + if (e) e.preventDefault() + + e = $.Event('hide.bs.modal') + + this.$element.trigger(e) + + if (!this.isShown || e.isDefaultPrevented()) return + + this.isShown = false + + this.escape() + this.resize() + + $(document).off('focusin.bs.modal') + + this.$element + .removeClass('in') + .off('click.dismiss.bs.modal') + .off('mouseup.dismiss.bs.modal') + + this.$dialog.off('mousedown.dismiss.bs.modal') + + $.support.transition && this.$element.hasClass('fade') ? + this.$element + .one('bsTransitionEnd', $.proxy(this.hideModal, this)) + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : + this.hideModal() + } + + Modal.prototype.enforceFocus = function () { + $(document) + .off('focusin.bs.modal') // guard against infinite focus loop + .on('focusin.bs.modal', $.proxy(function (e) { + if (document !== e.target && + this.$element[0] !== e.target && + !this.$element.has(e.target).length) { + this.$element.trigger('focus') + } + }, this)) + } + + Modal.prototype.escape = function () { + if (this.isShown && this.options.keyboard) { + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { + e.which == 27 && this.hide() + }, this)) + } else if (!this.isShown) { + this.$element.off('keydown.dismiss.bs.modal') + } + } + + Modal.prototype.resize = function () { + if (this.isShown) { + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) + } else { + $(window).off('resize.bs.modal') + } + } + + Modal.prototype.hideModal = function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.$body.removeClass('modal-open') + that.resetAdjustments() + that.resetScrollbar() + that.$element.trigger('hidden.bs.modal') + }) + } + + Modal.prototype.removeBackdrop = function () { + this.$backdrop && this.$backdrop.remove() + this.$backdrop = null + } + + Modal.prototype.backdrop = function (callback) { + var that = this + var animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $(document.createElement('div')) + .addClass('modal-backdrop ' + animate) + .appendTo(this.$body) + + this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { + if (this.ignoreBackdropClick) { + this.ignoreBackdropClick = false + return + } + if (e.target !== e.currentTarget) return + this.options.backdrop == 'static' + ? this.$element[0].focus() + : this.hide() + }, this)) + + if (doAnimate) this.$backdrop[0].offsetWidth // force reflow + + this.$backdrop.addClass('in') + + if (!callback) return + + doAnimate ? + this.$backdrop + .one('bsTransitionEnd', callback) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callback() + + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass('in') + + var callbackRemove = function () { + that.removeBackdrop() + callback && callback() + } + $.support.transition && this.$element.hasClass('fade') ? + this.$backdrop + .one('bsTransitionEnd', callbackRemove) + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : + callbackRemove() + + } else if (callback) { + callback() + } + } + + // these following methods are used to handle overflowing modals + + Modal.prototype.handleUpdate = function () { + this.adjustDialog() + } + + Modal.prototype.adjustDialog = function () { + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight + + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' + }) + } + + Modal.prototype.resetAdjustments = function () { + this.$element.css({ + paddingLeft: '', + paddingRight: '' + }) + } + + Modal.prototype.checkScrollbar = function () { + var fullWindowWidth = window.innerWidth + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 + var documentElementRect = document.documentElement.getBoundingClientRect() + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) + } + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth + this.scrollbarWidth = this.measureScrollbar() + } + + Modal.prototype.setScrollbar = function () { + var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) + this.originalBodyPad = document.body.style.paddingRight || '' + if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) + } + + Modal.prototype.resetScrollbar = function () { + this.$body.css('padding-right', this.originalBodyPad) + } + + Modal.prototype.measureScrollbar = function () { // thx walsh + var scrollDiv = document.createElement('div') + scrollDiv.className = 'modal-scrollbar-measure' + this.$body.append(scrollDiv) + var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth + this.$body[0].removeChild(scrollDiv) + return scrollbarWidth + } + + + // MODAL PLUGIN DEFINITION + // ======================= + + function Plugin(option, _relatedTarget) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.modal') + var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('bs.modal', (data = new Modal(this, options))) + if (typeof option == 'string') data[option](_relatedTarget) + else if (options.show) data.show(_relatedTarget) + }) + } + + var old = $.fn.modal + + $.fn.modal = Plugin + $.fn.modal.Constructor = Modal + + + // MODAL NO CONFLICT + // ================= + + $.fn.modal.noConflict = function () { + $.fn.modal = old + return this + } + + + // MODAL DATA-API + // ============== + + $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { + var $this = $(this) + var href = $this.attr('href') + var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7 + var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) + + if ($this.is('a')) e.preventDefault() + + $target.one('show.bs.modal', function (showEvent) { + if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown + $target.one('hidden.bs.modal', function () { + $this.is(':visible') && $this.trigger('focus') + }) + }) + Plugin.call($target, option, this) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: tooltip.js v3.3.7 + * http://getbootstrap.com/javascript/#tooltip + * Inspired by the original jQuery.tipsy by Jason Frame + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // TOOLTIP PUBLIC CLASS DEFINITION + // =============================== + + var Tooltip = function (element, options) { + this.type = null + this.options = null + this.enabled = null + this.timeout = null + this.hoverState = null + this.$element = null + this.inState = null + + this.init('tooltip', element, options) + } + + Tooltip.VERSION = '3.3.7' + + Tooltip.TRANSITION_DURATION = 150 + + Tooltip.DEFAULTS = { + animation: true, + placement: 'top', + selector: false, + template: '', + trigger: 'hover focus', + title: '', + delay: 0, + html: false, + container: false, + viewport: { + selector: 'body', + padding: 0 + } + } + + Tooltip.prototype.init = function (type, element, options) { + this.enabled = true + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) + this.inState = { click: false, hover: false, focus: false } + + if (this.$element[0] instanceof document.constructor && !this.options.selector) { + throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') + } + + var triggers = this.options.trigger.split(' ') + + for (var i = triggers.length; i--;) { + var trigger = triggers[i] + + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' + var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' + + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + Tooltip.prototype.getDefaults = function () { + return Tooltip.DEFAULTS + } + + Tooltip.prototype.getOptions = function (options) { + options = $.extend({}, this.getDefaults(), this.$element.data(), options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay, + hide: options.delay + } + } + + return options + } + + Tooltip.prototype.getDelegateOptions = function () { + var options = {} + var defaults = this.getDefaults() + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] != value) options[key] = value + }) + + return options + } + + Tooltip.prototype.enter = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true + } + + if (self.tip().hasClass('in') || self.hoverState == 'in') { + self.hoverState = 'in' + return + } + + clearTimeout(self.timeout) + + self.hoverState = 'in' + + if (!self.options.delay || !self.options.delay.show) return self.show() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + Tooltip.prototype.isInStateTrue = function () { + for (var key in this.inState) { + if (this.inState[key]) return true + } + + return false + } + + Tooltip.prototype.leave = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false + } + + if (self.isInStateTrue()) return + + clearTimeout(self.timeout) + + self.hoverState = 'out' + + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + Tooltip.prototype.show = function () { + var e = $.Event('show.bs.' + this.type) + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) + if (e.isDefaultPrevented() || !inDom) return + var that = this + + var $tip = this.tip() + + var tipId = this.getUID(this.type) + + this.setContent() + $tip.attr('id', tipId) + this.$element.attr('aria-describedby', tipId) + + if (this.options.animation) $tip.addClass('fade') + + var placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + var autoToken = /\s?auto?\s?/i + var autoPlace = autoToken.test(placement) + if (autoPlace) placement = placement.replace(autoToken, '') || 'top' + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .addClass(placement) + .data('bs.' + this.type, this) + + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + this.$element.trigger('inserted.bs.' + this.type) + + var pos = this.getPosition() + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (autoPlace) { + var orgPlacement = placement + var viewportDim = this.getPosition(this.$viewport) + + placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : + placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : + placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : + placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : + placement + + $tip + .removeClass(orgPlacement) + .addClass(placement) + } + + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) + + this.applyPlacement(calculatedOffset, placement) + + var complete = function () { + var prevHoverState = that.hoverState + that.$element.trigger('shown.bs.' + that.type) + that.hoverState = null + + if (prevHoverState == 'out') that.leave(that) + } + + $.support.transition && this.$tip.hasClass('fade') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + } + } + + Tooltip.prototype.applyPlacement = function (offset, placement) { + var $tip = this.tip() + var width = $tip[0].offsetWidth + var height = $tip[0].offsetHeight + + // manually read margins because getBoundingClientRect includes difference + var marginTop = parseInt($tip.css('margin-top'), 10) + var marginLeft = parseInt($tip.css('margin-left'), 10) + + // we must check for NaN for ie 8/9 + if (isNaN(marginTop)) marginTop = 0 + if (isNaN(marginLeft)) marginLeft = 0 + + offset.top += marginTop + offset.left += marginLeft + + // $.fn.offset doesn't round pixel values + // so we use setOffset directly with our own function B-0 + $.offset.setOffset($tip[0], $.extend({ + using: function (props) { + $tip.css({ + top: Math.round(props.top), + left: Math.round(props.left) + }) + } + }, offset), 0) + + $tip.addClass('in') + + // check to see if placing tip in new offset caused the tip to resize itself + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + } + + var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) + + if (delta.left) offset.left += delta.left + else offset.top += delta.top + + var isVertical = /top|bottom/.test(placement) + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' + + $tip.offset(offset) + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) + } + + Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { + this.arrow() + .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') + .css(isVertical ? 'top' : 'left', '') + } + + Tooltip.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + + $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) + $tip.removeClass('fade in top bottom left right') + } + + Tooltip.prototype.hide = function (callback) { + var that = this + var $tip = $(this.$tip) + var e = $.Event('hide.bs.' + this.type) + + function complete() { + if (that.hoverState != 'in') $tip.detach() + if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. + that.$element + .removeAttr('aria-describedby') + .trigger('hidden.bs.' + that.type) + } + callback && callback() + } + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + $tip.removeClass('in') + + $.support.transition && $tip.hasClass('fade') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + + this.hoverState = null + + return this + } + + Tooltip.prototype.fixTitle = function () { + var $e = this.$element + if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') + } + } + + Tooltip.prototype.hasContent = function () { + return this.getTitle() + } + + Tooltip.prototype.getPosition = function ($element) { + $element = $element || this.$element + + var el = $element[0] + var isBody = el.tagName == 'BODY' + + var elRect = el.getBoundingClientRect() + if (elRect.width == null) { + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) + } + var isSvg = window.SVGElement && el instanceof window.SVGElement + // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. + // See https://github.com/twbs/bootstrap/issues/20280 + var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null + + return $.extend({}, elRect, scroll, outerDims, elOffset) + } + + Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } + + } + + Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { + var delta = { top: 0, left: 0 } + if (!this.$viewport) return delta + + var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 + var viewportDimensions = this.getPosition(this.$viewport) + + if (/right|left/.test(placement)) { + var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll + var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight + if (topEdgeOffset < viewportDimensions.top) { // top overflow + delta.top = viewportDimensions.top - topEdgeOffset + } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow + delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset + } + } else { + var leftEdgeOffset = pos.left - viewportPadding + var rightEdgeOffset = pos.left + viewportPadding + actualWidth + if (leftEdgeOffset < viewportDimensions.left) { // left overflow + delta.left = viewportDimensions.left - leftEdgeOffset + } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow + delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset + } + } + + return delta + } + + Tooltip.prototype.getTitle = function () { + var title + var $e = this.$element + var o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + Tooltip.prototype.getUID = function (prefix) { + do prefix += ~~(Math.random() * 1000000) + while (document.getElementById(prefix)) + return prefix + } + + Tooltip.prototype.tip = function () { + if (!this.$tip) { + this.$tip = $(this.options.template) + if (this.$tip.length != 1) { + throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') + } + } + return this.$tip + } + + Tooltip.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) + } + + Tooltip.prototype.enable = function () { + this.enabled = true + } + + Tooltip.prototype.disable = function () { + this.enabled = false + } + + Tooltip.prototype.toggleEnabled = function () { + this.enabled = !this.enabled + } + + Tooltip.prototype.toggle = function (e) { + var self = this + if (e) { + self = $(e.currentTarget).data('bs.' + this.type) + if (!self) { + self = new this.constructor(e.currentTarget, this.getDelegateOptions()) + $(e.currentTarget).data('bs.' + this.type, self) + } + } + + if (e) { + self.inState.click = !self.inState.click + if (self.isInStateTrue()) self.enter(self) + else self.leave(self) + } else { + self.tip().hasClass('in') ? self.leave(self) : self.enter(self) + } + } + + Tooltip.prototype.destroy = function () { + var that = this + clearTimeout(this.timeout) + this.hide(function () { + that.$element.off('.' + that.type).removeData('bs.' + that.type) + if (that.$tip) { + that.$tip.detach() + } + that.$tip = null + that.$arrow = null + that.$viewport = null + that.$element = null + }) + } + + + // TOOLTIP PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tooltip') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tooltip + + $.fn.tooltip = Plugin + $.fn.tooltip.Constructor = Tooltip + + + // TOOLTIP NO CONFLICT + // =================== + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(jQuery); + +/* ======================================================================== + * Bootstrap: popover.js v3.3.7 + * http://getbootstrap.com/javascript/#popovers + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // POPOVER PUBLIC CLASS DEFINITION + // =============================== + + var Popover = function (element, options) { + this.init('popover', element, options) + } + + if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') + + Popover.VERSION = '3.3.7' + + Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { + placement: 'right', + trigger: 'click', + content: '', + template: '' + }) + + + // NOTE: POPOVER EXTENDS tooltip.js + // ================================ + + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) + + Popover.prototype.constructor = Popover + + Popover.prototype.getDefaults = function () { + return Popover.DEFAULTS + } + + Popover.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + var content = this.getContent() + + $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) + $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events + this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' + ](content) + + $tip.removeClass('fade top bottom left right in') + + // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do + // this manually by checking the contents. + if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() + } + + Popover.prototype.hasContent = function () { + return this.getTitle() || this.getContent() + } + + Popover.prototype.getContent = function () { + var $e = this.$element + var o = this.options + + return $e.attr('data-content') + || (typeof o.content == 'function' ? + o.content.call($e[0]) : + o.content) + } + + Popover.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.arrow')) + } + + + // POPOVER PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.popover') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.popover', (data = new Popover(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.popover + + $.fn.popover = Plugin + $.fn.popover.Constructor = Popover + + + // POPOVER NO CONFLICT + // =================== + + $.fn.popover.noConflict = function () { + $.fn.popover = old + return this + } + +}(jQuery); + +/* ======================================================================== + * Bootstrap: scrollspy.js v3.3.7 + * http://getbootstrap.com/javascript/#scrollspy + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // SCROLLSPY CLASS DEFINITION + // ========================== + + function ScrollSpy(element, options) { + this.$body = $(document.body) + this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) + this.options = $.extend({}, ScrollSpy.DEFAULTS, options) + this.selector = (this.options.target || '') + ' .nav li > a' + this.offsets = [] + this.targets = [] + this.activeTarget = null + this.scrollHeight = 0 + + this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) + this.refresh() + this.process() + } + + ScrollSpy.VERSION = '3.3.7' + + ScrollSpy.DEFAULTS = { + offset: 10 + } + + ScrollSpy.prototype.getScrollHeight = function () { + return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight) + } + + ScrollSpy.prototype.refresh = function () { + var that = this + var offsetMethod = 'offset' + var offsetBase = 0 + + this.offsets = [] + this.targets = [] + this.scrollHeight = this.getScrollHeight() + + if (!$.isWindow(this.$scrollElement[0])) { + offsetMethod = 'position' + offsetBase = this.$scrollElement.scrollTop() + } + + this.$body + .find(this.selector) + .map(function () { + var $el = $(this) + var href = $el.data('target') || $el.attr('href') + var $href = /^#./.test(href) && $(href) + + return ($href + && $href.length + && $href.is(':visible') + && [[$href[offsetMethod]().top + offsetBase, href]]) || null + }) + .sort(function (a, b) { return a[0] - b[0] }) + .each(function () { + that.offsets.push(this[0]) + that.targets.push(this[1]) + }) + } + + ScrollSpy.prototype.process = function () { + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset + var scrollHeight = this.getScrollHeight() + var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height() + var offsets = this.offsets + var targets = this.targets + var activeTarget = this.activeTarget + var i + + if (this.scrollHeight != scrollHeight) { + this.refresh() + } + + if (scrollTop >= maxScroll) { + return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) + } + + if (activeTarget && scrollTop < offsets[0]) { + this.activeTarget = null + return this.clear() + } + + for (i = offsets.length; i--;) { + activeTarget != targets[i] + && scrollTop >= offsets[i] + && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) + && this.activate(targets[i]) + } + } + + ScrollSpy.prototype.activate = function (target) { + this.activeTarget = target + + this.clear() + + var selector = this.selector + + '[data-target="' + target + '"],' + + this.selector + '[href="' + target + '"]' + + var active = $(selector) + .parents('li') + .addClass('active') + + if (active.parent('.dropdown-menu').length) { + active = active + .closest('li.dropdown') + .addClass('active') + } + + active.trigger('activate.bs.scrollspy') + } + + ScrollSpy.prototype.clear = function () { + $(this.selector) + .parentsUntil(this.options.target, '.active') + .removeClass('active') + } + + + // SCROLLSPY PLUGIN DEFINITION + // =========================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.scrollspy') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.scrollspy + + $.fn.scrollspy = Plugin + $.fn.scrollspy.Constructor = ScrollSpy + + + // SCROLLSPY NO CONFLICT + // ===================== + + $.fn.scrollspy.noConflict = function () { + $.fn.scrollspy = old + return this + } + + + // SCROLLSPY DATA-API + // ================== + + $(window).on('load.bs.scrollspy.data-api', function () { + $('[data-spy="scroll"]').each(function () { + var $spy = $(this) + Plugin.call($spy, $spy.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: tab.js v3.3.7 + * http://getbootstrap.com/javascript/#tabs + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // TAB CLASS DEFINITION + // ==================== + + var Tab = function (element) { + // jscs:disable requireDollarBeforejQueryAssignment + this.element = $(element) + // jscs:enable requireDollarBeforejQueryAssignment + } + + Tab.VERSION = '3.3.7' + + Tab.TRANSITION_DURATION = 150 + + Tab.prototype.show = function () { + var $this = this.element + var $ul = $this.closest('ul:not(.dropdown-menu)') + var selector = $this.data('target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + if ($this.parent('li').hasClass('active')) return + + var $previous = $ul.find('.active:last a') + var hideEvent = $.Event('hide.bs.tab', { + relatedTarget: $this[0] + }) + var showEvent = $.Event('show.bs.tab', { + relatedTarget: $previous[0] + }) + + $previous.trigger(hideEvent) + $this.trigger(showEvent) + + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return + + var $target = $(selector) + + this.activate($this.closest('li'), $ul) + this.activate($target, $target.parent(), function () { + $previous.trigger({ + type: 'hidden.bs.tab', + relatedTarget: $this[0] + }) + $this.trigger({ + type: 'shown.bs.tab', + relatedTarget: $previous[0] + }) + }) + } + + Tab.prototype.activate = function (element, container, callback) { + var $active = container.find('> .active') + var transition = callback + && $.support.transition + && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) + + function next() { + $active + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', false) + + element + .addClass('active') + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + + if (transition) { + element[0].offsetWidth // reflow for transition + element.addClass('in') + } else { + element.removeClass('fade') + } + + if (element.parent('.dropdown-menu').length) { + element + .closest('li.dropdown') + .addClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) + } + + callback && callback() + } + + $active.length && transition ? + $active + .one('bsTransitionEnd', next) + .emulateTransitionEnd(Tab.TRANSITION_DURATION) : + next() + + $active.removeClass('in') + } + + + // TAB PLUGIN DEFINITION + // ===================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tab') + + if (!data) $this.data('bs.tab', (data = new Tab(this))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tab + + $.fn.tab = Plugin + $.fn.tab.Constructor = Tab + + + // TAB NO CONFLICT + // =============== + + $.fn.tab.noConflict = function () { + $.fn.tab = old + return this + } + + + // TAB DATA-API + // ============ + + var clickHandler = function (e) { + e.preventDefault() + Plugin.call($(this), 'show') + } + + $(document) + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: affix.js v3.3.7 + * http://getbootstrap.com/javascript/#affix + * ======================================================================== + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // AFFIX CLASS DEFINITION + // ====================== + + var Affix = function (element, options) { + this.options = $.extend({}, Affix.DEFAULTS, options) + + this.$target = $(this.options.target) + .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) + .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) + + this.$element = $(element) + this.affixed = null + this.unpin = null + this.pinnedOffset = null + + this.checkPosition() + } + + Affix.VERSION = '3.3.7' + + Affix.RESET = 'affix affix-top affix-bottom' + + Affix.DEFAULTS = { + offset: 0, + target: window + } + + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + var targetHeight = this.$target.height() + + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false + + if (this.affixed == 'bottom') { + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' + } + + var initializing = this.affixed == null + var colliderTop = initializing ? scrollTop : position.top + var colliderHeight = initializing ? targetHeight : height + + if (offsetTop != null && scrollTop <= offsetTop) return 'top' + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' + + return false + } + + Affix.prototype.getPinnedOffset = function () { + if (this.pinnedOffset) return this.pinnedOffset + this.$element.removeClass(Affix.RESET).addClass('affix') + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + return (this.pinnedOffset = position.top - scrollTop) + } + + Affix.prototype.checkPositionWithEventLoop = function () { + setTimeout($.proxy(this.checkPosition, this), 1) + } + + Affix.prototype.checkPosition = function () { + if (!this.$element.is(':visible')) return + + var height = this.$element.height() + var offset = this.options.offset + var offsetTop = offset.top + var offsetBottom = offset.bottom + var scrollHeight = Math.max($(document).height(), $(document.body).height()) + + if (typeof offset != 'object') offsetBottom = offsetTop = offset + if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) + if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) + + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) + + if (this.affixed != affix) { + if (this.unpin != null) this.$element.css('top', '') + + var affixType = 'affix' + (affix ? '-' + affix : '') + var e = $.Event(affixType + '.bs.affix') + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + this.affixed = affix + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null + + this.$element + .removeClass(Affix.RESET) + .addClass(affixType) + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') + } + + if (affix == 'bottom') { + this.$element.offset({ + top: scrollHeight - height - offsetBottom + }) + } + } + + + // AFFIX PLUGIN DEFINITION + // ======================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.affix') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.affix', (data = new Affix(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.affix + + $.fn.affix = Plugin + $.fn.affix.Constructor = Affix + + + // AFFIX NO CONFLICT + // ================= + + $.fn.affix.noConflict = function () { + $.fn.affix = old + return this + } + + + // AFFIX DATA-API + // ============== + + $(window).on('load', function () { + $('[data-spy="affix"]').each(function () { + var $spy = $(this) + var data = $spy.data() + + data.offset = data.offset || {} + + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom + if (data.offsetTop != null) data.offset.top = data.offsetTop + + Plugin.call($spy, data) + }) + }) + +}(jQuery); diff --git a/assets/js/OLDBOOTSTRAP/bootstrap.min.js b/assets/js/OLDBOOTSTRAP/bootstrap.min.js new file mode 100644 index 0000000000..9bcd2fccae --- /dev/null +++ b/assets/js/OLDBOOTSTRAP/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
    ',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/assets/js/bootstrap.js b/assets/js/bootstrap.js new file mode 100644 index 0000000000..af3e1bf0b3 --- /dev/null +++ b/assets/js/bootstrap.js @@ -0,0 +1,3944 @@ +/*! + * Bootstrap v4.1.3 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery'), require('popper.js')) : + typeof define === 'function' && define.amd ? define(['exports', 'jquery', 'popper.js'], factory) : + (factory((global.bootstrap = {}),global.jQuery,global.Popper)); +}(this, (function (exports,$,Popper) { 'use strict'; + + $ = $ && $.hasOwnProperty('default') ? $['default'] : $; + Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper; + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + } + + function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } + + return target; + } + + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + subClass.__proto__ = superClass; + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): util.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Util = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Private TransitionEnd Helpers + * ------------------------------------------------------------------------ + */ + var TRANSITION_END = 'transitionend'; + var MAX_UID = 1000000; + var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp) + + function toType(obj) { + return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); + } + + function getSpecialTransitionEndEvent() { + return { + bindType: TRANSITION_END, + delegateType: TRANSITION_END, + handle: function handle(event) { + if ($$$1(event.target).is(this)) { + return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params + } + + return undefined; // eslint-disable-line no-undefined + } + }; + } + + function transitionEndEmulator(duration) { + var _this = this; + + var called = false; + $$$1(this).one(Util.TRANSITION_END, function () { + called = true; + }); + setTimeout(function () { + if (!called) { + Util.triggerTransitionEnd(_this); + } + }, duration); + return this; + } + + function setTransitionEndSupport() { + $$$1.fn.emulateTransitionEnd = transitionEndEmulator; + $$$1.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); + } + /** + * -------------------------------------------------------------------------- + * Public Util Api + * -------------------------------------------------------------------------- + */ + + + var Util = { + TRANSITION_END: 'bsTransitionEnd', + getUID: function getUID(prefix) { + do { + // eslint-disable-next-line no-bitwise + prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here + } while (document.getElementById(prefix)); + + return prefix; + }, + getSelectorFromElement: function getSelectorFromElement(element) { + var selector = element.getAttribute('data-target'); + + if (!selector || selector === '#') { + selector = element.getAttribute('href') || ''; + } + + try { + return document.querySelector(selector) ? selector : null; + } catch (err) { + return null; + } + }, + getTransitionDurationFromElement: function getTransitionDurationFromElement(element) { + if (!element) { + return 0; + } // Get transition-duration of the element + + + var transitionDuration = $$$1(element).css('transition-duration'); + var floatTransitionDuration = parseFloat(transitionDuration); // Return 0 if element or transition duration is not found + + if (!floatTransitionDuration) { + return 0; + } // If multiple durations are defined, take the first + + + transitionDuration = transitionDuration.split(',')[0]; + return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER; + }, + reflow: function reflow(element) { + return element.offsetHeight; + }, + triggerTransitionEnd: function triggerTransitionEnd(element) { + $$$1(element).trigger(TRANSITION_END); + }, + // TODO: Remove in v5 + supportsTransitionEnd: function supportsTransitionEnd() { + return Boolean(TRANSITION_END); + }, + isElement: function isElement(obj) { + return (obj[0] || obj).nodeType; + }, + typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { + for (var property in configTypes) { + if (Object.prototype.hasOwnProperty.call(configTypes, property)) { + var expectedTypes = configTypes[property]; + var value = config[property]; + var valueType = value && Util.isElement(value) ? 'element' : toType(value); + + if (!new RegExp(expectedTypes).test(valueType)) { + throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); + } + } + } + } + }; + setTransitionEndSupport(); + return Util; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): alert.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Alert = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'alert'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.alert'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Selector = { + DISMISS: '[data-dismiss="alert"]' + }; + var Event = { + CLOSE: "close" + EVENT_KEY, + CLOSED: "closed" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + ALERT: 'alert', + FADE: 'fade', + SHOW: 'show' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Alert = + /*#__PURE__*/ + function () { + function Alert(element) { + this._element = element; + } // Getters + + + var _proto = Alert.prototype; + + // Public + _proto.close = function close(element) { + var rootElement = this._element; + + if (element) { + rootElement = this._getRootElement(element); + } + + var customEvent = this._triggerCloseEvent(rootElement); + + if (customEvent.isDefaultPrevented()) { + return; + } + + this._removeElement(rootElement); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._element = null; + }; // Private + + + _proto._getRootElement = function _getRootElement(element) { + var selector = Util.getSelectorFromElement(element); + var parent = false; + + if (selector) { + parent = document.querySelector(selector); + } + + if (!parent) { + parent = $$$1(element).closest("." + ClassName.ALERT)[0]; + } + + return parent; + }; + + _proto._triggerCloseEvent = function _triggerCloseEvent(element) { + var closeEvent = $$$1.Event(Event.CLOSE); + $$$1(element).trigger(closeEvent); + return closeEvent; + }; + + _proto._removeElement = function _removeElement(element) { + var _this = this; + + $$$1(element).removeClass(ClassName.SHOW); + + if (!$$$1(element).hasClass(ClassName.FADE)) { + this._destroyElement(element); + + return; + } + + var transitionDuration = Util.getTransitionDurationFromElement(element); + $$$1(element).one(Util.TRANSITION_END, function (event) { + return _this._destroyElement(element, event); + }).emulateTransitionEnd(transitionDuration); + }; + + _proto._destroyElement = function _destroyElement(element) { + $$$1(element).detach().trigger(Event.CLOSED).remove(); + }; // Static + + + Alert._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var $element = $$$1(this); + var data = $element.data(DATA_KEY); + + if (!data) { + data = new Alert(this); + $element.data(DATA_KEY, data); + } + + if (config === 'close') { + data[config](this); + } + }); + }; + + Alert._handleDismiss = function _handleDismiss(alertInstance) { + return function (event) { + if (event) { + event.preventDefault(); + } + + alertInstance.close(this); + }; + }; + + _createClass(Alert, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }]); + + return Alert; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Alert._jQueryInterface; + $$$1.fn[NAME].Constructor = Alert; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Alert._jQueryInterface; + }; + + return Alert; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): button.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Button = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'button'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.button'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ClassName = { + ACTIVE: 'active', + BUTTON: 'btn', + FOCUS: 'focus' + }; + var Selector = { + DATA_TOGGLE_CARROT: '[data-toggle^="button"]', + DATA_TOGGLE: '[data-toggle="buttons"]', + INPUT: 'input', + ACTIVE: '.active', + BUTTON: '.btn' + }; + var Event = { + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, + FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY) + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Button = + /*#__PURE__*/ + function () { + function Button(element) { + this._element = element; + } // Getters + + + var _proto = Button.prototype; + + // Public + _proto.toggle = function toggle() { + var triggerChangeEvent = true; + var addAriaPressed = true; + var rootElement = $$$1(this._element).closest(Selector.DATA_TOGGLE)[0]; + + if (rootElement) { + var input = this._element.querySelector(Selector.INPUT); + + if (input) { + if (input.type === 'radio') { + if (input.checked && this._element.classList.contains(ClassName.ACTIVE)) { + triggerChangeEvent = false; + } else { + var activeElement = rootElement.querySelector(Selector.ACTIVE); + + if (activeElement) { + $$$1(activeElement).removeClass(ClassName.ACTIVE); + } + } + } + + if (triggerChangeEvent) { + if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) { + return; + } + + input.checked = !this._element.classList.contains(ClassName.ACTIVE); + $$$1(input).trigger('change'); + } + + input.focus(); + addAriaPressed = false; + } + } + + if (addAriaPressed) { + this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName.ACTIVE)); + } + + if (triggerChangeEvent) { + $$$1(this._element).toggleClass(ClassName.ACTIVE); + } + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._element = null; + }; // Static + + + Button._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + if (!data) { + data = new Button(this); + $$$1(this).data(DATA_KEY, data); + } + + if (config === 'toggle') { + data[config](); + } + }); + }; + + _createClass(Button, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }]); + + return Button; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { + event.preventDefault(); + var button = event.target; + + if (!$$$1(button).hasClass(ClassName.BUTTON)) { + button = $$$1(button).closest(Selector.BUTTON); + } + + Button._jQueryInterface.call($$$1(button), 'toggle'); + }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { + var button = $$$1(event.target).closest(Selector.BUTTON)[0]; + $$$1(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Button._jQueryInterface; + $$$1.fn[NAME].Constructor = Button; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Button._jQueryInterface; + }; + + return Button; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): carousel.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Carousel = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'carousel'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.carousel'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key + + var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key + + var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch + + var Default = { + interval: 5000, + keyboard: true, + slide: false, + pause: 'hover', + wrap: true + }; + var DefaultType = { + interval: '(number|boolean)', + keyboard: 'boolean', + slide: '(boolean|string)', + pause: '(string|boolean)', + wrap: 'boolean' + }; + var Direction = { + NEXT: 'next', + PREV: 'prev', + LEFT: 'left', + RIGHT: 'right' + }; + var Event = { + SLIDE: "slide" + EVENT_KEY, + SLID: "slid" + EVENT_KEY, + KEYDOWN: "keydown" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY, + TOUCHEND: "touchend" + EVENT_KEY, + LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + CAROUSEL: 'carousel', + ACTIVE: 'active', + SLIDE: 'slide', + RIGHT: 'carousel-item-right', + LEFT: 'carousel-item-left', + NEXT: 'carousel-item-next', + PREV: 'carousel-item-prev', + ITEM: 'carousel-item' + }; + var Selector = { + ACTIVE: '.active', + ACTIVE_ITEM: '.active.carousel-item', + ITEM: '.carousel-item', + NEXT_PREV: '.carousel-item-next, .carousel-item-prev', + INDICATORS: '.carousel-indicators', + DATA_SLIDE: '[data-slide], [data-slide-to]', + DATA_RIDE: '[data-ride="carousel"]' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Carousel = + /*#__PURE__*/ + function () { + function Carousel(element, config) { + this._items = null; + this._interval = null; + this._activeElement = null; + this._isPaused = false; + this._isSliding = false; + this.touchTimeout = null; + this._config = this._getConfig(config); + this._element = $$$1(element)[0]; + this._indicatorsElement = this._element.querySelector(Selector.INDICATORS); + + this._addEventListeners(); + } // Getters + + + var _proto = Carousel.prototype; + + // Public + _proto.next = function next() { + if (!this._isSliding) { + this._slide(Direction.NEXT); + } + }; + + _proto.nextWhenVisible = function nextWhenVisible() { + // Don't call next when the page isn't visible + // or the carousel or its parent isn't visible + if (!document.hidden && $$$1(this._element).is(':visible') && $$$1(this._element).css('visibility') !== 'hidden') { + this.next(); + } + }; + + _proto.prev = function prev() { + if (!this._isSliding) { + this._slide(Direction.PREV); + } + }; + + _proto.pause = function pause(event) { + if (!event) { + this._isPaused = true; + } + + if (this._element.querySelector(Selector.NEXT_PREV)) { + Util.triggerTransitionEnd(this._element); + this.cycle(true); + } + + clearInterval(this._interval); + this._interval = null; + }; + + _proto.cycle = function cycle(event) { + if (!event) { + this._isPaused = false; + } + + if (this._interval) { + clearInterval(this._interval); + this._interval = null; + } + + if (this._config.interval && !this._isPaused) { + this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); + } + }; + + _proto.to = function to(index) { + var _this = this; + + this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); + + var activeIndex = this._getItemIndex(this._activeElement); + + if (index > this._items.length - 1 || index < 0) { + return; + } + + if (this._isSliding) { + $$$1(this._element).one(Event.SLID, function () { + return _this.to(index); + }); + return; + } + + if (activeIndex === index) { + this.pause(); + this.cycle(); + return; + } + + var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; + + this._slide(direction, this._items[index]); + }; + + _proto.dispose = function dispose() { + $$$1(this._element).off(EVENT_KEY); + $$$1.removeData(this._element, DATA_KEY); + this._items = null; + this._config = null; + this._element = null; + this._interval = null; + this._isPaused = null; + this._isSliding = null; + this._activeElement = null; + this._indicatorsElement = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._addEventListeners = function _addEventListeners() { + var _this2 = this; + + if (this._config.keyboard) { + $$$1(this._element).on(Event.KEYDOWN, function (event) { + return _this2._keydown(event); + }); + } + + if (this._config.pause === 'hover') { + $$$1(this._element).on(Event.MOUSEENTER, function (event) { + return _this2.pause(event); + }).on(Event.MOUSELEAVE, function (event) { + return _this2.cycle(event); + }); + + if ('ontouchstart' in document.documentElement) { + // If it's a touch-enabled device, mouseenter/leave are fired as + // part of the mouse compatibility events on first tap - the carousel + // would stop cycling until user tapped out of it; + // here, we listen for touchend, explicitly pause the carousel + // (as if it's the second time we tap on it, mouseenter compat event + // is NOT fired) and after a timeout (to allow for mouse compatibility + // events to fire) we explicitly restart cycling + $$$1(this._element).on(Event.TOUCHEND, function () { + _this2.pause(); + + if (_this2.touchTimeout) { + clearTimeout(_this2.touchTimeout); + } + + _this2.touchTimeout = setTimeout(function (event) { + return _this2.cycle(event); + }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval); + }); + } + } + }; + + _proto._keydown = function _keydown(event) { + if (/input|textarea/i.test(event.target.tagName)) { + return; + } + + switch (event.which) { + case ARROW_LEFT_KEYCODE: + event.preventDefault(); + this.prev(); + break; + + case ARROW_RIGHT_KEYCODE: + event.preventDefault(); + this.next(); + break; + + default: + } + }; + + _proto._getItemIndex = function _getItemIndex(element) { + this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) : []; + return this._items.indexOf(element); + }; + + _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) { + var isNextDirection = direction === Direction.NEXT; + var isPrevDirection = direction === Direction.PREV; + + var activeIndex = this._getItemIndex(activeElement); + + var lastItemIndex = this._items.length - 1; + var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex; + + if (isGoingToWrap && !this._config.wrap) { + return activeElement; + } + + var delta = direction === Direction.PREV ? -1 : 1; + var itemIndex = (activeIndex + delta) % this._items.length; + return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex]; + }; + + _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { + var targetIndex = this._getItemIndex(relatedTarget); + + var fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)); + + var slideEvent = $$$1.Event(Event.SLIDE, { + relatedTarget: relatedTarget, + direction: eventDirectionName, + from: fromIndex, + to: targetIndex + }); + $$$1(this._element).trigger(slideEvent); + return slideEvent; + }; + + _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) { + if (this._indicatorsElement) { + var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)); + $$$1(indicators).removeClass(ClassName.ACTIVE); + + var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]; + + if (nextIndicator) { + $$$1(nextIndicator).addClass(ClassName.ACTIVE); + } + } + }; + + _proto._slide = function _slide(direction, element) { + var _this3 = this; + + var activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); + + var activeElementIndex = this._getItemIndex(activeElement); + + var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement); + + var nextElementIndex = this._getItemIndex(nextElement); + + var isCycling = Boolean(this._interval); + var directionalClassName; + var orderClassName; + var eventDirectionName; + + if (direction === Direction.NEXT) { + directionalClassName = ClassName.LEFT; + orderClassName = ClassName.NEXT; + eventDirectionName = Direction.LEFT; + } else { + directionalClassName = ClassName.RIGHT; + orderClassName = ClassName.PREV; + eventDirectionName = Direction.RIGHT; + } + + if (nextElement && $$$1(nextElement).hasClass(ClassName.ACTIVE)) { + this._isSliding = false; + return; + } + + var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); + + if (slideEvent.isDefaultPrevented()) { + return; + } + + if (!activeElement || !nextElement) { + // Some weirdness is happening, so we bail + return; + } + + this._isSliding = true; + + if (isCycling) { + this.pause(); + } + + this._setActiveIndicatorElement(nextElement); + + var slidEvent = $$$1.Event(Event.SLID, { + relatedTarget: nextElement, + direction: eventDirectionName, + from: activeElementIndex, + to: nextElementIndex + }); + + if ($$$1(this._element).hasClass(ClassName.SLIDE)) { + $$$1(nextElement).addClass(orderClassName); + Util.reflow(nextElement); + $$$1(activeElement).addClass(directionalClassName); + $$$1(nextElement).addClass(directionalClassName); + var transitionDuration = Util.getTransitionDurationFromElement(activeElement); + $$$1(activeElement).one(Util.TRANSITION_END, function () { + $$$1(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE); + $$$1(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName); + _this3._isSliding = false; + setTimeout(function () { + return $$$1(_this3._element).trigger(slidEvent); + }, 0); + }).emulateTransitionEnd(transitionDuration); + } else { + $$$1(activeElement).removeClass(ClassName.ACTIVE); + $$$1(nextElement).addClass(ClassName.ACTIVE); + this._isSliding = false; + $$$1(this._element).trigger(slidEvent); + } + + if (isCycling) { + this.cycle(); + } + }; // Static + + + Carousel._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = _objectSpread({}, Default, $$$1(this).data()); + + if (typeof config === 'object') { + _config = _objectSpread({}, _config, config); + } + + var action = typeof config === 'string' ? config : _config.slide; + + if (!data) { + data = new Carousel(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'number') { + data.to(config); + } else if (typeof action === 'string') { + if (typeof data[action] === 'undefined') { + throw new TypeError("No method named \"" + action + "\""); + } + + data[action](); + } else if (_config.interval) { + data.pause(); + data.cycle(); + } + }); + }; + + Carousel._dataApiClickHandler = function _dataApiClickHandler(event) { + var selector = Util.getSelectorFromElement(this); + + if (!selector) { + return; + } + + var target = $$$1(selector)[0]; + + if (!target || !$$$1(target).hasClass(ClassName.CAROUSEL)) { + return; + } + + var config = _objectSpread({}, $$$1(target).data(), $$$1(this).data()); + + var slideIndex = this.getAttribute('data-slide-to'); + + if (slideIndex) { + config.interval = false; + } + + Carousel._jQueryInterface.call($$$1(target), config); + + if (slideIndex) { + $$$1(target).data(DATA_KEY).to(slideIndex); + } + + event.preventDefault(); + }; + + _createClass(Carousel, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Carousel; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler); + $$$1(window).on(Event.LOAD_DATA_API, function () { + var carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)); + + for (var i = 0, len = carousels.length; i < len; i++) { + var $carousel = $$$1(carousels[i]); + + Carousel._jQueryInterface.call($carousel, $carousel.data()); + } + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Carousel._jQueryInterface; + $$$1.fn[NAME].Constructor = Carousel; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Carousel._jQueryInterface; + }; + + return Carousel; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): collapse.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Collapse = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'collapse'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.collapse'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Default = { + toggle: true, + parent: '' + }; + var DefaultType = { + toggle: 'boolean', + parent: '(string|element)' + }; + var Event = { + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + SHOW: 'show', + COLLAPSE: 'collapse', + COLLAPSING: 'collapsing', + COLLAPSED: 'collapsed' + }; + var Dimension = { + WIDTH: 'width', + HEIGHT: 'height' + }; + var Selector = { + ACTIVES: '.show, .collapsing', + DATA_TOGGLE: '[data-toggle="collapse"]' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Collapse = + /*#__PURE__*/ + function () { + function Collapse(element, config) { + this._isTransitioning = false; + this._element = element; + this._config = this._getConfig(config); + this._triggerArray = $$$1.makeArray(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); + var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); + + for (var i = 0, len = toggleList.length; i < len; i++) { + var elem = toggleList[i]; + var selector = Util.getSelectorFromElement(elem); + var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) { + return foundElem === element; + }); + + if (selector !== null && filterElement.length > 0) { + this._selector = selector; + + this._triggerArray.push(elem); + } + } + + this._parent = this._config.parent ? this._getParent() : null; + + if (!this._config.parent) { + this._addAriaAndCollapsedClass(this._element, this._triggerArray); + } + + if (this._config.toggle) { + this.toggle(); + } + } // Getters + + + var _proto = Collapse.prototype; + + // Public + _proto.toggle = function toggle() { + if ($$$1(this._element).hasClass(ClassName.SHOW)) { + this.hide(); + } else { + this.show(); + } + }; + + _proto.show = function show() { + var _this = this; + + if (this._isTransitioning || $$$1(this._element).hasClass(ClassName.SHOW)) { + return; + } + + var actives; + var activesData; + + if (this._parent) { + actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) { + return elem.getAttribute('data-parent') === _this._config.parent; + }); + + if (actives.length === 0) { + actives = null; + } + } + + if (actives) { + activesData = $$$1(actives).not(this._selector).data(DATA_KEY); + + if (activesData && activesData._isTransitioning) { + return; + } + } + + var startEvent = $$$1.Event(Event.SHOW); + $$$1(this._element).trigger(startEvent); + + if (startEvent.isDefaultPrevented()) { + return; + } + + if (actives) { + Collapse._jQueryInterface.call($$$1(actives).not(this._selector), 'hide'); + + if (!activesData) { + $$$1(actives).data(DATA_KEY, null); + } + } + + var dimension = this._getDimension(); + + $$$1(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); + this._element.style[dimension] = 0; + + if (this._triggerArray.length) { + $$$1(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); + } + + this.setTransitioning(true); + + var complete = function complete() { + $$$1(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW); + _this._element.style[dimension] = ''; + + _this.setTransitioning(false); + + $$$1(_this._element).trigger(Event.SHOWN); + }; + + var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); + var scrollSize = "scroll" + capitalizedDimension; + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + this._element.style[dimension] = this._element[scrollSize] + "px"; + }; + + _proto.hide = function hide() { + var _this2 = this; + + if (this._isTransitioning || !$$$1(this._element).hasClass(ClassName.SHOW)) { + return; + } + + var startEvent = $$$1.Event(Event.HIDE); + $$$1(this._element).trigger(startEvent); + + if (startEvent.isDefaultPrevented()) { + return; + } + + var dimension = this._getDimension(); + + this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px"; + Util.reflow(this._element); + $$$1(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); + var triggerArrayLength = this._triggerArray.length; + + if (triggerArrayLength > 0) { + for (var i = 0; i < triggerArrayLength; i++) { + var trigger = this._triggerArray[i]; + var selector = Util.getSelectorFromElement(trigger); + + if (selector !== null) { + var $elem = $$$1([].slice.call(document.querySelectorAll(selector))); + + if (!$elem.hasClass(ClassName.SHOW)) { + $$$1(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); + } + } + } + } + + this.setTransitioning(true); + + var complete = function complete() { + _this2.setTransitioning(false); + + $$$1(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN); + }; + + this._element.style[dimension] = ''; + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + }; + + _proto.setTransitioning = function setTransitioning(isTransitioning) { + this._isTransitioning = isTransitioning; + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._config = null; + this._parent = null; + this._element = null; + this._triggerArray = null; + this._isTransitioning = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + config.toggle = Boolean(config.toggle); // Coerce string values + + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._getDimension = function _getDimension() { + var hasWidth = $$$1(this._element).hasClass(Dimension.WIDTH); + return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT; + }; + + _proto._getParent = function _getParent() { + var _this3 = this; + + var parent = null; + + if (Util.isElement(this._config.parent)) { + parent = this._config.parent; // It's a jQuery object + + if (typeof this._config.parent.jquery !== 'undefined') { + parent = this._config.parent[0]; + } + } else { + parent = document.querySelector(this._config.parent); + } + + var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]"; + var children = [].slice.call(parent.querySelectorAll(selector)); + $$$1(children).each(function (i, element) { + _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); + }); + return parent; + }; + + _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) { + if (element) { + var isOpen = $$$1(element).hasClass(ClassName.SHOW); + + if (triggerArray.length) { + $$$1(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); + } + } + }; // Static + + + Collapse._getTargetFromElement = function _getTargetFromElement(element) { + var selector = Util.getSelectorFromElement(element); + return selector ? document.querySelector(selector) : null; + }; + + Collapse._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var $this = $$$1(this); + var data = $this.data(DATA_KEY); + + var _config = _objectSpread({}, Default, $this.data(), typeof config === 'object' && config ? config : {}); + + if (!data && _config.toggle && /show|hide/.test(config)) { + _config.toggle = false; + } + + if (!data) { + data = new Collapse(this, _config); + $this.data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Collapse, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Collapse; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + // preventDefault only for elements (which change the URL) not inside the collapsible element + if (event.currentTarget.tagName === 'A') { + event.preventDefault(); + } + + var $trigger = $$$1(this); + var selector = Util.getSelectorFromElement(this); + var selectors = [].slice.call(document.querySelectorAll(selector)); + $$$1(selectors).each(function () { + var $target = $$$1(this); + var data = $target.data(DATA_KEY); + var config = data ? 'toggle' : $trigger.data(); + + Collapse._jQueryInterface.call($target, config); + }); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Collapse._jQueryInterface; + $$$1.fn[NAME].Constructor = Collapse; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Collapse._jQueryInterface; + }; + + return Collapse; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): dropdown.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Dropdown = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'dropdown'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.dropdown'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + + var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key + + var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key + + var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key + + var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key + + var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) + + var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE); + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, + KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY, + KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + DISABLED: 'disabled', + SHOW: 'show', + DROPUP: 'dropup', + DROPRIGHT: 'dropright', + DROPLEFT: 'dropleft', + MENURIGHT: 'dropdown-menu-right', + MENULEFT: 'dropdown-menu-left', + POSITION_STATIC: 'position-static' + }; + var Selector = { + DATA_TOGGLE: '[data-toggle="dropdown"]', + FORM_CHILD: '.dropdown form', + MENU: '.dropdown-menu', + NAVBAR_NAV: '.navbar-nav', + VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' + }; + var AttachmentMap = { + TOP: 'top-start', + TOPEND: 'top-end', + BOTTOM: 'bottom-start', + BOTTOMEND: 'bottom-end', + RIGHT: 'right-start', + RIGHTEND: 'right-end', + LEFT: 'left-start', + LEFTEND: 'left-end' + }; + var Default = { + offset: 0, + flip: true, + boundary: 'scrollParent', + reference: 'toggle', + display: 'dynamic' + }; + var DefaultType = { + offset: '(number|string|function)', + flip: 'boolean', + boundary: '(string|element)', + reference: '(string|element)', + display: 'string' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Dropdown = + /*#__PURE__*/ + function () { + function Dropdown(element, config) { + this._element = element; + this._popper = null; + this._config = this._getConfig(config); + this._menu = this._getMenuElement(); + this._inNavbar = this._detectNavbar(); + + this._addEventListeners(); + } // Getters + + + var _proto = Dropdown.prototype; + + // Public + _proto.toggle = function toggle() { + if (this._element.disabled || $$$1(this._element).hasClass(ClassName.DISABLED)) { + return; + } + + var parent = Dropdown._getParentFromElement(this._element); + + var isActive = $$$1(this._menu).hasClass(ClassName.SHOW); + + Dropdown._clearMenus(); + + if (isActive) { + return; + } + + var relatedTarget = { + relatedTarget: this._element + }; + var showEvent = $$$1.Event(Event.SHOW, relatedTarget); + $$$1(parent).trigger(showEvent); + + if (showEvent.isDefaultPrevented()) { + return; + } // Disable totally Popper.js for Dropdown in Navbar + + + if (!this._inNavbar) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)'); + } + + var referenceElement = this._element; + + if (this._config.reference === 'parent') { + referenceElement = parent; + } else if (Util.isElement(this._config.reference)) { + referenceElement = this._config.reference; // Check if it's jQuery element + + if (typeof this._config.reference.jquery !== 'undefined') { + referenceElement = this._config.reference[0]; + } + } // If boundary is not `scrollParent`, then set position to `static` + // to allow the menu to "escape" the scroll parent's boundaries + // https://github.com/twbs/bootstrap/issues/24251 + + + if (this._config.boundary !== 'scrollParent') { + $$$1(parent).addClass(ClassName.POSITION_STATIC); + } + + this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()); + } // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + + + if ('ontouchstart' in document.documentElement && $$$1(parent).closest(Selector.NAVBAR_NAV).length === 0) { + $$$1(document.body).children().on('mouseover', null, $$$1.noop); + } + + this._element.focus(); + + this._element.setAttribute('aria-expanded', true); + + $$$1(this._menu).toggleClass(ClassName.SHOW); + $$$1(parent).toggleClass(ClassName.SHOW).trigger($$$1.Event(Event.SHOWN, relatedTarget)); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(this._element).off(EVENT_KEY); + this._element = null; + this._menu = null; + + if (this._popper !== null) { + this._popper.destroy(); + + this._popper = null; + } + }; + + _proto.update = function update() { + this._inNavbar = this._detectNavbar(); + + if (this._popper !== null) { + this._popper.scheduleUpdate(); + } + }; // Private + + + _proto._addEventListeners = function _addEventListeners() { + var _this = this; + + $$$1(this._element).on(Event.CLICK, function (event) { + event.preventDefault(); + event.stopPropagation(); + + _this.toggle(); + }); + }; + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, this.constructor.Default, $$$1(this._element).data(), config); + Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); + return config; + }; + + _proto._getMenuElement = function _getMenuElement() { + if (!this._menu) { + var parent = Dropdown._getParentFromElement(this._element); + + if (parent) { + this._menu = parent.querySelector(Selector.MENU); + } + } + + return this._menu; + }; + + _proto._getPlacement = function _getPlacement() { + var $parentDropdown = $$$1(this._element.parentNode); + var placement = AttachmentMap.BOTTOM; // Handle dropup + + if ($parentDropdown.hasClass(ClassName.DROPUP)) { + placement = AttachmentMap.TOP; + + if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.TOPEND; + } + } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) { + placement = AttachmentMap.RIGHT; + } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) { + placement = AttachmentMap.LEFT; + } else if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.BOTTOMEND; + } + + return placement; + }; + + _proto._detectNavbar = function _detectNavbar() { + return $$$1(this._element).closest('.navbar').length > 0; + }; + + _proto._getPopperConfig = function _getPopperConfig() { + var _this2 = this; + + var offsetConf = {}; + + if (typeof this._config.offset === 'function') { + offsetConf.fn = function (data) { + data.offsets = _objectSpread({}, data.offsets, _this2._config.offset(data.offsets) || {}); + return data; + }; + } else { + offsetConf.offset = this._config.offset; + } + + var popperConfig = { + placement: this._getPlacement(), + modifiers: { + offset: offsetConf, + flip: { + enabled: this._config.flip + }, + preventOverflow: { + boundariesElement: this._config.boundary + } + } // Disable Popper.js if we have a static display + + }; + + if (this._config.display === 'static') { + popperConfig.modifiers.applyStyle = { + enabled: false + }; + } + + return popperConfig; + }; // Static + + + Dropdown._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' ? config : null; + + if (!data) { + data = new Dropdown(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + Dropdown._clearMenus = function _clearMenus(event) { + if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { + return; + } + + var toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); + + for (var i = 0, len = toggles.length; i < len; i++) { + var parent = Dropdown._getParentFromElement(toggles[i]); + + var context = $$$1(toggles[i]).data(DATA_KEY); + var relatedTarget = { + relatedTarget: toggles[i] + }; + + if (event && event.type === 'click') { + relatedTarget.clickEvent = event; + } + + if (!context) { + continue; + } + + var dropdownMenu = context._menu; + + if (!$$$1(parent).hasClass(ClassName.SHOW)) { + continue; + } + + if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $$$1.contains(parent, event.target)) { + continue; + } + + var hideEvent = $$$1.Event(Event.HIDE, relatedTarget); + $$$1(parent).trigger(hideEvent); + + if (hideEvent.isDefaultPrevented()) { + continue; + } // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().off('mouseover', null, $$$1.noop); + } + + toggles[i].setAttribute('aria-expanded', 'false'); + $$$1(dropdownMenu).removeClass(ClassName.SHOW); + $$$1(parent).removeClass(ClassName.SHOW).trigger($$$1.Event(Event.HIDDEN, relatedTarget)); + } + }; + + Dropdown._getParentFromElement = function _getParentFromElement(element) { + var parent; + var selector = Util.getSelectorFromElement(element); + + if (selector) { + parent = document.querySelector(selector); + } + + return parent || element.parentNode; + }; // eslint-disable-next-line complexity + + + Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { + // If not input/textarea: + // - And not a key in REGEXP_KEYDOWN => not a dropdown command + // If input/textarea: + // - If space key => not a dropdown command + // - If key is other than escape + // - If key is not up or down => not a dropdown command + // - If trigger inside the menu => not a dropdown command + if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $$$1(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + if (this.disabled || $$$1(this).hasClass(ClassName.DISABLED)) { + return; + } + + var parent = Dropdown._getParentFromElement(this); + + var isActive = $$$1(parent).hasClass(ClassName.SHOW); + + if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { + if (event.which === ESCAPE_KEYCODE) { + var toggle = parent.querySelector(Selector.DATA_TOGGLE); + $$$1(toggle).trigger('focus'); + } + + $$$1(this).trigger('click'); + return; + } + + var items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS)); + + if (items.length === 0) { + return; + } + + var index = items.indexOf(event.target); + + if (event.which === ARROW_UP_KEYCODE && index > 0) { + // Up + index--; + } + + if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { + // Down + index++; + } + + if (index < 0) { + index = 0; + } + + items[index].focus(); + }; + + _createClass(Dropdown, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Dropdown; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + event.preventDefault(); + event.stopPropagation(); + + Dropdown._jQueryInterface.call($$$1(this), 'toggle'); + }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) { + e.stopPropagation(); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Dropdown._jQueryInterface; + $$$1.fn[NAME].Constructor = Dropdown; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Dropdown._jQueryInterface; + }; + + return Dropdown; + }($, Popper); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): modal.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Modal = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'modal'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.modal'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + + var Default = { + backdrop: true, + keyboard: true, + focus: true, + show: true + }; + var DefaultType = { + backdrop: '(boolean|string)', + keyboard: 'boolean', + focus: 'boolean', + show: 'boolean' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + RESIZE: "resize" + EVENT_KEY, + CLICK_DISMISS: "click.dismiss" + EVENT_KEY, + KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY, + MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY, + MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + SCROLLBAR_MEASURER: 'modal-scrollbar-measure', + BACKDROP: 'modal-backdrop', + OPEN: 'modal-open', + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + DIALOG: '.modal-dialog', + DATA_TOGGLE: '[data-toggle="modal"]', + DATA_DISMISS: '[data-dismiss="modal"]', + FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', + STICKY_CONTENT: '.sticky-top' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Modal = + /*#__PURE__*/ + function () { + function Modal(element, config) { + this._config = this._getConfig(config); + this._element = element; + this._dialog = element.querySelector(Selector.DIALOG); + this._backdrop = null; + this._isShown = false; + this._isBodyOverflowing = false; + this._ignoreBackdropClick = false; + this._scrollbarWidth = 0; + } // Getters + + + var _proto = Modal.prototype; + + // Public + _proto.toggle = function toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget); + }; + + _proto.show = function show(relatedTarget) { + var _this = this; + + if (this._isTransitioning || this._isShown) { + return; + } + + if ($$$1(this._element).hasClass(ClassName.FADE)) { + this._isTransitioning = true; + } + + var showEvent = $$$1.Event(Event.SHOW, { + relatedTarget: relatedTarget + }); + $$$1(this._element).trigger(showEvent); + + if (this._isShown || showEvent.isDefaultPrevented()) { + return; + } + + this._isShown = true; + + this._checkScrollbar(); + + this._setScrollbar(); + + this._adjustDialog(); + + $$$1(document.body).addClass(ClassName.OPEN); + + this._setEscapeEvent(); + + this._setResizeEvent(); + + $$$1(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) { + return _this.hide(event); + }); + $$$1(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () { + $$$1(_this._element).one(Event.MOUSEUP_DISMISS, function (event) { + if ($$$1(event.target).is(_this._element)) { + _this._ignoreBackdropClick = true; + } + }); + }); + + this._showBackdrop(function () { + return _this._showElement(relatedTarget); + }); + }; + + _proto.hide = function hide(event) { + var _this2 = this; + + if (event) { + event.preventDefault(); + } + + if (this._isTransitioning || !this._isShown) { + return; + } + + var hideEvent = $$$1.Event(Event.HIDE); + $$$1(this._element).trigger(hideEvent); + + if (!this._isShown || hideEvent.isDefaultPrevented()) { + return; + } + + this._isShown = false; + var transition = $$$1(this._element).hasClass(ClassName.FADE); + + if (transition) { + this._isTransitioning = true; + } + + this._setEscapeEvent(); + + this._setResizeEvent(); + + $$$1(document).off(Event.FOCUSIN); + $$$1(this._element).removeClass(ClassName.SHOW); + $$$1(this._element).off(Event.CLICK_DISMISS); + $$$1(this._dialog).off(Event.MOUSEDOWN_DISMISS); + + if (transition) { + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, function (event) { + return _this2._hideModal(event); + }).emulateTransitionEnd(transitionDuration); + } else { + this._hideModal(); + } + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(window, document, this._element, this._backdrop).off(EVENT_KEY); + this._config = null; + this._element = null; + this._dialog = null; + this._backdrop = null; + this._isShown = null; + this._isBodyOverflowing = null; + this._ignoreBackdropClick = null; + this._scrollbarWidth = null; + }; + + _proto.handleUpdate = function handleUpdate() { + this._adjustDialog(); + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._showElement = function _showElement(relatedTarget) { + var _this3 = this; + + var transition = $$$1(this._element).hasClass(ClassName.FADE); + + if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { + // Don't move modal's DOM position + document.body.appendChild(this._element); + } + + this._element.style.display = 'block'; + + this._element.removeAttribute('aria-hidden'); + + this._element.scrollTop = 0; + + if (transition) { + Util.reflow(this._element); + } + + $$$1(this._element).addClass(ClassName.SHOW); + + if (this._config.focus) { + this._enforceFocus(); + } + + var shownEvent = $$$1.Event(Event.SHOWN, { + relatedTarget: relatedTarget + }); + + var transitionComplete = function transitionComplete() { + if (_this3._config.focus) { + _this3._element.focus(); + } + + _this3._isTransitioning = false; + $$$1(_this3._element).trigger(shownEvent); + }; + + if (transition) { + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration); + } else { + transitionComplete(); + } + }; + + _proto._enforceFocus = function _enforceFocus() { + var _this4 = this; + + $$$1(document).off(Event.FOCUSIN) // Guard against infinite focus loop + .on(Event.FOCUSIN, function (event) { + if (document !== event.target && _this4._element !== event.target && $$$1(_this4._element).has(event.target).length === 0) { + _this4._element.focus(); + } + }); + }; + + _proto._setEscapeEvent = function _setEscapeEvent() { + var _this5 = this; + + if (this._isShown && this._config.keyboard) { + $$$1(this._element).on(Event.KEYDOWN_DISMISS, function (event) { + if (event.which === ESCAPE_KEYCODE) { + event.preventDefault(); + + _this5.hide(); + } + }); + } else if (!this._isShown) { + $$$1(this._element).off(Event.KEYDOWN_DISMISS); + } + }; + + _proto._setResizeEvent = function _setResizeEvent() { + var _this6 = this; + + if (this._isShown) { + $$$1(window).on(Event.RESIZE, function (event) { + return _this6.handleUpdate(event); + }); + } else { + $$$1(window).off(Event.RESIZE); + } + }; + + _proto._hideModal = function _hideModal() { + var _this7 = this; + + this._element.style.display = 'none'; + + this._element.setAttribute('aria-hidden', true); + + this._isTransitioning = false; + + this._showBackdrop(function () { + $$$1(document.body).removeClass(ClassName.OPEN); + + _this7._resetAdjustments(); + + _this7._resetScrollbar(); + + $$$1(_this7._element).trigger(Event.HIDDEN); + }); + }; + + _proto._removeBackdrop = function _removeBackdrop() { + if (this._backdrop) { + $$$1(this._backdrop).remove(); + this._backdrop = null; + } + }; + + _proto._showBackdrop = function _showBackdrop(callback) { + var _this8 = this; + + var animate = $$$1(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : ''; + + if (this._isShown && this._config.backdrop) { + this._backdrop = document.createElement('div'); + this._backdrop.className = ClassName.BACKDROP; + + if (animate) { + this._backdrop.classList.add(animate); + } + + $$$1(this._backdrop).appendTo(document.body); + $$$1(this._element).on(Event.CLICK_DISMISS, function (event) { + if (_this8._ignoreBackdropClick) { + _this8._ignoreBackdropClick = false; + return; + } + + if (event.target !== event.currentTarget) { + return; + } + + if (_this8._config.backdrop === 'static') { + _this8._element.focus(); + } else { + _this8.hide(); + } + }); + + if (animate) { + Util.reflow(this._backdrop); + } + + $$$1(this._backdrop).addClass(ClassName.SHOW); + + if (!callback) { + return; + } + + if (!animate) { + callback(); + return; + } + + var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); + $$$1(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration); + } else if (!this._isShown && this._backdrop) { + $$$1(this._backdrop).removeClass(ClassName.SHOW); + + var callbackRemove = function callbackRemove() { + _this8._removeBackdrop(); + + if (callback) { + callback(); + } + }; + + if ($$$1(this._element).hasClass(ClassName.FADE)) { + var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); + + $$$1(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration); + } else { + callbackRemove(); + } + } else if (callback) { + callback(); + } + }; // ---------------------------------------------------------------------- + // the following methods are used to handle overflowing modals + // todo (fat): these should probably be refactored out of modal.js + // ---------------------------------------------------------------------- + + + _proto._adjustDialog = function _adjustDialog() { + var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; + + if (!this._isBodyOverflowing && isModalOverflowing) { + this._element.style.paddingLeft = this._scrollbarWidth + "px"; + } + + if (this._isBodyOverflowing && !isModalOverflowing) { + this._element.style.paddingRight = this._scrollbarWidth + "px"; + } + }; + + _proto._resetAdjustments = function _resetAdjustments() { + this._element.style.paddingLeft = ''; + this._element.style.paddingRight = ''; + }; + + _proto._checkScrollbar = function _checkScrollbar() { + var rect = document.body.getBoundingClientRect(); + this._isBodyOverflowing = rect.left + rect.right < window.innerWidth; + this._scrollbarWidth = this._getScrollbarWidth(); + }; + + _proto._setScrollbar = function _setScrollbar() { + var _this9 = this; + + if (this._isBodyOverflowing) { + // Note: DOMNode.style.paddingRight returns the actual value or '' if not set + // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set + var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); + var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding + + $$$1(fixedContent).each(function (index, element) { + var actualPadding = element.style.paddingRight; + var calculatedPadding = $$$1(element).css('padding-right'); + $$$1(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px"); + }); // Adjust sticky content margin + + $$$1(stickyContent).each(function (index, element) { + var actualMargin = element.style.marginRight; + var calculatedMargin = $$$1(element).css('margin-right'); + $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px"); + }); // Adjust body padding + + var actualPadding = document.body.style.paddingRight; + var calculatedPadding = $$$1(document.body).css('padding-right'); + $$$1(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px"); + } + }; + + _proto._resetScrollbar = function _resetScrollbar() { + // Restore fixed content padding + var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); + $$$1(fixedContent).each(function (index, element) { + var padding = $$$1(element).data('padding-right'); + $$$1(element).removeData('padding-right'); + element.style.paddingRight = padding ? padding : ''; + }); // Restore sticky content + + var elements = [].slice.call(document.querySelectorAll("" + Selector.STICKY_CONTENT)); + $$$1(elements).each(function (index, element) { + var margin = $$$1(element).data('margin-right'); + + if (typeof margin !== 'undefined') { + $$$1(element).css('margin-right', margin).removeData('margin-right'); + } + }); // Restore body padding + + var padding = $$$1(document.body).data('padding-right'); + $$$1(document.body).removeData('padding-right'); + document.body.style.paddingRight = padding ? padding : ''; + }; + + _proto._getScrollbarWidth = function _getScrollbarWidth() { + // thx d.walsh + var scrollDiv = document.createElement('div'); + scrollDiv.className = ClassName.SCROLLBAR_MEASURER; + document.body.appendChild(scrollDiv); + var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + return scrollbarWidth; + }; // Static + + + Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = _objectSpread({}, Default, $$$1(this).data(), typeof config === 'object' && config ? config : {}); + + if (!data) { + data = new Modal(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](relatedTarget); + } else if (_config.show) { + data.show(relatedTarget); + } + }); + }; + + _createClass(Modal, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Modal; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + var _this10 = this; + + var target; + var selector = Util.getSelectorFromElement(this); + + if (selector) { + target = document.querySelector(selector); + } + + var config = $$$1(target).data(DATA_KEY) ? 'toggle' : _objectSpread({}, $$$1(target).data(), $$$1(this).data()); + + if (this.tagName === 'A' || this.tagName === 'AREA') { + event.preventDefault(); + } + + var $target = $$$1(target).one(Event.SHOW, function (showEvent) { + if (showEvent.isDefaultPrevented()) { + // Only register focus restorer if modal will actually get shown + return; + } + + $target.one(Event.HIDDEN, function () { + if ($$$1(_this10).is(':visible')) { + _this10.focus(); + } + }); + }); + + Modal._jQueryInterface.call($$$1(target), config, this); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Modal._jQueryInterface; + $$$1.fn[NAME].Constructor = Modal; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Modal._jQueryInterface; + }; + + return Modal; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): tooltip.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Tooltip = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'tooltip'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.tooltip'; + var EVENT_KEY = "." + DATA_KEY; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var CLASS_PREFIX = 'bs-tooltip'; + var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); + var DefaultType = { + animation: 'boolean', + template: 'string', + title: '(string|element|function)', + trigger: 'string', + delay: '(number|object)', + html: 'boolean', + selector: '(string|boolean)', + placement: '(string|function)', + offset: '(number|string)', + container: '(string|element|boolean)', + fallbackPlacement: '(string|array)', + boundary: '(string|element)' + }; + var AttachmentMap = { + AUTO: 'auto', + TOP: 'top', + RIGHT: 'right', + BOTTOM: 'bottom', + LEFT: 'left' + }; + var Default = { + animation: true, + template: '', + trigger: 'hover focus', + title: '', + delay: 0, + html: false, + selector: false, + placement: 'top', + offset: 0, + container: false, + fallbackPlacement: 'flip', + boundary: 'scrollParent' + }; + var HoverState = { + SHOW: 'show', + OUT: 'out' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + INSERTED: "inserted" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + FOCUSOUT: "focusout" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY + }; + var ClassName = { + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + TOOLTIP: '.tooltip', + TOOLTIP_INNER: '.tooltip-inner', + ARROW: '.arrow' + }; + var Trigger = { + HOVER: 'hover', + FOCUS: 'focus', + CLICK: 'click', + MANUAL: 'manual' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Tooltip = + /*#__PURE__*/ + function () { + function Tooltip(element, config) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)'); + } // private + + + this._isEnabled = true; + this._timeout = 0; + this._hoverState = ''; + this._activeTrigger = {}; + this._popper = null; // Protected + + this.element = element; + this.config = this._getConfig(config); + this.tip = null; + + this._setListeners(); + } // Getters + + + var _proto = Tooltip.prototype; + + // Public + _proto.enable = function enable() { + this._isEnabled = true; + }; + + _proto.disable = function disable() { + this._isEnabled = false; + }; + + _proto.toggleEnabled = function toggleEnabled() { + this._isEnabled = !this._isEnabled; + }; + + _proto.toggle = function toggle(event) { + if (!this._isEnabled) { + return; + } + + if (event) { + var dataKey = this.constructor.DATA_KEY; + var context = $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + context._activeTrigger.click = !context._activeTrigger.click; + + if (context._isWithActiveTrigger()) { + context._enter(null, context); + } else { + context._leave(null, context); + } + } else { + if ($$$1(this.getTipElement()).hasClass(ClassName.SHOW)) { + this._leave(null, this); + + return; + } + + this._enter(null, this); + } + }; + + _proto.dispose = function dispose() { + clearTimeout(this._timeout); + $$$1.removeData(this.element, this.constructor.DATA_KEY); + $$$1(this.element).off(this.constructor.EVENT_KEY); + $$$1(this.element).closest('.modal').off('hide.bs.modal'); + + if (this.tip) { + $$$1(this.tip).remove(); + } + + this._isEnabled = null; + this._timeout = null; + this._hoverState = null; + this._activeTrigger = null; + + if (this._popper !== null) { + this._popper.destroy(); + } + + this._popper = null; + this.element = null; + this.config = null; + this.tip = null; + }; + + _proto.show = function show() { + var _this = this; + + if ($$$1(this.element).css('display') === 'none') { + throw new Error('Please use show on visible elements'); + } + + var showEvent = $$$1.Event(this.constructor.Event.SHOW); + + if (this.isWithContent() && this._isEnabled) { + $$$1(this.element).trigger(showEvent); + var isInTheDom = $$$1.contains(this.element.ownerDocument.documentElement, this.element); + + if (showEvent.isDefaultPrevented() || !isInTheDom) { + return; + } + + var tip = this.getTipElement(); + var tipId = Util.getUID(this.constructor.NAME); + tip.setAttribute('id', tipId); + this.element.setAttribute('aria-describedby', tipId); + this.setContent(); + + if (this.config.animation) { + $$$1(tip).addClass(ClassName.FADE); + } + + var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement; + + var attachment = this._getAttachment(placement); + + this.addAttachmentClass(attachment); + var container = this.config.container === false ? document.body : $$$1(document).find(this.config.container); + $$$1(tip).data(this.constructor.DATA_KEY, this); + + if (!$$$1.contains(this.element.ownerDocument.documentElement, this.tip)) { + $$$1(tip).appendTo(container); + } + + $$$1(this.element).trigger(this.constructor.Event.INSERTED); + this._popper = new Popper(this.element, tip, { + placement: attachment, + modifiers: { + offset: { + offset: this.config.offset + }, + flip: { + behavior: this.config.fallbackPlacement + }, + arrow: { + element: Selector.ARROW + }, + preventOverflow: { + boundariesElement: this.config.boundary + } + }, + onCreate: function onCreate(data) { + if (data.originalPlacement !== data.placement) { + _this._handlePopperPlacementChange(data); + } + }, + onUpdate: function onUpdate(data) { + _this._handlePopperPlacementChange(data); + } + }); + $$$1(tip).addClass(ClassName.SHOW); // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().on('mouseover', null, $$$1.noop); + } + + var complete = function complete() { + if (_this.config.animation) { + _this._fixTransition(); + } + + var prevHoverState = _this._hoverState; + _this._hoverState = null; + $$$1(_this.element).trigger(_this.constructor.Event.SHOWN); + + if (prevHoverState === HoverState.OUT) { + _this._leave(null, _this); + } + }; + + if ($$$1(this.tip).hasClass(ClassName.FADE)) { + var transitionDuration = Util.getTransitionDurationFromElement(this.tip); + $$$1(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + } else { + complete(); + } + } + }; + + _proto.hide = function hide(callback) { + var _this2 = this; + + var tip = this.getTipElement(); + var hideEvent = $$$1.Event(this.constructor.Event.HIDE); + + var complete = function complete() { + if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) { + tip.parentNode.removeChild(tip); + } + + _this2._cleanTipClass(); + + _this2.element.removeAttribute('aria-describedby'); + + $$$1(_this2.element).trigger(_this2.constructor.Event.HIDDEN); + + if (_this2._popper !== null) { + _this2._popper.destroy(); + } + + if (callback) { + callback(); + } + }; + + $$$1(this.element).trigger(hideEvent); + + if (hideEvent.isDefaultPrevented()) { + return; + } + + $$$1(tip).removeClass(ClassName.SHOW); // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().off('mouseover', null, $$$1.noop); + } + + this._activeTrigger[Trigger.CLICK] = false; + this._activeTrigger[Trigger.FOCUS] = false; + this._activeTrigger[Trigger.HOVER] = false; + + if ($$$1(this.tip).hasClass(ClassName.FADE)) { + var transitionDuration = Util.getTransitionDurationFromElement(tip); + $$$1(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + } else { + complete(); + } + + this._hoverState = ''; + }; + + _proto.update = function update() { + if (this._popper !== null) { + this._popper.scheduleUpdate(); + } + }; // Protected + + + _proto.isWithContent = function isWithContent() { + return Boolean(this.getTitle()); + }; + + _proto.addAttachmentClass = function addAttachmentClass(attachment) { + $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); + }; + + _proto.getTipElement = function getTipElement() { + this.tip = this.tip || $$$1(this.config.template)[0]; + return this.tip; + }; + + _proto.setContent = function setContent() { + var tip = this.getTipElement(); + this.setElementContent($$$1(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle()); + $$$1(tip).removeClass(ClassName.FADE + " " + ClassName.SHOW); + }; + + _proto.setElementContent = function setElementContent($element, content) { + var html = this.config.html; + + if (typeof content === 'object' && (content.nodeType || content.jquery)) { + // Content is a DOM node or a jQuery + if (html) { + if (!$$$1(content).parent().is($element)) { + $element.empty().append(content); + } + } else { + $element.text($$$1(content).text()); + } + } else { + $element[html ? 'html' : 'text'](content); + } + }; + + _proto.getTitle = function getTitle() { + var title = this.element.getAttribute('data-original-title'); + + if (!title) { + title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title; + } + + return title; + }; // Private + + + _proto._getAttachment = function _getAttachment(placement) { + return AttachmentMap[placement.toUpperCase()]; + }; + + _proto._setListeners = function _setListeners() { + var _this3 = this; + + var triggers = this.config.trigger.split(' '); + triggers.forEach(function (trigger) { + if (trigger === 'click') { + $$$1(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) { + return _this3.toggle(event); + }); + } else if (trigger !== Trigger.MANUAL) { + var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN; + var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT; + $$$1(_this3.element).on(eventIn, _this3.config.selector, function (event) { + return _this3._enter(event); + }).on(eventOut, _this3.config.selector, function (event) { + return _this3._leave(event); + }); + } + + $$$1(_this3.element).closest('.modal').on('hide.bs.modal', function () { + return _this3.hide(); + }); + }); + + if (this.config.selector) { + this.config = _objectSpread({}, this.config, { + trigger: 'manual', + selector: '' + }); + } else { + this._fixTitle(); + } + }; + + _proto._fixTitle = function _fixTitle() { + var titleType = typeof this.element.getAttribute('data-original-title'); + + if (this.element.getAttribute('title') || titleType !== 'string') { + this.element.setAttribute('data-original-title', this.element.getAttribute('title') || ''); + this.element.setAttribute('title', ''); + } + }; + + _proto._enter = function _enter(event, context) { + var dataKey = this.constructor.DATA_KEY; + context = context || $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + if (event) { + context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true; + } + + if ($$$1(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) { + context._hoverState = HoverState.SHOW; + return; + } + + clearTimeout(context._timeout); + context._hoverState = HoverState.SHOW; + + if (!context.config.delay || !context.config.delay.show) { + context.show(); + return; + } + + context._timeout = setTimeout(function () { + if (context._hoverState === HoverState.SHOW) { + context.show(); + } + }, context.config.delay.show); + }; + + _proto._leave = function _leave(event, context) { + var dataKey = this.constructor.DATA_KEY; + context = context || $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + if (event) { + context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false; + } + + if (context._isWithActiveTrigger()) { + return; + } + + clearTimeout(context._timeout); + context._hoverState = HoverState.OUT; + + if (!context.config.delay || !context.config.delay.hide) { + context.hide(); + return; + } + + context._timeout = setTimeout(function () { + if (context._hoverState === HoverState.OUT) { + context.hide(); + } + }, context.config.delay.hide); + }; + + _proto._isWithActiveTrigger = function _isWithActiveTrigger() { + for (var trigger in this._activeTrigger) { + if (this._activeTrigger[trigger]) { + return true; + } + } + + return false; + }; + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, this.constructor.Default, $$$1(this.element).data(), typeof config === 'object' && config ? config : {}); + + if (typeof config.delay === 'number') { + config.delay = { + show: config.delay, + hide: config.delay + }; + } + + if (typeof config.title === 'number') { + config.title = config.title.toString(); + } + + if (typeof config.content === 'number') { + config.content = config.content.toString(); + } + + Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); + return config; + }; + + _proto._getDelegateConfig = function _getDelegateConfig() { + var config = {}; + + if (this.config) { + for (var key in this.config) { + if (this.constructor.Default[key] !== this.config[key]) { + config[key] = this.config[key]; + } + } + } + + return config; + }; + + _proto._cleanTipClass = function _cleanTipClass() { + var $tip = $$$1(this.getTipElement()); + var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); + + if (tabClass !== null && tabClass.length) { + $tip.removeClass(tabClass.join('')); + } + }; + + _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) { + var popperInstance = popperData.instance; + this.tip = popperInstance.popper; + + this._cleanTipClass(); + + this.addAttachmentClass(this._getAttachment(popperData.placement)); + }; + + _proto._fixTransition = function _fixTransition() { + var tip = this.getTipElement(); + var initConfigAnimation = this.config.animation; + + if (tip.getAttribute('x-placement') !== null) { + return; + } + + $$$1(tip).removeClass(ClassName.FADE); + this.config.animation = false; + this.hide(); + this.show(); + this.config.animation = initConfigAnimation; + }; // Static + + + Tooltip._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' && config; + + if (!data && /dispose|hide/.test(config)) { + return; + } + + if (!data) { + data = new Tooltip(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Tooltip, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "NAME", + get: function get() { + return NAME; + } + }, { + key: "DATA_KEY", + get: function get() { + return DATA_KEY; + } + }, { + key: "Event", + get: function get() { + return Event; + } + }, { + key: "EVENT_KEY", + get: function get() { + return EVENT_KEY; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Tooltip; + }(); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + + $$$1.fn[NAME] = Tooltip._jQueryInterface; + $$$1.fn[NAME].Constructor = Tooltip; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Tooltip._jQueryInterface; + }; + + return Tooltip; + }($, Popper); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): popover.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Popover = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'popover'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.popover'; + var EVENT_KEY = "." + DATA_KEY; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var CLASS_PREFIX = 'bs-popover'; + var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); + + var Default = _objectSpread({}, Tooltip.Default, { + placement: 'right', + trigger: 'click', + content: '', + template: '' + }); + + var DefaultType = _objectSpread({}, Tooltip.DefaultType, { + content: '(string|element|function)' + }); + + var ClassName = { + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + TITLE: '.popover-header', + CONTENT: '.popover-body' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + INSERTED: "inserted" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + FOCUSOUT: "focusout" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Popover = + /*#__PURE__*/ + function (_Tooltip) { + _inheritsLoose(Popover, _Tooltip); + + function Popover() { + return _Tooltip.apply(this, arguments) || this; + } + + var _proto = Popover.prototype; + + // Overrides + _proto.isWithContent = function isWithContent() { + return this.getTitle() || this._getContent(); + }; + + _proto.addAttachmentClass = function addAttachmentClass(attachment) { + $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); + }; + + _proto.getTipElement = function getTipElement() { + this.tip = this.tip || $$$1(this.config.template)[0]; + return this.tip; + }; + + _proto.setContent = function setContent() { + var $tip = $$$1(this.getTipElement()); // We use append for html objects to maintain js events + + this.setElementContent($tip.find(Selector.TITLE), this.getTitle()); + + var content = this._getContent(); + + if (typeof content === 'function') { + content = content.call(this.element); + } + + this.setElementContent($tip.find(Selector.CONTENT), content); + $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); + }; // Private + + + _proto._getContent = function _getContent() { + return this.element.getAttribute('data-content') || this.config.content; + }; + + _proto._cleanTipClass = function _cleanTipClass() { + var $tip = $$$1(this.getTipElement()); + var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); + + if (tabClass !== null && tabClass.length > 0) { + $tip.removeClass(tabClass.join('')); + } + }; // Static + + + Popover._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' ? config : null; + + if (!data && /destroy|hide/.test(config)) { + return; + } + + if (!data) { + data = new Popover(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Popover, null, [{ + key: "VERSION", + // Getters + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "NAME", + get: function get() { + return NAME; + } + }, { + key: "DATA_KEY", + get: function get() { + return DATA_KEY; + } + }, { + key: "Event", + get: function get() { + return Event; + } + }, { + key: "EVENT_KEY", + get: function get() { + return EVENT_KEY; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Popover; + }(Tooltip); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + + $$$1.fn[NAME] = Popover._jQueryInterface; + $$$1.fn[NAME].Constructor = Popover; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Popover._jQueryInterface; + }; + + return Popover; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): scrollspy.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var ScrollSpy = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'scrollspy'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.scrollspy'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Default = { + offset: 10, + method: 'auto', + target: '' + }; + var DefaultType = { + offset: 'number', + method: 'string', + target: '(string|element)' + }; + var Event = { + ACTIVATE: "activate" + EVENT_KEY, + SCROLL: "scroll" + EVENT_KEY, + LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + DROPDOWN_ITEM: 'dropdown-item', + DROPDOWN_MENU: 'dropdown-menu', + ACTIVE: 'active' + }; + var Selector = { + DATA_SPY: '[data-spy="scroll"]', + ACTIVE: '.active', + NAV_LIST_GROUP: '.nav, .list-group', + NAV_LINKS: '.nav-link', + NAV_ITEMS: '.nav-item', + LIST_ITEMS: '.list-group-item', + DROPDOWN: '.dropdown', + DROPDOWN_ITEMS: '.dropdown-item', + DROPDOWN_TOGGLE: '.dropdown-toggle' + }; + var OffsetMethod = { + OFFSET: 'offset', + POSITION: 'position' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var ScrollSpy = + /*#__PURE__*/ + function () { + function ScrollSpy(element, config) { + var _this = this; + + this._element = element; + this._scrollElement = element.tagName === 'BODY' ? window : element; + this._config = this._getConfig(config); + this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS); + this._offsets = []; + this._targets = []; + this._activeTarget = null; + this._scrollHeight = 0; + $$$1(this._scrollElement).on(Event.SCROLL, function (event) { + return _this._process(event); + }); + this.refresh(); + + this._process(); + } // Getters + + + var _proto = ScrollSpy.prototype; + + // Public + _proto.refresh = function refresh() { + var _this2 = this; + + var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION; + var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; + var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0; + this._offsets = []; + this._targets = []; + this._scrollHeight = this._getScrollHeight(); + var targets = [].slice.call(document.querySelectorAll(this._selector)); + targets.map(function (element) { + var target; + var targetSelector = Util.getSelectorFromElement(element); + + if (targetSelector) { + target = document.querySelector(targetSelector); + } + + if (target) { + var targetBCR = target.getBoundingClientRect(); + + if (targetBCR.width || targetBCR.height) { + // TODO (fat): remove sketch reliance on jQuery position/offset + return [$$$1(target)[offsetMethod]().top + offsetBase, targetSelector]; + } + } + + return null; + }).filter(function (item) { + return item; + }).sort(function (a, b) { + return a[0] - b[0]; + }).forEach(function (item) { + _this2._offsets.push(item[0]); + + _this2._targets.push(item[1]); + }); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(this._scrollElement).off(EVENT_KEY); + this._element = null; + this._scrollElement = null; + this._config = null; + this._selector = null; + this._offsets = null; + this._targets = null; + this._activeTarget = null; + this._scrollHeight = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {}); + + if (typeof config.target !== 'string') { + var id = $$$1(config.target).attr('id'); + + if (!id) { + id = Util.getUID(NAME); + $$$1(config.target).attr('id', id); + } + + config.target = "#" + id; + } + + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._getScrollTop = function _getScrollTop() { + return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; + }; + + _proto._getScrollHeight = function _getScrollHeight() { + return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); + }; + + _proto._getOffsetHeight = function _getOffsetHeight() { + return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; + }; + + _proto._process = function _process() { + var scrollTop = this._getScrollTop() + this._config.offset; + + var scrollHeight = this._getScrollHeight(); + + var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); + + if (this._scrollHeight !== scrollHeight) { + this.refresh(); + } + + if (scrollTop >= maxScroll) { + var target = this._targets[this._targets.length - 1]; + + if (this._activeTarget !== target) { + this._activate(target); + } + + return; + } + + if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { + this._activeTarget = null; + + this._clear(); + + return; + } + + var offsetLength = this._offsets.length; + + for (var i = offsetLength; i--;) { + var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); + + if (isActiveTarget) { + this._activate(this._targets[i]); + } + } + }; + + _proto._activate = function _activate(target) { + this._activeTarget = target; + + this._clear(); + + var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style + + + queries = queries.map(function (selector) { + return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]"); + }); + var $link = $$$1([].slice.call(document.querySelectorAll(queries.join(',')))); + + if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { + $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); + $link.addClass(ClassName.ACTIVE); + } else { + // Set triggered link as active + $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active + // With both
      and