-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathscripts.js
343 lines (295 loc) · 12.7 KB
/
scripts.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
var schema_src; // schema.org definitions source
var types = []; // schema.org parsed classes
var properties = []; // schema.org parsed properties
var selected_type = ''; // currently selected type
var selected_property = ''; // currently selected property
var selected_properties = []; // currently selected properties
//TODO: datatypes
// class for schema.org types
class Type {
constructor(id, comment, label, subClassOf = [], isPartOf = []) {
this.id = id;
this.comment = comment;
this.label = label;
this.subClassOf = subClassOf;
this.isPartOf = isPartOf;
}
}
// class for schema.org properties
class Property {
constructor(id, comment, label, domainIncludes = [], rangeIncludes = [], source = null) {
this.id = id;
this.comment = comment;
this.label = label;
this.domainIncludes = domainIncludes;
this.rangeIncludes = rangeIncludes;
this.source = source;
}
}
// on page load
document.addEventListener('DOMContentLoaded', async function() {
await get_database();
await build_types_and_properties();
await next_level_types(1,'schema:Thing');
document.querySelector('#types0').style.display = 'inline';
document.querySelector('#types0_next').style.display = 'inline'
document.querySelector('#types0').selectedIndex = 0;
document.querySelector('#types0').selectedOptions[0].dispatchEvent(new MouseEvent("click",{bubbles: true, cancellable: true}));
// show welcome box unless hidden before
if(localStorage.getItem('hide_welcome_box') !== "true") {
document.querySelector('#welcome_box').style.display = 'block';
}
return Promise.resolve(1);
});
// pull latest definition file from schema.org
async function get_database() {
const url = 'https://schema.org/version/latest/schemaorg-current-https.jsonld';
let response = await fetch(url);
let result = await response.json();
schema_src = result;
return Promise.resolve(result);
}
// populate types and properties arrays
function build_types_and_properties() {
for(var i=0; i<Object.keys(schema_src['@graph']).length; i++) {
// build classes
if(schema_src['@graph'][i]['@type'] === 'rdfs:Class') {
types.push(new Type(schema_src['@graph'][i]['@id'], schema_src['@graph'][i]['rdfs:comment'], schema_src['@graph'][i]['rdfs:label']));
//sub types
if(schema_src['@graph'][i].hasOwnProperty('rdfs:subClassOf')) {
if(Object.keys(schema_src['@graph'][i]['rdfs:subClassOf']).length === 1) {
types[types.length-1].subClassOf.push(schema_src['@graph'][i]['rdfs:subClassOf']['@id']);
} else {
for(var j=0; j<Object.keys(schema_src['@graph'][i]['rdfs:subClassOf']).length; j++) {
types[types.length-1].subClassOf.push(schema_src['@graph'][i]['rdfs:subClassOf'][j]['@id']);
}
}
}
//parent types
if(schema_src['@graph'][i].hasOwnProperty('schema:isPartOf')) {
if(Object.keys(schema_src['@graph'][i]['schema:isPartOf']).length === 1) {
types[types.length-1].isPartOf.push(schema_src['@graph'][i]['schema:isPartOf']['@id']);
} else {
for(var k=0; k<Object.keys(schema_src['@graph'][i]['schema:isPartOf']).length; k++) {
types[types.length-1].isPartOf.push(schema_src['@graph'][i]['schema:isPartOf'][k]['@id']);
}
}
}
}
// build properties
if(schema_src['@graph'][i]['@type'] === 'rdf:Property') {
properties.push(new Property(schema_src['@graph'][i]['@id'], schema_src['@graph'][i]['rdfs:comment'], schema_src['@graph'][i]['rdfs:label']));
// add domainIncludes (types using this property)
if(schema_src['@graph'][i].hasOwnProperty('schema:domainIncludes')) {
if(Object.keys(schema_src['@graph'][i]['schema:domainIncludes']).length === 1) {
properties[properties.length-1].domainIncludes.push(schema_src['@graph'][i]['schema:domainIncludes']['@id']);
} else {
for(var j=0; j<Object.keys(schema_src['@graph'][i]['schema:domainIncludes']).length; j++) {
properties[properties.length-1].domainIncludes.push(schema_src['@graph'][i]['schema:domainIncludes'][j]['@id']);
}
}
}
// add rangeIncludes (data types)
if(schema_src['@graph'][i].hasOwnProperty('schema:rangeIncludes')) {
if(Object.keys(schema_src['@graph'][i]['schema:rangeIncludes']).length === 1) {
properties[properties.length-1].rangeIncludes.push(schema_src['@graph'][i]['schema:rangeIncludes']['@id']);
} else {
for(var k=0; k<Object.keys(schema_src['@graph'][i]['schema:rangeIncludes']).length; k++) {
properties[properties.length-1].rangeIncludes.push(schema_src['@graph'][i]['schema:rangeIncludes'][k]['@id']);
}
}
}
}
}
//console.log(types);
//console.log(properties);
}
// returns number / position of TYPE object in types array
function get_type_number_from_id(id) {
for(var i=0; i<types.length; i++) {
if(types[i].id === id) {
return i;
}
}
return 0;
}
// returns number / position of PROPERTY object in properties array
function get_property_number_from_id(id) {
for(var i=0; i<properties.length; i++) {
if(properties[i].id === id) {
return i;
}
}
return 0;
}
// returns children of given type
function get_type_children(id) {
let children = [];
for(var i=0; i<types.length; i++) {
for(var j=0; j<Object.keys(types[i].subClassOf).length; j++) {
if(types[i].subClassOf[j] === id) {
children.push(types[i])
}
}
}
return children;
}
// get type parents
function get_type_parents(id) {
let parents = [];
let current_type = id;
while(types[get_type_number_from_id(current_type)].subClassOf.length > 0) {
parents.push(types[get_type_number_from_id(current_type)]);
current_type = types[get_type_number_from_id(current_type)].subClassOf[0];
}
parents.push(types[get_type_number_from_id(current_type)]);
return parents;
}
// returns properties of given type
function get_type_properties(id, include_parent_types=false) {
let type_properties = [];
let parent_ids = [];
for(var i=0; i<properties.length; i++) {
for(var j=0; j<Object.keys(properties[i].domainIncludes).length; j++) {
if(include_parent_types === false) {
if(properties[i].domainIncludes[j] === id) {
type_properties.push(properties[i]);
}
} else {
get_type_parents(id).forEach(child => { parent_ids.push(child.id) });
if(parent_ids.includes(properties[i].domainIncludes[j])) {
type_properties.push(properties[i]);
}
}
}
}
return type_properties;
}
// populate one of the type / sub-type selects based on parent
function next_level_types(level=0, id='schema:Thing') {
let children = get_type_children(id).sort(dynamicSort("label"));
let children_html = '';
children.forEach(child => {
children_html += '<option value="' + child.id + '" onclick="set_selected_type(\'' + child.id + '\');">' + child.label + ' (' + get_type_children(child.id).length + ')</option>';
});
const list = document.querySelector('#types' + level);
list.innerHTML = children_html;
document.querySelector('#types' + (level)).style.display = 'inline';
const next_button = document.querySelector('#types' + (level) + '_next')
if(next_button !== null) {
next_button.style.display = 'inline';
}
}
// populate property select with currently selected type's properties
function show_type_properties(id) {
let type_properties = [];
if(document.querySelector('#include_parent_types').checked) {
type_properties = get_type_properties(id, true).sort(dynamicSort("label"));
} else {
type_properties = get_type_properties(id, false).sort(dynamicSort("label"));
}
let type_html = '';
type_properties.forEach(child => {
type_html += '<option value="' + child.id + '" onclick="set_selected_property(\'' + child.id + '\');">' + child.label + ' (' + child.rangeIncludes[0] + ')</option>';
});
const list = document.querySelector('#properties');
list.innerHTML = type_html;
}
// set global var of currently selected type
function set_selected_type(id) {
selected_type = id;
show_type_properties(selected_type);
refresh_markup();
document.querySelector('#type_description').innerHTML = parseMarkdown(types[get_type_number_from_id(id)].comment);
}
function set_selected_property(id) {
selected_property = id;
document.querySelector('#property_description').innerHTML = parseMarkdown(properties[get_property_number_from_id(id)].comment);
}
// add a new property to the list of selected properties
function add_property_to_markup(id=null) {
if(id !== null) {
selected_properties.push(properties[get_property_number_from_id(id)]);
} else {
const properties_list = document.querySelector('#properties');
for(var i=0; i<properties_list.selectedOptions.length; i++) {
selected_properties.push(properties[get_property_number_from_id(properties_list.selectedOptions[i].value)]);
}
}
refresh_markup();
}
// put together markup text based on selected type and properties
function refresh_markup() {
const markup_field = document.querySelector('#markup');
let markup_html = '';
markup_html += '<div itemscope itemtype="https://schema.org/' + selected_type.split(":")[1] + '">\n';
for(var i=0; i<selected_properties.length; i++) {
markup_html += '\t<span>' + selected_properties[i].label + ': <span itemprop="' + selected_properties[i].label + '">Lorem ipsum (' + selected_properties[i].rangeIncludes[0] + ')</span></span>\n';
}
markup_html += '</div>';
markup_field.innerHTML = markup_html;
}
// reset all forms to initial state
async function reset() {
await set_selected_type('schema:Thing');
selected_properties = [];
refresh_markup();
document.querySelector('#types2').style.display = 'none';
document.querySelector('#types3').style.display = 'none';
document.querySelector('#types4').style.display = 'none';
document.querySelector('#types5').style.display = 'none';
document.querySelector('#types2_next').style.display = 'none';
document.querySelector('#types3_next').style.display = 'none';
document.querySelector('#types4_next').style.display = 'none';
for(var i=0; i<document.querySelector('#types1').options.length; i++) {
document.querySelector('#types1').options[i].selected = false;
}
for(var i=0; i<document.querySelector('#properties').options.length; i++) {
document.querySelector('#properties').options[i].selected = false;
}
document.querySelector('#include_parent_types').checked = true;
return Promise.resolve(1);
}
function reset2() {
reset();
}
// copy markup to clipboard
function copy() {
const markup = document.getElementById("markup");
markup.select();
markup.setSelectionRange(0, 99999);
document.execCommand("copy");
}
// sort function
// thank you https://stackoverflow.com/a/4760279/4619569
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
// hide welcome banner, set local storage var to keep hidden
function hide_welcome_box() {
document.querySelector('#welcome_box').style.display='none';
localStorage.setItem('hide_welcome_box', 'true');
}
// simple markdown to html converter
// thank you https://www.bigomega.dev/markdown-parser
function parseMarkdown(markdownText) {
const htmlText = markdownText
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
.replace(/^\> (.*$)/gim, '<blockquote>$1</blockquote>')
.replace(/\*\*(.*)\*\*/gim, '<b>$1</b>')
.replace(/\*(.*)\*/gim, '<i>$1</i>')
.replace(/!\[(.*?)\]\((.*?)\)/gim, "<img alt='$1' src='$2' />")
.replace(/\[(.*?)\]\((.*?)\)/gim, "<a href='$2'>$1</a>")
.replace(/\\n/g, ' ')
return htmlText.trim()
}