📜 ⬆️ ⬇️

Dynamic favicon or display karma without refreshing the page

image
For each of us, I believe, several tabs are constantly open in your favorite browser at the same time. More than once there are cases that the tab header is not visible - only favicons . But often they do not provide information other than displaying the site’s logo. And, probably, in vain. But we will try to use this place here (as much as 16px * 16px!) As we want. At the very least, we will know how to do it.

Don't even try to change <link [rel = "icon"] ... />.


Someone may exclaim: “Why is it so difficult? I took the link tag and changed the src in it! ”. But it was not there, comrades. This code will not work:
  1. var oldicons = document .querySelectorAll( 'link[rel="icon"], link[rel="shortcut icon"]' ); for ( var i = 0; i < oldicons.length; i++ ) { oldicons[i].setAttribute( "src" , "/newicon.png" ); }
  2. var oldicons = document .querySelectorAll( 'link[rel="icon"], link[rel="shortcut icon"]' ); for ( var i = 0; i < oldicons.length; i++ ) { oldicons[i].setAttribute( "src" , "/newicon.png" ); }
  3. var oldicons = document .querySelectorAll( 'link[rel="icon"], link[rel="shortcut icon"]' ); for ( var i = 0; i < oldicons.length; i++ ) { oldicons[i].setAttribute( "src" , "/newicon.png" ); }
  4. var oldicons = document .querySelectorAll( 'link[rel="icon"], link[rel="shortcut icon"]' ); for ( var i = 0; i < oldicons.length; i++ ) { oldicons[i].setAttribute( "src" , "/newicon.png" ); }

This one too:
  1. $ ( 'link [rel = "shortcut icon"]' ) .attr ( "src" , "/newicon.png" );

Why so - I will not say (someone will explain?), But it can be done like this (on jQuery):
  1. $ ( 'link [rel $ = icon]' ) .remove ();
  2. $ ( 'head' ) .append ($ ( '<link rel = "shortcut icon" type = "image / x-icon" />' ) .attr ( 'href' , "/newicon.png" ));


That is, we first delete the element, if any, and then add it as a child to the head tag. Instead of remove (), you can also use replaceWith ('') .

Since we need dynamic favicons, we will draw them on canvas, and then use it as favicons.
')
  1. var c = document .createElement ( 'canvas' );
  2. c.height = c.width = 16;
  3. var x = c.getContext ( '2d' );
  4. x.font = '18px bold Calibri' ;
  5. x.fillStyle = '# 000' ;
  6. if (m) {
  7. x.fillText (parseInt (m [1])> 9? '9+' : m [1], 0, 16, 16);
  8. }


Use __defineSetter__


In GMail, the number of new messages is displayed in the header:
(15) - v.pupkin@gmail.com - GMail
Let's extract from there regexp'om tsiferku and get the number of new messages.

To avoid this, you can use Google XML / API, but you need authorization for it, and I will not consider this method, since this is not about GMail mail. And how it is possible to process changes of title of a window, without resorting to different window.setTimeOut. To do this, we will take the Gecko's __defineSetter__ method (read more about it here ).

This method allows you to use an event handler when the data of an element changes (but has not yet changed):
  1. Object.prototype .__ defineSetter __ ( 'Id' , function (data) {
  2. alert ( "hooked data =" + data);
  3. });

This example shows that when the id attribute of the Object element changes (and this can be any tag or global variable), we will be shown an alert alert ("hooked data =" + data);

