How do I Get a website's favicon using JavaScript? - javascript

I am wondering if it is possible to get a website's favicon by a URL with JavaScript.
For example, I have the URL http://www.bbc.co.uk/ and I would like to get the path to the favicon described in <link rel="icon" .../> meta tag - http://www.bbc.co.uk/favicon.ico.
I have many URLs so that should not load every page and search for link tag I think.
Any ideas?

Here are 2 working options, I tested over 100 urls and got different results which each option.
Please note, this solution is not JS, but JS may not be necessary.
<!-- Free -->
<img height="16" width="16" src='http://www.google.com/s2/favicons?domain=www.edocuments.co.uk' />
<!-- Paid -->
<img height="16" width="16" src='http://grabicon.com/edocuments.co.uk' />

Suddenly I found something called Google Shared Stuff that returns image with website's favicon by hostname:
http://www.google.com/s2/favicons?domain=www.domain.com
But fot BBC site it returns favicon a bit small. Compare:
http://www.google.com/s2/favicons?domain=www.bbc.co.uk
http://www.bbc.co.uk/favicon.ico

You could use YQL for that
http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D"http://bbc.co.uk/"and%20xpath%3D"/html/head/link[#rel%3D'icon']%20|%20/html/head/link[#rel%3D'ICON']%20|%20/html/head/link[#rel%3D'shortcut%20icon']%20|%20/html/head/link[#rel%3D'SHORTCUT%20ICON']"&format=json&callback=grab
This query used by Display Feed Favicons Greasemonkey script.
You can write queries in YQL console, but it requires to login (btw, using queries don't):
http://developer.yahoo.com/yql/console/#h=select%20*%20from%20html%20where%20url%3D%22http%3A//bbc.co.uk/%22and%20xpath%3D%22/html/head/link%5B#rel%3D%27icon%27%5D%20%7C%20/html/head/link%5B#rel%3D%27ICON%27%5D%20%7C%20/html/head/link%5B#rel%3D%27shortcut%20icon%27%5D%20%7C%20/html/head/link%5B#rel%3D%27SHORTCUT%20ICON%27%5D%22
It is better than http://www.google.com/s2/favicons?domain=www.domain.com
, in case favicon exists, but doesn't located in domain.com/favicon.ico

After 30.000 to 40.000 tests I noticed that you really encounter lots of different situations which have to be worked against.
The starting point is ofcourse somewhere to only look at the rel tag in there and fetch this, but along the way you will find more and more situations you will have to cover.
In case anyone will look at this thread and tries to come closer to 100% perfection I uploaded my (PHP) code here: https://plugins.svn.wordpress.org/wp-favicons/trunk/includes/server/class-http.php. This is part of a (GPL) WordPress Plugin that retrieves Favicons, more or less on request back then, out of limitations of the standard Google one (as mentioned above). The code finds a substantially amount more icons that the code of Google. But also includes google and others as image providers to shortcut further iterations on trying to retrieve the icon.
When you read through the code you will probably see some situations that you will encounter e.g. base64 data uris, pages redirecting to 404 pages or redirecting a gazillion times, retrieving weird HTTP status codes and having to check every possible HTTP return code for validness, the icons themselves that have a wrong mime type, client side refresh tags, icons in the root folder and none in the html code, etc... etc... etc...
If you go up a directory you will find other classes that then are ment to store the actual icons against their url (and ofcourse you will then need to find out which "branches" use the same favicon and which not, and find out if they belong to the same "owner" or are really different parts but under the same domain.

These days I thought that GitHub's service did a much better job than Google's:
https://favicons.githubusercontent.com/microsoft.com
Though neither are perfect it seems.
For stackoverflow:
Works: https://www.google.com/s2/favicons?domain=stackoverflow.com
Does not work: https://favicons.githubusercontent.com/stackoverflow.com
For GitHub:
Does not work: https://www.google.com/s2/favicons?domain=github.com
Works: https://favicons.githubusercontent.com/github.com
Here is an article I wrote about a solution that can fetch favicons from multiple source.
Here is the source code:
<!DOCTYPE html>
<html>
<body style="background-color:grey;">
<script type="text/javascript">
const KRequestFaviconGitHub = 'https://favicons.githubusercontent.com/';
const KRequestFaviconGoogle = 'https://www.google.com/s2/favicons?domain=';
const KDefaultUrl = KRequestFaviconGoogle;
// We rely on pre-defined hostname configurations
const hostnames = {
"stackoverflow.com": { url:KRequestFaviconGoogle+"stackoverflow.com", invert:0 },
"theregister.co.uk": { url:KRequestFaviconGoogle+"theregister.co.uk", invert:1 },
"github.com": { url:KRequestFaviconGitHub+"github.com", invert:1 },
"android.googlesource.com": { url:KRequestFaviconGoogle+"googlesource.com", invert:0 },
"developer.android.com": { url:KRequestFaviconGitHub+"developer.android.com", invert:0 }
};
document.addEventListener('DOMContentLoaded', function(event) {
addFavicon("stackoverflow.com");
addFavicon("bbc.co.uk");
addFavicon("github.com");
addFavicon("theregister.co.uk");
addFavicon("developer.android.com");
addFavicon("android-doc.github.io");
addFavicon("slions.net");
addFavicon("alternate.de");
addFavicon("amazon.de");
addFavicon("microsoft.com");
addFavicon("apple.com");
addFavicon("googlesource.com");
addFavicon("android.googlesource.com");
addFavicon("firebase.google.com");
addFavicon("play.google.com");
addFavicon("google.com");
addFavicon("team-mediaportal.com");
addFavicon("caseking.de");
addFavicon("developer.mozilla.org");
addFavicon("theguardian.com");
addFavicon("niche-beauty.com");
addFavicon("octobre-editions.com");
addFavicon("dw.com");
addFavicon("douglas.com");
addFavicon("douglas.de");
addFavicon("www.sncf.fr");
addFavicon("paris.fr");
addFavicon("bahn.de");
addFavicon("hopfully.that.domain.does.not.exists.nowaythisisavaliddomain.fart");
});
/**
*
*/
function addFavicon(aDomain)
{
var a = document.createElement("a");
a.href = "http://" + aDomain;
//a.style.display = "block";
var div = document.createElement("div");
div.innerText = aDomain;
div.style.verticalAlign = "middle";
div.style.display = "inline-block";
var img = document.createElement("img");
img.className = "link-favicon";
img.style.width = "16px";
img.style.height = "16px";
img.style.verticalAlign = "middle";
img.style.display = "inline-block";
img.style.marginRight = "4px";
a.prepend(img);
a.appendChild(div);
document.body.appendChild(a);
document.body.appendChild(document.createElement("p"));
const conf = hostnames[aDomain]
if (conf==null)
{
img.src = KDefaultUrl+aDomain;
}
else
{
img.src = conf.url;
img.style.filter = "invert(" + conf.invert + ")";
}
}
</script>
</body>
</html>

Related

List of .png files in html and js

I am trying to create a something in my project, that display the images that ends with .png
Currently, I have this part of code :
<h2>Files list :</h2>
<p id="list"></p>
<script>
import 'path';
const EXTENSION = '.png';
const targetFiles = files.filter(file => {
return path.extname(file).toLowerCase() === EXTENSION;
});
if(targetFiles == "") {
document.getElementById("list").innerHTML = "No images found.";
} else {
document.getElementById("list").innerHTML = targetFiles;
}
</script>
The issue here is that I can't find an alternative solution for the path package that is working for web and can help me with this.
You cannot access any file system through a web application, client or server, no matter how "localy on a pc" it will be.
To do the kind of thing you're describing, you need a second application to handle the file system lookup and/or transfer (presumably, you also want to see the images, right?). And then the two applications can talk over AJAX calls or web-sockets to request the look ups and download the needed files.
step 1 for HTML
img src= for pic
step 2
use the internet to look for picture or go to gallery to find a picture go to your file
step3
use the img src for the picture
example
img src =a

Vue - Set different favicon when browser online or offline

I am trying to set different icons for when my browser is online(Normal logo) and offline(Greyed out logo). I am using Vue JS and I am able to detect online and offline set, I am also able to set different favicon for the different state but the offline icon won't show because my browser does not have internet to fetch the icon.
What is the best approach to achieve this? The code I am using is below, btw I am using 'v-offline' to detect online or offline states
handleConnectivityChange (status) {
status ? $('#favicon').attr('href', 'https://snackify-cdn.sfo2.digitaloceanspaces.com/favicon-on.png') : $('#favicon').attr('href', 'https://snackify-cdn.sfo2.digitaloceanspaces.com/favicon-off.png')
}
There are two elements to this, preloading the favicons, and setting them dynamically.
The first part can be achieved in various ways. I would opt for the Vue created method as you could show a spinner on the page until the component is mounted. This would probably be better suited as a mixin, instead of directly on the component.
data() {
return {
favicons: {} // we need to store the images to prevent the browser releasing them
}
},
created () {
// This can be improved but the logic is here
// Create the JS images
this.favicons = {
'online': new Image(),
'offline': new Image()
};
// Set the source properties
this.favicons.online.src = 'https://snackify-cdn.sfo2.digitaloceanspaces.com/favicon-on.png';
this.favicons.offline.src = 'https://snackify-cdn.sfo2.digitaloceanspaces.com/favicon-off.png';
}
Then, to update the favicon, you can do something along the lines of the following:
handleConnectivityChange (status) {
// Get or create the favicon
let link = document.querySelector("link[rel*='icon']") || document.createElement('link');
// Set the attributes of the favicon
link.type = 'image/x-icon';
link.rel = 'shortcut icon';
link.href = status ? this.favicons.online.src : this.favicons.offline.src;
// Append the favicon to the `head`
document.getElementsByTagName('head')[0].appendChild(link);
}
Credit to: Changing website favicon dynamically
As a side note, and this is just my opinion, I would advise dropping jQuery if you are using Vue. There is very little need for it and it just adds to the overhead. In the scenario here, you can very easily use vanilla JS to achieve what you need as the example demonstrates...

Images aren't displaying on github pages

I'm using github pages to host a practice website. I've built a simple JS slideshow and the images in the slideshow are not displaying. When I use Atom live server to display the site, the images and slideshow work fine. When using github pages I inspected the active slideshow and it is moving through the image array fine as I can see the src attribute changing the way it should so I know the code is looping through the array properly. I'm not sure what is wrong.
the relevant JavaScript
const image = [
'../images/karakoy-1.jpg',
'../images/karakoy-2.jpg',
'../images/karakoy-3.jpg',
'../images/karakoy-4.jpg',
'../images/karakoy-5.jpg',
];
let i = 0;
const imageContainer = document.getElementsByClassName('slideshow-image');
const time = 3000;
function changeSlide() {
imageContainer[0].src = image[i];
if (i < image.length - 1) {
i++;
} else {
i = 0;
}
setTimeout('changeSlide()', time);
}
changeSlide();
I've also checked all the spelling and capitilization on the filenames. Everything checks out. Like I said, when I use Atom live server everything works fine.
UPDATE https://jtc10.github.io/Arcadia-Restaurant/
Here is a link to the page. Click the "reservations" link. The slideshow is on that page.
It's most likely an issue resolving relative paths between your local and live servers.
The requests with the relative paths are all returning 404 Not Found:
I prefer to use the full path from root instead. This takes the ambiguity out of the situation.
const image = [
'/images/karakoy-1.jpg',
'/images/karakoy-2.jpg',
'/images/karakoy-3.jpg',
'/images/karakoy-4.jpg',
'/images/karakoy-5.jpg',
];
It tries to load https://jtc10.github.io/images/karakoy-2.jpg which don't exist, remove the ../ from the image path.

Name html blob urls for easy reference

Within our web application we load a lot of content from package files (zipped packages containing html, js, css, images and so on.) The module loader (client side JS) processes the packages and makes the content available to the DOM using blob urls.
While this works very nice, it's sometimes tedious to find the right piece of JavaScript file for debugging.
IE: in chrome in the development console->sources all blob urls are listed under (no domain) and have random names such as:
blob:https://example.com/0613efd7-6977-4872-981f-519eea0bc911
In a normal production environment there are roughly 100 lines like this, so finding the right one might take some time.
I'd pretty much like to name the blob urls, or do something to make them easier to find for debugging purposes. This seems possible since WebPack is doing something like this, however i can't seem to find how. Is there anybody that can hint me in the right direction.
Ok, the way I would do it is have some global that keeps a track of the URL's, using a simple reverse map.
One problem of course with this is that references to a blob that no longer exists will be kept in memory, but if say you was only enabling this for debugging purposes this might not be a problem.
var namedblobs = {};
function addNamedBlob(name, uri) {
namedblobs[uri] = name;
}
function getNamedBlob(uri) {
return namedblobs[uri];
}
function createSomeBlob() {
//for testing just a random number would do
return Math.random().toString();
}
var blob = createSomeBlob();
addNamedBlob("test1", blob);
addNamedBlob("test2", createSomeBlob());
console.log(getNamedBlob(blob)); //should be test1
Finally i have found a solution that works to my liking. For our application we already used a serviceworker which has caching active. So i ended up writing the module files into the serviceworker cache whenever somebody has debug mode turned on.
Since the url portion of the resource files is static this way, all the nice browser features such as breakpoints are now useable again.
Below i've posted the relevant code of the serviceworker. The rest of the code is just plain serviceworker caching.
api.serveScript = function(module, script, content){
try{
content = atob(content);
} catch(err){}
return new Promise(function(resolve, reject){
var init = {
status: 200,
statusText: "OK",
headers: {'Content-Type': 'text/javascript'}
};
caches.open("modulecache-1").then(function(cache) {
console.log('[ServiceWorker] Caching ' + module + "/" + script);
cache.put("/R/" + module + "/script/" + script, new Response(content, init));
resolve("/R/" + module + "/script/" + script);
});
});
}
Thanks for your answers and help. I hope this solution is going to help some others too.
#Keith's option is probably the best one. (create a Map of your blobURIs and easy to read file names).
You could also do a dynamic router that will point some nice url to the blobURIs, but if you are open to do this, then just don't use blobURIs.
An other hackish workaround, really less cleaner than the Map, would be to append a fragment identifier to your blobURI blob:https://example.com/0613efd7-6977-4872-981f-519eea0bc911#script_name.js.
Beware, This should work for application/javascript Blobs or some other resource types, but not for documents (html/svg/...) where this fragment identifier has a special meaning.
var hello = new Blob(["alert('hello')"], {type:'application/javascript'});
var script = document.createElement('script');
script.src = URL.createObjectURL(hello) + '#hello.js';
document.head.appendChild(script);
console.log(script.src);
var css = new Blob(["body{background:red}"], {type:'text/css'});
var style = document.createElement('link');
style.href = URL.createObjectURL(css) + '#style.css';
style.rel = 'stylesheet';
document.head.appendChild(style);
console.log(style.href);
And as a fiddle for browsers which doesn't like null origined StackSnippet's iframes.

How to get all images from a website and replace them with base64 encodings?

How to get all images from a specific website and replace them with base64 encodings?
Server-side solutions would work.
like:
var img = document.querySelectorAll("img");
for (var i = 0; i < img.length; i++) {
//replace with base64 encoding
}
Why: I wanted to create an e-book (mobi) based on a RSS feed. I already converted the content to HTML but the images need to be local for display. Replacing the images base64 looked like the best solution.
First—and I'm not sure that this specifically applies to your situation—remember that data URIs aren't supported by IE ≤ 7 and IE 8's support is shaky; and that there can be many disadvantages to using data URIs.
That said, there are two places to worry about: <img> tags and CSS files.
I found this tool that will replace all image references in a stylesheet with its data URI representation.
I didn't see anything to do the same for <img>s in a HTML page, but it wouldn't be hard to build something that does what you need.
Alternatively—and considering that base64-encoding all of your images will bloat filesize by 33%—you could use the HTML5 app cache, which is designed for running HTML pages offline and works in everything but IE ≤ 9. (This is the approach I'd use.)
Just add a manifest attribute to the <html> element:
<html manifest="files.appcache">
...
</html>
files.appcache is a simple text file:
CACHE MANIFEST
http://www.example.com/index.html
http://www.example.com/header.png
http://www.example.com/blah/blah
The MDN article about app caches has much more in-depth information.
Something like this:
jQuery + canvas:
$("img").load(function(i) {
var $this = $(this),
jCanvas = $("<canvas width='" + $this.width() + "' height='" + $this.height() + "'/>"),
oCanvas = jCanvas[0];
oCanvas.getContext("2d").drawImage(this, 0, 0);
this.src = oCanvas.toDataURL();
});
But this will only work if the image is on the same domain as the script.
Demo: http://jsfiddle.net/K5RY3/3/

Categories

Resources