<template> <iframe v-if="campaign?.banner?.type === 'html'" ref="iframe" :width="campaign.banner.width" :height="campaign.banner.height" :src="getSource(campaign)" scrolling="none" marginwidth="0" marginheight="0" class="campaign frame" data-umami-event="campaign-click" :data-umami-event-campaign-id="`${campaign.entity.slug}-${campaign.id}`" /> <a v-else-if="campaign" :href="campaign.url || campaign.affiliate?.url" target="_blank" class="campaign" data-umami-event="campaign-click" :data-umami-event-campaign-id="`${campaign.entity.slug}-${campaign.id}`" > <img :src="getSource(campaign)" :width="campaign.banner.width" :height="campaign.banner.height" class="campaign-banner" > </a> </template> <script> function ratioFilter(banner) { if (!banner) { return false; } if (this.minHeight && banner.height < this.minHeight) { return false; } if (this.maxHeight && banner.height > this.minHeight) { return false; } if (banner.type === 'html' && banner.width > window.innerWidth) { // usually non-scalable iframes return false; } if (this.minRatio && banner.ratio < this.minRatio) { return false; } if (this.maxRatio && banner.ratio > this.maxRatio) { return false; } return true; } function getSource(campaign) { if (campaign.banner.entity.type === 'network' || !campaign.banner.entity.parent) { return `/banners/${campaign.banner.entity.slug}/${campaign.banner.id}.${campaign.banner.type || 'jpg'}`; } if (campaign.banner.entity.type === 'channel' && campaign.banner.entity.parent?.type === 'network') { return `/banners/${campaign.banner.entity.parent.slug}/${campaign.banner.entity.slug}/${campaign.banner.id}.${campaign.banner.type || 'jpg'}`; } return null; } function entityCampaign() { const bannerCampaigns = this.entity.campaigns .concat(this.entity.children?.flatMap((child) => child.campaigns)) .concat(this.entity.parent?.campaigns) .filter((campaignX) => campaignX && this.ratioFilter(campaignX.banner)); if (bannerCampaigns.length > 0) { const randomCampaign = bannerCampaigns[Math.floor(Math.random() * bannerCampaigns.length)]; this.campaign = randomCampaign; this.$emit('campaign', randomCampaign); return randomCampaign; } if (this.allowGeneric) { return this.genericCampaign(); } this.$emit('campaign', null); return null; } function tagCampaign() { const campaignBanners = this.tag.banners.filter((banner) => banner.campaigns.length > 0 && this.ratioFilter(banner)); const banner = campaignBanners[Math.floor(Math.random() * campaignBanners.length)]; if (banner?.campaigns.length > 0) { const randomCampaign = { ...banner.campaigns[Math.floor(Math.random() * banner.campaigns.length)], banner, }; this.campaign = randomCampaign; this.$emit('campaign', randomCampaign); return randomCampaign; } if (this.allowGeneric) { return this.genericCampaign(); } this.$emit('campaign', null); return null; } async function genericCampaign() { const randomCampaign = await this.$store.dispatch('fetchRandomCampaign', { minRatio: this.minRatio, maxRatio: this.maxRatio }); this.campaign = randomCampaign; this.$emit('campaign', randomCampaign); return randomCampaign; } async function specificCampaign(campaignId) { const campaign = await this.$store.dispatch('fetchCampaign', campaignId); this.campaign = campaign; this.$emit('campaign', campaign); return campaign; } async function mounted() { if (this.$route.query.campaign) { await this.specificCampaign(this.$route.query.campaign); return; } if (this.entity) { await this.entityCampaign(); return; } if (this.tag) { await this.tagCampaign(); return; } await this.genericCampaign(); } export default { props: { entity: { type: Object, default: null, }, tag: { type: Object, default: null, }, minHeight: { type: Number, default: null, }, maxHeight: { type: Number, default: null, }, minRatio: { type: Number, default: null, }, allowGeneric: { type: Boolean, default: false, }, maxRatio: { type: Number, default: null, }, }, emits: ['campaign'], data() { return { campaign: null, }; }, mounted, methods: { entityCampaign, genericCampaign, getSource, ratioFilter, specificCampaign, tagCampaign, }, }; </script> <style lang="scss" scoped> .campaign { display: inline-flex; align-items: center; justify-content: center; border: none; } .campaign-banner { height: auto; width: auto; max-height: 100%; max-width: 100%; } .frame-container { position: relative; font-size: 0; } .frame-target { width: 100%; height: 100%; position: absolute; top: 0; left: 0; } </style>