And let's hang this "handler" on document.title, after which we will perform all of the above actions, thus summing up the first part of the article.
  1. document .__ defineSetter __ ( 'title' , function (v) {
  2. delete document .title; // remove the old "handler"
  3. document .title = v; // intercept new data and put into variable
  4. document .__ defineSetter __ ( 'title' , arguments.callee); // and quickly return the handler to the place
  5. var m = / \ (([0-9] +) \) /. exec (v); // we take a regular bite with the number of messages with a variable
  6. var c = document .createElement ( 'canvas' ); // start the canvas. Create a canvas
  7. c.height = c.width = 16; // and assign it dimensions
  8. var x = c.getContext ( '2d' ); // get context
  9. x.font = '18px bold Calibri' ; // set the font style
  10. x.fillStyle = '# 000' ; // and fill color
  11. if (m) {
  12. x.fillText (parseInt (m [1])> 9? '9+' : m [1], 0, 16, 16); // If qty> 9, then show “9+”
  13. }
  14. var o = document .querySelectorAll ( 'link [rel = "icon"], link [rel = "shortcut icon"]' ); // find all possible favicon tags
  15. for ( var i = 0; i <o.length; i ++) {
  16. o [i] .parentNode.removeChild (o [i]); // and bang them,
  17. }
  18. var n = document .createElement ( 'link' ); // then re-create
  19. n.setAttribute ( 'rel' , 'icon' ); // with the required atrubutsy
  20. n.setAttribute ( 'href' , c.toDataURL ()); // c.toDataURL () gets the finished image on our canvas as text "data: image / png; base64, ......" /
  21. document .querySelector ( 'head' ) .appendChild (n); // well, and finally, apply the newly created favicon to the document. Voila!
  22. });


To check how it works, go to the link , and then to the inbox on GMail. If there are new messages, you will see a counter as a picture of a favion. I worked on Opera and Firefox under Ubuntu. Chrome didn't like the idea.

Where can this be applied?


Yes, wherever you want. For example, in order not to look into the tab, whether there are new messages, you can apply this method. Although, you can use counter type things with Google Labs and gmail-notifier for FF .
But maybe you want to inform your users on your site about something.

Or even enjoy how your karma grows or falls in Habré :)

The last case and take as a basis for another example.

As a "engine" for the script used Greasemonkey . You can use this userscript .

Mapping will work only when you are in a habrocentre (by the way, not only yours). You can simply screw the ajax and get tsiferki not being in your haborcenter, it is on your own. With a great desire, you can screw it to Google Chrome (write an extension) or Opera (for example, the same “javascript bookmark”).

Here is the script itself ( upd: slightly updated):
  1. var c = document .createElement ( "canvas" ); // Use the same canvas
  2. c.height = c.width = 16;
  3. var cx = c.getContext ( "2d" );
  4. cx.beginPath (); // draw a blue square and black text on it
  5. cx.rect (0, 3, 18, 11); // and put them on canvas
  6. cx.fillStyle = "# 6DA3BD" ;
  7. cx.fill ();
  8. cx.font = "10px Normal Tahoma" ;
  9. cx.fillStyle = "#fff" ;
  10. var mark = document .querySelectorAll ( ".mark span" ); // get tsiferki from the page
  11. cx.fillText (parseInt (mark [0] .innerHTML), 0, 12, 16);
  12. // use favicon
  13. var oldicons = document .querySelectorAll ( 'link [rel = "icon"], link [rel = "shortcut icon"]' );
  14. for ( var i = 0; i <oldicons.length; i ++) {
  15. oldicons [i] .parentNode.removeChild (oldicons [i]);
  16. }
  17. var newicon = document .createElement ( "link" );
  18. newicon.setAttribute ( "rel" , "icon" );
  19. newicon.setAttribute ( "href" , c.toDataURL ());
  20. document .querySelector ( "head" ) .appendChild (newicon);
  21. // update the page every 2 minutes
  22. window.setTimeout ( function () {
  23. window.clearTimeout ();
  24. window.location.reload ();
  25. }, 120000);
* This source code was highlighted with Source Code Highlighter .


Actually that's all. If you have found at least some part of the post useful for yourself, even if it doesn’t even concern the topic topic, then allow time to be considered spent not in vain for writing it.
If you are interested in the dynamic change of favicon, then you can use the ready -made jQuery plugin - there you can also animate favicons (via the same canvas).

Thanks for attention.

Source: https://habr.com/ru/post/112551/


All Articles