This repository has been archived by the owner on Nov 3, 2021. It is now read-only.
/
icons_helper.js
139 lines (116 loc) · 3.59 KB
/
icons_helper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* exported IconsHelper */
'use strict';
/**
* Utility library that will help us to work with icons coming from
* different sources.
*/
(function IconsHelper(exports) {
function getIcon(uri, iconSize, placeObj) {
var icon;
if (placeObj && placeObj.icons) {
icon = getBestIcon(placeObj.icons, iconSize);
}
// If we dont pick up a valid icon, use favicon.ico at the origin
if (!icon) {
var a = document.createElement('a');
a.href = uri;
icon = a.origin + '/favicon.ico';
}
// Future proofing as eventually this helper will retrieve and
// cache the icons, and will need an async API
return new Promise(resolve => {
resolve(icon);
});
}
// See bug 1041482, we will need to support better
// icons for different part of the system application.
// A web page have different ways to defining icons
// based on size, 'touch' capabilities and so on.
// From gecko we will receive all the rel='icon'
// defined which will containg as well the sizes
// supported in that file.
// This function will help to deliver the best suitable
// icon based on that definition list.
// The expected format is the following one:
//
// {
// '[uri 1]': {
// sizes: ['16x16 32x32 48x48', '60x60']
// },
// '[uri 2]': {
// sizes: ['16x16']
// }
// }
//
// iconSize is an aditional parameter to specify a concrete
// size or the closest icon.
function getBestIcon(icons, iconSize) {
if (!icons) {
return null;
}
var options = getSizes(icons);
var sizes = Object.keys(options).sort(function(a, b) {
return a - b;
});
// Handle the case of no size info in the whole list
// just return the first icon.
if (sizes.length === 0) {
var iconStrings = Object.keys(icons);
return iconStrings.length > 0 ? iconStrings[0] : null;
}
var preferredSize = getPreferredSize(sizes, iconSize);
return options[preferredSize];
}
// Given an object representing the icons detected in a web
// return the list of sizes and which uris offer the specific
// size.
// Current implementation overrides the source if the size is
// defined twice.
function getSizes(icons) {
var sizes = {};
var uris = Object.keys(icons);
uris.forEach(function(uri) {
var uriSizes = icons[uri].sizes.join(' ').split(' ');
uriSizes.forEach(function(size) {
var sizeValue = guessSize(size);
if (!sizeValue) {
return;
}
sizes[sizeValue] = uri;
});
});
return sizes;
}
function getPreferredSize(sizes, iconSize) {
var targeted = iconSize ? parseInt(iconSize) : 0;
// Sized based on current homescreen selected icons for apps
// in a configuration of 3 icons per row. See:
// https://github.com/mozilla-b2g/gaia/blob/master/
// shared/elements/gaia_grid/js/grid_layout.js#L15
if (targeted === 0) {
targeted = window.devicePixelRatio > 1 ? 142 : 84;
}
var selected = -1;
var length = sizes.length;
for(var i = 0; i < length && selected < targeted; i++) {
selected = sizes[i];
}
return selected;
}
// Given an icon size by string YYxYY returns the
// width measurement, so will assume this will be
// used by strings that identify a square size.
function guessSize(size) {
var xIndex = size.indexOf('x');
if (!xIndex) {
return null;
}
return size.substr(0, xIndex);
}
exports.IconsHelper = {
getIcon: getIcon,
getBestIcon: getBestIcon,
// Make public for unit test purposes
getSizes: getSizes
};
})(window);