Reputation: 1275
I want to turn any value added to the form to be link with title (hyperlink)
for example:
Value: https://www.udemy.com/
Result (hyperlink): Udemy: Online Courses - Learn Anything, On Your Schedule
this is my code
HTML
<div class="container">
<form action="" class="addform">
<div class="input-group mb-3">
<input type="url" class="form-control" id="item" aria-describedby="emailHelp" placeholder="Enter link"> <div class="input-group-append">
<button class="btn btn-primary" id="addItem" type="button">Submit</button>
</div>
</div>
</form>
</div>
JS
document.getElementById('addItem').addEventListener('click', function() {
var value = document.getElementById('item').value;
if (value) addItemToList(value);
});
function addItemToList(text) {
var list = document.getElementById('linkss')
var item = document.createElement('li');
item.innerHTML = text;
var buttons = document.createElement('linkss');
buttons.classList.add('buttons')
var remove = document.createElement('button');
remove.classList.add('remove');
// remove.innerHTML = removeIcon;
var add = document.createElement('button');
add.classList.add('add');
// buttons.appendChild(remove);
item.appendChild(buttons);
list.appendChild(item);
}
Upvotes: 0
Views: 291
Reputation: 21161
In order to do that you would have to load that page and get its <title>
element.
You might try to do that in two different ways:
With an AJAX GET request to get the content of the page, in which case you will get a CORS error:
Failed to load https://www.udemy.com/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://stackoverflow.com' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
fetch('https://www.udemy.com');
Using an <iframe>
, in which case you will get an X-Frame-Options
error:
Refused to display 'https://www.udemy.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
<iframe src="https://udemy.com" />
The right way to do this would be to use a proxy/API that would make that same GET request for you, get the title of the page and send it back. For example:
Textance: A simple API that will just retrieve the title of the page. This one is just an example, as you would also get an Access-Control-Allow-Origin
error if you try to use it on your page.
For example, https://textance.herokuapp.com/rest/title/http%3A%2F%2Fudemy.com returns the text:
Online Courses - Learn Anything, On Your Schedule | Udemy
URL Meta: Another API that returns additional metadata and is publicly available, so you can use this one directly from your application, but it's a bit slower and it can be down sometimes.
For example, https://url-meta.herokuapp.com/?url=http%3A%2F%2Fwww.udemy.com returns the following JSON response:
{
"result": {
"status": "OK"
},
"meta": {
"url": "http://udemy.com",
"type": "text/html",
"title": "Online Courses - Learn Anything, On Your Schedule | Udemy",
"image": "https://www.udemy.com/staticx/udemy/images/v6/logo-coral.svg",
"description": "Udemy is an online learning and teaching marketplace with over 65,000 courses and 15 million students. Learn programming, marketing, data science and more.",
"favicon": "https://www.udemy.com/staticx/udemy/images/v6/favicon-128.png",
"feed": {
"link": "http://udemy.com/"
}
}
}
To use it, just make a GET request with the URL you want to get the title from. For example, using the Fetch API, which is not supported in IE:
const input = document.getElementById('input');
const list = document.getElementById('list');
document.getElementById('add').onclick = () => {
let url = input.value;
if (!url) return;
if (url.indexOf('http') !== 0) {
// Make sure the url we send always starts with http or https:
url = `http://${ url }`;
}
// Clear input field:
input.value = '';
const li = document.createElement('li');
// Create a new entry in the list indicating we are still loading the title:
li.innerText = `Loading title for ${ url }...`;
list.appendChild(li);
// Request the actual title of that URL from the URL Meta API:
fetch(`https://url-meta.herokuapp.com/?url=${ encodeURIComponent(url) }`)
.then(res => res.json())
.then(data => {
// Once we get a response back, update the text/HTML inside the <li> we have just added
// with the right text and <a> or an error message:
if (data.result.status === 'ERROR') {
li.innerText = `There was an error loading ${ url }: ${ data.result.reason }`;
} else {
li.innerHTML = `<a href="${ url }">${ data.meta.title }</a>`;
}
}).catch(() => {
li.innerText = `There was an error loading ${ url }.`;
});
};
body {
margin: 0;
font-family: monospace;
line-height: 15px;
}
#menu {
position: fixed;
top: 0;
left: 0;
width: 100%;
display: flex;
border-bottom: 3px solid #000;
height: 33px;
}
#input,
#add {
border: 0;
outline: none;
padding: 4px 8px;
box-sizing: border-box;
background: #FFF;
font-family: monospace;
text-align: left;
}
#input {
width: 70%;
border-right: 3px solid #000;
}
#add {
width: 30%;
}
#input:hover,
#add:hover {
background: #EEE;
}
#list {
list-style: none;
margin: 0;
padding: 35px 0 0;
}
#list > li {
border-bottom: 1px solid #000;
padding: 10px;
}
#list > li > a {
word-break: break-word;
word-break: break-all;
}
<header id="menu">
<input id="input" type="text" placeholder="URL" value="http://www.udemy.com" />
<button id="add">ADD LINK</button>
</header>
<ul id="list"></ul>
Alternatively, you could implement your own proxy/API. This would be a good starting point: Getting the page title from a scraped webpage
Upvotes: 2
Reputation:
The main issue here is finding a way to grab the title without CORS preventing it. One way to solve this is to use a CORS proxy, or an API that allows CORS requests and provides website info.
Here's an implementation that also fixes adding an actual link / <a>
.
getTitle
uses the fetch
API to make the request and extract the title from the returned JSON.
In the click listener, the Promise returned by getTitle
passes the title on to addItemToList
, which does exactly that, creating the elements in the process.
Creating and adding elements is easier / less tedious with jQuery, which is required by Bootstrap anyway. I've used Vanilla JS though since you didn't use jQuery.
document.getElementById('addItem').addEventListener('click', function() {
var url = document.getElementById('item').value;
if (url) getTitle(url).then(title => addItemToList(url, title));
});
function getTitle(url) {
return fetch("https://api.urlmeta.org/?url=" + url).then(response => response.json()).then(info => info.meta.title);
}
function addItemToList(url, title) {
// create <a>
var a = document.createElement('a');
a.innerHTML = title;
a.href = url;
a.target = "_blank";
var list = document.getElementById('links')
var li = document.createElement('li');
li.classList.add('list-group-item');
var remove = document.createElement('button');
remove.classList.add('btn');
remove.classList.add('remove');
remove.classList.add('float-right');
remove.innerHTML = "X";
let p = li;
remove.onclick = function() {
list.removeChild(p);
};
li.appendChild(a);
li.appendChild(remove);
list.appendChild(li);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
<div class="container">
<form action="" class="addform">
<div class="input-group mb-3">
<input type="url" class="form-control" id="item" aria-describedby="emailHelp" placeholder="Enter link" value="https://udemy.com">
<div class="input-group-append">
<button class="btn btn-primary" id="addItem" type="button">Submit</button>
</div>
</div>
</form>
</div>
<div class="container">
<ul id="links" class="list-group">
</ul>
</div>
Upvotes: 1