I am fetching all the websites links and putting them into a array where I will eventually compare them with a JSON list. I need the websites to be shortened down to
Examples (What I'm trying to get the array to look like)
google.com
computers.intercom-clicks.com
mad-websites.ru
just-eat.com
Example links
https://mad-websites.ru/via/e?ob=RohpF3uuLGksOJfxJOwcgRL5vknYi4kC2aQRzvu2v3s%3D&h=04ce1caed8c7cf4b69d751230eaf7a2450660d67-o26qxr01_77963700909352&l=6ef96bea4775c44a5bc10cdaa661c5053819c0b8-7456283
https://notifications.google.com/g/p/AD-FnEwlAH83isfsH0zLOoNuynSmz1pMuK9Y8guqew5CkdyaEu28Zu30iRcw-SI6y7LRO7v8Tqy6p_9LhGcQClO1e2P5WYSVNa9dWPVhmA
https://finance.rambler.ru/?utm_source=head&utm_campaign=self_promo&utm_medium=topline&utm_content=finance_media
https://www.google.com/covid19?utm_source=Google-Maps-timeline&utm_medium=email&utm_campaign=COVID-site-promo
My code currently only shortens some websites down while others are still the same. It will also remove any duplicates.
const links = Array.from(document.querySelectorAll(".a3s a")).map(link => {
const url = new URL(link.href);
url.search = '';
return url.toString();
})
//removes duplicate links
const uniq = [...new Set(links)];
//window.alert(uniq);
return warningPopup(uniq);
}
Is this what you look for?
const links = Array.from(document.querySelectorAll(".a3s a")).map(link => {
const url = new URL(link.href);
return url.hostname;
})
//removes duplicate links
const uniq = [...new Set(links)];
document.write(uniq.join(', '))
<div class="a3s">
</div>
Related
I have an API request and I'm generating a HTML content from its data using .map();.
The issue I'm facing is that in the array of objects I have keys that are showing content in one language or another. I need to display specific keys in mapped HTML based on the language of the page.
Example of object key: keyAEN: 'content in EN' for English or keyAFR: 'contenu en français' for French.
My way of solving this isn't the DRY-est and there's some repeating code.
Please check below existing code and let me know what would be a better solution in this case. I would like to avoid generating a long HTML because of different language content in the keys.
// Find page language in URL
const findUrl = window.location.href;
const regex = /\.eu\/(\w{2})\//;
const match = regex.exec(findUrl);
const resultLangUrl = match && match[1];
let pageLang = resultLangUrl.toUpperCase();
let language = pageLang.includes("EN");
let pickContainer = document.querySelector('#container');
// deleting keys not coresponding to page language from the objects
//ex: page language is EN, delete all FR keys
if (pageLang === true) {
data.forEach(object => {
delete object['KeyAFR']
delete object['KeyBFR']
delete object['KeyCFR']
});
//generate html for EN
const generateHtmlEN = data.map(test => {
return `<p>${test.KeyAEN}</p>
<p>${test.KeyBEN}</p>
<p>${test.KeyCEN}</p>`
}).join('');
pickContainer.insertAdjacentHTML('afterbegin', generateHtmlEN);
} else {
data.forEach(object => {
delete object['KeyAEN']
delete object['KeyBEN']
delete object['KeyCEN']
});
//generate html for FR
const generateHtmlFR = data.map(test => {
return `<p>${test.KeyAFR}</p>
<p>${test.KeyBFR}</p>
<p>${test.KeyCFR}</p>`
}).join('');
pickContainer.insertAdjacentHTML('afterbegin', generateHtmlFR);
}
I keep trying to pull the email addresses out of an array of links using filter by text. This is the code I tried that is not working. I'm sure I'm missing something simple, any ideas?
let links = Array.from(document.getElementsByTagName('a'));
let subset = links.filter(getEmails);
function getEmails(email) {
return subset.includes('#');
}
Filter doesn't work like that. The callback for the filter method gets each element.
function getEmailLinks() {
const links = Array.from(document.querySelectorAll('a'));
return links
.map((link) => link.href)
.filter((link) => link.includes('mailto'))
.map((link) => link.split(':')[1])
.filter((email) => email.includes('#'));
}
console.log(getEmailLinks());
mailto
mailto
I have a function that runs before every API request to check if the request is from a valid origin.
I have an array of valid origins
const whitelist = [ 'a.com', 'b.co.uk' ]
const validOrigin = str => {
const url = new URL( str )
return whitelist.includes( url.host )
}
console.log(validOrigin('https://www.a.com'))
It returns false because of the www. I dont want to just add a copy with www. to the array of valid origins. I would like a way that covers this and everything else thats unexpected.
Keeping in mind that, by the rules, www.example.com and example.com are different origins:
If you want to match any origin on the same domain or a subdomain of the domains in the whitelist, then you need to:
Strip off the scheme and port - which you are doing already
Check for an exact match - which you are doing already
Check for a match which ends in . followed by the string (to stop third-party-hacker-a.com matching)
So something like:
const validOrigin = str => {
const url = new URL( str )
const host = url.host;
return whitelist.some( element => {
if (element === host) return true;
return element.endsWith(`.${host}`);
} )
}
you can try something like this
str = str.replace( new RegExp("((http)(s)?:\/\/)?(www.)?","gm"),"")
this will delete the first part of the url
The Array.prototype.includes function only accepts the value to search for, and looks for an exact match.
You would need to use a function that accepts a callback to test the elements - for example, the Array.prototype.findIndex function.
As you mention in the comments, you'll also need to change the whitelist so that you can exclude domains whose name ends with one of your valid domains.
const whitelist = [ /(^|\.)a\.com$/i, /(^|\.)b\.co\.uk$/i ];
const validOrigin = str => {
const url = new URL(str);
const index = whitelist.findIndex(el => el.test(url.host));
return index !== -1;
};
document.querySelectorAll("#tests > li").forEach(li => {
const str = li.dataset.value;
const result = validOrigin(str);
li.textContent = `${str} = ${result}`;
});
<ul id="tests">
<li data-value="http://a.com/foo"></li>
<li data-value="http://www.a.com/foo"></li>
<li data-value="http://dev.a.com/foo"></li>
<li data-value="http://banana.com/foo"></li>
<li data-value="http://a.com.b.ru/foo"></li>
</ul>
I'm building out a function to handle dynamic phone number swapping, identifying the referral url, mapping through a data set, and then outputting the promoUrl's related phone number. The data is formatted like this:
const phoneNumbers = [
{
promoUrl: '/interior-doors/',
promoNumber: '589-918-0710',
},
{
promoUrl: '/promo4/',
promoNumber: '307-789-8615',
},
];
And the function maps through the data and reduces it, allowing me to sort through it like this:
const url = location.pathname.replace(/\/+$/, '');
const promoNumber = phoneNumbers.reduce((promoNumber, results) => {
const hasPromo = results.promoUrl.includes(url);
if (hasPromo) {
return results.promoNumber;
}
return promoNumber;
}, '');
I'm having some issues with hasPromo. The way it's built right now allows for the promoUrl to have some variance and still work, meaning as long as it includes what is returned from url then it works i.e. /interior-doors/, /interior-doors, and interior-doors will all work, which is great, but it also works if url is /interior-do. I need it to not do that. It should work independent of formatting, but only return the promoNumber if the string of letters is exact.
I'm assuming this is a regex thing, but I don't know what I'm doing with regex. Any help would be greatly appreciated.
Use == to do an exact match. And since the promoURL property always has / around it, add those delimiters when you set url
const url = '/' + location.pathname.replace(/\/+$/, '') + '/';
const promoNumber = phoneNumbers.reduce((promoNumber, results) => {
const hasPromo = results.promoUrl == url;
if (hasPromo) {
return results.promoNumber;
}
return promoNumber;
}, '');
reduce also seems like the wrong function for this. You just need to find the matching promoUrl, you don't have to continue reducing, since the reduction function doesn't merge the results in any way.
const promo = phoneNumbers.find(({promoUrl}) => promoUrl == url);
const promoNumber = promo ? promo.promoNumber : '';
I am developing a music player using JavaScript and I am trying to add a search bar to my page but every tutorial I have seen so far uses a list created in the HTML page, whereas I have created a list using JavaScript code like this:
const songs = [
"BlindingLights.mp3",
"Boyfriend.mp3",
"DontStartNow.mp3",
"Intentions.mp3",
"Physical"
]
const createSongList = () => {
const list = document.createElement('ol')
for(let i = 0; i<songs.length; i++){
const item = document.createElement('li')
item.appendChild(document.createTextNode(songs[i]))
list.appendChild(item)
}
return list
}
document.getElementById('songList').appendChild(createSongList())
Is there a way I can use the 'songs' array or to develop a search function? Any advice would be appreciated. Thanks! :)
Edit for clarity:
So I have an input tag on my html that I want to use for a search bar, then I want what the user types in to return any matching songs from the songs array. For example if they type in 'Bli' I want it to show the Blinding Lights song.
The code snippet above is how I am currently displaying a list of songs using the array.
This is my input tag:
<input type="text" name="searchBar" id="searchBar" placeholder="Search" onkeyup="searchBar()">
Assuming that you want to filter songs array from a search string, you can use this function :
const songs = [
"BlindingLights.mp3",
"Boyfriend.mp3",
"DontStartNow.mp3",
"Intentions.mp3",
"Physical"
];
const searchSong = (value) => {
return songs.filter(song => song.includes(value));
};
console.log(searchSong('B'));
Maybe you can create a new function search to Array.prototype to make it used more easily
Array.prototype.search = function (keyword) {
return this.filter(text => text.toLowerCase().includes(keyword.toLowerCase().trim()))
}
const songs = [
"BlindingLights.mp3",
"Boyfriend.mp6",
"DontStartNow.mp5",
"Intentions.mp3",
"Physical"
];
songs.search('phy ') // => ["Physical"]
songs.search(' MP3') // => ["BlindingLights.mp3", "Intentions.mp3"]