marrioa
marrioa

Reputation: 1275

JS:How to turn any value to be a hyperlink via HTML form

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);
}

enter image description here

Upvotes: 0

Views: 291

Answers (2)

Danziger
Danziger

Reputation: 21161

🌈 What you need to do

In order to do that you would have to load that page and get its <title> element.

❌ Fetching the page from the frontend

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" />

🌎 Using an API

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/"
        }
      }
    }
    

✨ Working example

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>

🛠️ Building your own API/proxy

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

user5734311
user5734311

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

Related Questions