const ChannelItem = { props: ['channel'], template: `

` } const CountryItem = { components: { ChannelItem }, props: ['channels', 'normQuery', 'regQuery', 'country'], template: `
{{country.flag}} {{country.name}}
Name TVG-ID EPG
` } const App = { compilerOptions: { isCustomElement: tag => tag.startsWith('ion-') }, components: { CountryItem }, data() { return { isLoading: true, query: '', normQuery: '', regQuery: null, countries: [], channels: [], scrollTop: 0 } }, computed: { filtered() { if (!this.normQuery) return this.channels return this.channels.filter(c => { const normResult = c.key.includes(this.normQuery) const regResult = this.regQuery ? this.regQuery.test(c.name) || this.regQuery.test(c.id) : false return normResult || regResult }) }, grouped() { return _.groupBy(this.filtered, 'country') } }, methods: { search() { this.normQuery = this.query.replace(/\s/g, '').toLowerCase() this.regQuery = new RegExp(this.query) }, scrollToTop() { document.body.scrollTop = 0 document.documentElement.scrollTop = 0 }, onScroll(e) { this.scrollTop = window.top.scrollY }, async loadChannels() { let guides = await fetch('https://iptv-org.github.io/api/guides.json') .then(response => response.json()) .catch(console.log) guides = guides.length ? guides : [] guides = _.groupBy(guides, 'channel') this.channels = await fetch('https://iptv-org.github.io/api/channels.json') .then(response => response.json()) .then(arr => arr.map(c => { c.key = `${c.id}_${c.name}`.replace(/\s/g, '').toLowerCase() c.guides = guides[c.id] || [] return c }) ) .catch(err => { console.log(err) return [] }) const countries = await fetch('https://iptv-org.github.io/api/countries.json') .then(response => response.json()) .catch(console.log) this.countries = countries.map(i => { i.expanded = false return i }) } }, beforeDestroy() { window.removeEventListener('scroll', this.onScroll) }, async mounted() { window.addEventListener('scroll', this.onScroll) await this.loadChannels() this.isLoading = false } } Vue.createApp(App).mount('#app')