Browse Source

Dynamic favicon (#972)

Dynamic favicon
Jasper van Merle 6 years ago
parent
commit
db079c13cd

+ 63 - 0
assets/javascripts/lib/favicon.coffee

@@ -0,0 +1,63 @@
+defaultUrl = null
+currentSlug = null
+
+imageCache = {}
+urlCache = {}
+
+withImage = (url, action) ->
+  if imageCache[url]
+    action(imageCache[url])
+  else
+    img = new Image()
+    img.src = url
+    img.onload = () =>
+      imageCache[url] = img
+      action(img)
+
+@setFaviconForDoc = (doc) ->
+  return if currentSlug == doc.slug
+
+  favicon = $('link[rel="icon"]')
+
+  if defaultUrl == null
+    defaultUrl = favicon.href
+
+  if urlCache[doc.slug]
+    favicon.href = urlCache[doc.slug]
+    currentSlug = doc.slug
+    return
+
+  styles = window.getComputedStyle($("._icon-#{doc.slug}"), ':before')
+
+  bgUrl = styles['background-image'].slice(5, -2)
+  sourceSize = if bgUrl.includes('@2x') then 32 else 16
+  sourceX = Math.abs(parseInt(styles['background-position-x'].slice(0, -2)))
+  sourceY = Math.abs(parseInt(styles['background-position-y'].slice(0, -2)))
+
+  withImage(bgUrl, (docImg) ->
+    withImage(defaultUrl, (defaultImg) ->
+      size = defaultImg.width
+
+      canvas = document.createElement('canvas')
+      ctx = canvas.getContext('2d')
+
+      canvas.width = size
+      canvas.height = size
+      ctx.drawImage(defaultImg, 0, 0)
+
+      docIconPercentage = 65
+      destinationCoords = size / 100 * (100 - docIconPercentage)
+      destinationSize = size / 100 * docIconPercentage
+      ctx.drawImage(docImg, sourceX, sourceY, sourceSize, sourceSize, destinationCoords, destinationCoords, destinationSize, destinationSize)
+
+      urlCache[doc.slug] = canvas.toDataURL()
+      favicon.href = urlCache[doc.slug]
+
+      currentSlug = doc.slug
+    )
+  )
+
+@resetFavicon = () ->
+  if defaultUrl != null and currentSlug != null
+    $('link[rel="icon"]').href = defaultUrl
+    currentSlug = null

+ 3 - 0
assets/javascripts/views/content/content.coffee

@@ -153,6 +153,9 @@ class app.views.Content extends app.View
     return
 
   afterRoute: (route, context) =>
+    if route != 'entry' and route != 'type'
+      resetFavicon()
+
     switch route
       when 'root'
         @show @rootPage

+ 1 - 0
assets/javascripts/views/content/entry_page.coffee

@@ -40,6 +40,7 @@ class app.views.EntryPage extends app.View
     if app.disabledDocs.findBy 'slug', @entry.doc.slug
       @hiddenView = new app.views.HiddenPage @el, @entry
 
+    setFaviconForDoc(@entry.doc)
     @delay @polyfillMathML
     @trigger 'loaded'
     return

+ 1 - 0
assets/javascripts/views/content/type_page.coffee

@@ -9,6 +9,7 @@ class app.views.TypePage extends app.View
 
   render: (@type) ->
     @html @tmpl('typePage', @type)
+    setFaviconForDoc(@type.doc)
     return
 
   getTitle: ->