/
microdata-to-download-link-processor.js
129 lines (117 loc) · 4.92 KB
/
microdata-to-download-link-processor.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
(function() {
var getDownloadLinks = function() {
var links = document.getElementsByTagName('a');
var downloadLinks = [];
for (var i = 0, l = links.length; i < l; i++) {
var link = links[i];
var rel = link.getAttribute('rel');
var itemprop = link.getAttribute('itemprop');
if (rel === 'download' ||
itemprop === 'downloadUrl' ||
itemprop === 'contentUrl') {
downloadLinks.push(link);
}
}
return downloadLinks;
};
var processDownloadLinks = function(links) {
for (var i = 0, l = links.length; i < l; i++) {
var link = links[i];
link.setAttribute('rel', 'download');
var hash = {};
link.hash.replace(/[\#\&]([^=^&]*)=([^&]*)/g, function(whole, key, value) {
hash[key] = value;
return whole;
})
var scopeElement = getNearestScopeElement(link);
var itemProps = getItemProps(scopeElement);
if (itemProps.name && !hash.name) {
hash.name = encodeURIComponent(itemProps.name);
}
if ((itemProps.image || itemProps.thumbnailUrl || itemProps.thumbnail.image) && !hash.image) {
hash.image = encodeURIComponent(itemProps.image || itemProps.thumbnailUrl || itemProps.thumbnail.image)
}
if ((itemProps.fileSize || itemProps.contentSize) && !hash['content-length']) {
hash['content-length'] = encodeURIComponent(itemProps.fileSize || itemProps.contentSize);
}
var hashArray = [];
for (var key in hash) {
hashArray.push(key + '=' +hash[key]);
}
/* TODO: support itemid */
link.hash = '#' + hashArray.join('&');
}
};
var getNearestScopeElement = function(element) {
while (element && !element.hasAttribute('itemscope')) {
element = element.parentNode;
}
return element;
};
var getItemProps = function(scopeElement) {
var allPropElements = scopeElement.querySelectorAll('*[itemprop]');
var directItemProps = {};
scopeElement = getNearestScopeElement(scopeElement);
for (var i = 0, l = allPropElements.length; i < l; i++) {
var propElement = allPropElements[i];
if (getNearestScopeElement(propElement) === scopeElement) {
var itemProp = getItemProp(propElement);
if (itemProp.key) {
/* TODO: need to add multiple values support instead of simple overriding existed key */
directItemProps[itemProp.key] = itemProp.value;
}
}
}
return directItemProps;
};
var getItemProp = function(propElement) {
/* see Microdata standard for how to extract value from element: http://www.w3.org/TR/microdata/#values */
var property = {};
property.node = propElement;
/* TODO: support multiple keys within one itemprop attribute */
property.key = propElement.getAttribute('itemprop');
if (propElement.hasAttribute('itemscope')) {
/* embedded struct */
property.value = getItemProps(propElement);
} else {
switch (propElement.nodeName) {
case 'META':
property.value = propElement.getAttribute('content');
break;
case 'AUDIO':
case 'EMBED':
case 'IFRAME':
case 'IMG':
case 'SOURCE':
case 'TRACK':
case 'VIDEO':
/* let the browser resolve src attribute and provide absolute path in src property */
property.value = propElement.src;
break;
case 'A':
case 'AREA':
case 'LINK':
/* let the browser resolve href attribute and provide absolute path in href property */
property.value = propElement.href;
break;
case 'OBJECT':
property.value = propElement.data;
break;
case 'DATA':
property.value = propElement.value;
break;
case 'TIME':
property.value = propElement.getAttribute('datetime') || propElement.textContent;
break;
default:
property.value = propElement.textContent;
break;
}
}
return property;
};
window.addEventListener ('DOMContentLoaded', function() {
var links = getDownloadLinks();
processDownloadLinks(links);
}, false);
})();