PageSourceSearch

https://prov-a.github.io/generate-lod.html

html prov-a.github.io collected 2026-10-03 09:47:27 UTC 32,772 bytes, 408 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5    <meta name="viewport" content="width=device-width, initial-scale=1.0">
6    <title>PROV-A, the Provenance App</title>
7    <!-- External Libraries -->
8    
8<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
8
9    
9<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
9
10    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
11    
11<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
11
12    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.5.0/css/all.css">
13    <link rel="stylesheet" href="style/codemirror.css">
14    <style>
15        .CodeMirror {
16            border: 1px solid #eee;
17            height: 350px;
18        }
19        .loader {
20            margin: auto;
21            border: 16px solid #f3f3f3;
22            border-radius: 50%;
23            border-top: 16px solid #3498db;
24            width: 150px;
25            height: 150px;
26            animation: spin 1s linear infinite;
27        }
28        @keyframes spin {
29            0% { transform: rotate(0deg); }
30            100% { transform: rotate(360deg); }
31        }
32    </style>
33</head>
34<body style="display: flex; flex-direction: column; min-height: 100vh;">
35    <nav class="navbar navbar-dark navbar-expand-lg bg-dark">
36        <div class="container-fluid">
37            <a class="navbar-brand" href="index.html">PROV-A, the Provenance App</a>
38            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
39                <span class="navbar-toggler-icon"></span>
40            </button>
41            <div class="collapse navbar-collapse" id="navbarSupportedContent">
42                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
43                  <li class="nav-item">
44                    <a class="nav-link" aria-current="page" href="index.html">Home</a>
45                  </li>
46                  <li class="nav-item">
47                    <a class="nav-link" aria-current="page" href="initialise-project.html">Initialise Project</a>
48                  </li>
49                  <li class="nav-item">
50                    <a class="nav-link" aria-current="page" href="structure-data.html">Structure Data</a>
51                  </li>
52                  <li class="nav-item">
53                    <a class="nav-link active" aria-current="page" href="generate-lod.html">Generate LOD</a>
54                  </li>
55                </ul>
56            </div>
57        </div>
58    </nav>
59
60    <div class="container-fluid mt-5">
61        <div id="step1" class="container">
62            <div class="row">
63                 <div class="col text-center">
64                    <button class="btn btn-success d-none" id="generateLODButton">Initialize Database</button>
65                    <div id="noDataMessage" class="mt-3 d-none">No data found. Please <a href="initialise-project.html">initialize a new project</a>. </div>
66                </div>
67            </div>
68        </div>
69        <div id="loaderModal" class="modal" tabindex="-1" style="z-index:9999" role="dialog" aria-labelledby="loaderLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
70            <div class="modal-dialog modal-dialog-centered text-center" role="document">
71                <div class="modal-content" style="background: transparent !important; border: 0 !important">
72                    <div class="loader"></div>
73                    <div class="mt-5 p-3 alert alert-light">Initializing Database. This may take a few minutes.</div>
74                </div>
75            </div>
76        </div>
77        <div id="loaderModalQuery" class="modal" tabindex="-1" style="z-index:9999" role="dialog" aria-labelledby="loaderLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
78            <div class="modal-dialog modal-dialog-centered" role="document">
79                <div class="modal-content" style="background: transparent !important; border: 0 !important">
80                    <div class="loader"></div>
81                </div>
82            </div>
83        </div>
84        <div id="step2" class="d-none">
85            <div class="container">
86                <div class="d-flex justify-content-between align-items-center my-4">
87                    <div>
88                        <a type="button" class="btn btn-success me-2" id="downloadLink">
89                            <i class="fa-solid fa-file-arrow-down"></i> Download LOD
90                        </a>
91                        <a type="button" class="btn btn-primary" id="updateLOD">
92                            <i class="fa-solid fa-arrow-rotate-right"></i> Refresh LOD
93                        </a>
94                    </div>
95                    <div>
96                        <button class="btn btn-info me-2 text-white" data-bs-toggle="modal" data-bs-target="#sparqlModal"> <i class="fa-solid fa-folder-open"></i> SPARQL Queries</button>
97                        <a href="https://github.com/prov-a/prov-a.github.io/blob/main/data-model.md" type="button" class="btn btn-secondary" target="_blank">
98                            Data Model <i class="fa-solid fa-arrow-up-right-from-square"></i>
99                        </a>
100                    </div>
101                </div>
102                <div class="row">
103                  <div class="col">
104                    <div class="code-textarea">
105                      <div class="line-numbers">
106                      </div>
107                      <textarea class="form-control code-input" rows="20" id="codeTextarea" style="resize: none;">
108PREFIX owl: <http://www.w3.org/2002/07/owl#>
109PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
110PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
111PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
112PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
113PREFIX crminf: <http://www.cidoc-crm.org/crminf/>
114PREFIX np: <http://www.nanopub.org/nschema#>
115PREFIX dct: <http://purl.org/dc/terms/>
116PREFIX gvp: <http://vocab.getty.edu/ontology#>
117
118SELECT ?subject ?predicate ?object ?graph
119WHERE {
120  GRAPH ?graph {
121    ?subject ?predicate ?object .
122  }
123} LIMIT 1000</textarea>
124                    </div>
125                    <div class="alert alert-danger alert-query alert-dismissible mt-3 d-none" role="alert" id="error">
126                        <button type="button" class="btn-close" onclick="$(this).closest('.alert').addClass('d-none')"></button>
127                        <strong>Malformed SPARQL query</strong>
128                    </div>
129                    <div class="alert alert-warning alert-query alert-dismissible mt-3 d-none" role="alert" id="noresults">
130                        <button type="button" class="btn-close" onclick="$(this).closest('.alert').addClass('d-none')"></button>
131                        <strong>No Results</strong>
132                    </div>
133                  </div>
134                </div>
135                <div class="row text-center mt-4">
136                  <div class="col">
137                    <button type="submit" id="submitButton" class="btn btn-outline-primary">Submit</button>
138                  </div>
139                </div>
140            </div>
141            <div class="row mt-4">
142                <nav class="navbar navbar-light bg-light d-none" id="resultsNav">
143                  <div class="container-fluid">
144                      <ul class="navbar-nav">
145                        <li class="nav-item">
146                            <div class="navbar-text"><span id="resultsCounter"></span> Results</div>
147                        </li>
148                      </ul>
149                      <div class="d-flex">
150                        <input class="form-control me-2" type="search" placeholder="Filter" id="searchInput">
151                        <button class="btn btn-success text-nowrap" type="button" id="downloadButton"><i class="fa-solid fa-file-arrow-down"></i> Download Results</button>
152                    </div>
153                  </div>
154                </nav>
155                <div id="resultsContainer" class="mt-3 table-responsive"></div>
156            </div>
157        </div>
158    </div>
159    <!-- Modal -->
160    <div class="modal fade" id="sparqlModal" tabindex="-1">
161      <div class="modal-dialog modal-lg">
162        <div class="modal-content">
163          <div class="modal-header">
164            <h5 class="modal-title" id="sparqlModalLabel">SPARQL Queries</h5>
165            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
166          </div>
167          <div class="modal-body">
168            <div class="list-group" id="sparqlQueryList">
169              <!-- Queries will be dynamically added here -->
170            </div>
171          </div>
172          <div class="modal-footer">
173            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
174          </div>
175        </div>
176      </div>
177    </div>
178
179
180    
180<script src="./src/dist/codemirror.js"></script>
180
181    
181<script src="./src/dist/matchbrackets.js"></script>
181
182    
182<script src="./src/dist/codemirror_sparql.js"></script>
182
183    
183<script src="src/dist/n3.js"></script>
183
184    
184<script type="text/javascript" src="./src/edtf.js"></script>
184
185
186    
186<script type="module">
187        import { generateLOD, sparql, download, initializeDatabase } from './src/plod.js';
188
189        $(document).ready(function() {
190            // Step 1: Check for data in localStorage
191            const storedJsonData = localStorage.getItem('provaData');
192            indexedDB.databases().then(databases => {
193                if (!storedJsonData) {
194                    for (var i = 0; i < databases.length; i++) { window.indexedDB.deleteDatabase(databases[i].name) }
195                    $('#noDataMessage').removeClass('d-none');
196                }
197                else if (databases.length > 0) {
198                    $('#step1').addClass('d-none');
199                    $('#step2').removeClass('d-none');
200                    initializeDatabase().then(() => {
201                        download();
202                        initCodeMirror();
203                    })
204                } else if (storedJsonData) {
205                    $('#generateLODButton').removeClass('d-none');
206                    $('#generateLODButton').on('click', function() {
207                        $('#loaderModal').modal('show');
208                        initializeDatabase().then(() => {
209                            generateLOD(JSON.parse(storedJsonData)).then(() => {
210                                $('#loaderModal').modal('hide');
211                                $('#step1').addClass('d-none');
212                                $('#step2').removeClass('d-none');
213                                initCodeMirror();
214                            }).catch((error) => {
215                                alert('Error generating LOD: ' + error);
216                                $('#loaderModal').modal('hide');
217                            });
218                        });
219                    });
220                }
221            })
222
223            function initCodeMirror() {
224                // Initialize CodeMirror editor
225                const editor = CodeMirror.fromTextArea(document.getElementById("codeTextarea"), {
226                    mode: "application/x-sparql-query",
227                    lineNumbers: true,
228                    matchBrackets: true
229                });
230
231                $('#updateLOD').on('click', function() {
232                    $("#error").addClass("d-none")
233                    $("#noresults").addClass("d-none")
234                    $("#resultsNav").addClass("d-none")
235                    var container = $("#resultsContainer");
236                    container.empty()
237                    var counter = $("#resultsCounter");
238                    counter.empty()
239                    container.empty()
240                    $('#loaderModal').modal('show');
241                    generateLOD(JSON.parse(storedJsonData)).then(() => {
242                        $('#loaderModal').modal('hide');
243                    }).catch((error) => {
244                        alert('Error generating LOD: ' + error);
245                        $('#loaderModal').modal('hide');
246                    });
247                });
248
249                $('#submitButton').on('click', function() {
250                  let textareaContent = editor.getValue();
251                  if (textareaContent){
252                    sparql(textareaContent)
253                  }
254                });
255
256                $('#searchInput').on('input', function() {
257                  var searchText = $(this).val().toLowerCase();
258                  $('#resultsTable tbody tr').filter(function() {
259                    $(this).toggle($(this).text().toLowerCase().indexOf(searchText) > -1);
260                  });
261                });
262
263                $('#downloadButton').on('click', function() {
264                    var confirmDownload = confirm("Are you sure you want to download the table as CSV?");
265                    if (confirmDownload) {
266                        var csvContent = [];
267
268                        // Add table headers to CSV
269                        var headers = [];
270                        $('#resultsTable thead th').each(function() {
271                            headers.push($(this).text());
272                        });
273                        csvContent.push(headers.join(','));
274
275                        // Add table rows to CSV
276                        $('#resultsTable tbody tr').each(function() {
277                            const rowData = [];
278                            $(this).find('td').each(function() {
279                              const cellContent = $(this).text().replace(/"/g, '""').trim();
280                              rowData.push('"' + cellContent.replace(/\n/g, '\\n') + '"');
281                            });
282                            csvContent.push(rowData.join(','));
283                        });
284                        const csvString = csvContent.join('\n');
285                        const encodedUri = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csvString);
286                        const link = document.createElement('a');
287                        link.setAttribute('href', encodedUri);
288                        link.setAttribute('download', 'results.csv');
289                        document.body.appendChild(link);
290                        link.click();
291                        document.body.removeChild(link);
292                    }
293                });
294
295                const sparqlPrefixes = `PREFIX owl: <http://www.w3.org/2002/07/owl#>
296PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
297PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
298PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
299PREFIX crm: <http://www.cidoc-crm.org/cidoc-crm/>
300PREFIX crminf: <http://www.cidoc-crm.org/crminf/>
301PREFIX np: <http://www.nanopub.org/nschema#>
302PREFIX dct: <http://purl.org/dc/terms/>
303PREFIX gvp: <http://vocab.getty.edu/ontology#>
304
305`;
306                const sparqlQuerySections = [
307                    {
308                        category: "Queries for Physical Objects",
309                        queries: [
310                            { id: 1, description: "Retrieve Titles of Physical Objects", query: `SELECT ?physical_object ?title_content\nWHERE {\n  GRAPH ?object_graph {\n    ?physical_object a crm:E19_Physical_Object .\n    ?physical_object crm:P102_has_title ?title.\n    ?title crm:P190_has_symbolic_content ?title_content.\n  }\n}\n` },
311                            { id: 2, description: "Retrieve URLs for Physical Objects", query: `SELECT ?physical_object ?url_content\nWHERE {\n  GRAPH ?object_graph {\n    ?physical_object a crm:E19_Physical_Object .\n    ?physical_object crm:P70i_is_documented_in ?document.\n    ?document crm:P1_is_identified_by ?url.\n    ?url crm:P190_has_symbolic_content ?url_content.\n  }\n}\n` },
312                            { id: 3, description: "Retrieve Medium Information of Physical Objects", query: `SELECT ?physical_object ?medium_content\nWHERE {\n  GRAPH ?object_graph {\n    ?physical_object a crm:E19_Physical_Object .\n    ?physical_object crm:P67i_is_referred_to_by ?linguistic_object .\n    ?linguistic_object crm:P2_has_type <http://vocab.getty.edu/aat/300435429> .\n    ?linguistic_object crm:P190_has_symbolic_content ?medium_content .\n  }\n}\n` },
313                            { id: 4, description: "Retrieve Accession Numbers of Physical Objects", query: `SELECT ?physical_object ?accession\nWHERE {\n  GRAPH ?object_graph {\n    ?physical_object a crm:E19_Physical_Object .\n    ?physical_object crm:P67i_is_referred_to_by ?linguistic_object .\n    ?linguistic_object crm:P2_has_type <http://vocab.getty.edu/aat/300312355> .\n    ?linguistic_object crm:P190_has_symbolic_content ?accession .\n  }\n}\n` },
314                            { id: 5, description: "Retrieve Credit Line for Physical Objects", query: `SELECT ?physical_object ?credit_line\nWHERE {\n  GRAPH ?object_graph {\n    ?physical_object a crm:E19_Physical_Object .\n    ?physical_object crm:P67i_is_referred_to_by ?linguistic_object .\n    ?linguistic_object crm:P2_has_type <http://vocab.getty.edu/aat/300435418> .\n    ?linguistic_object crm:P190_has_symbolic_content ?credit_line .\n  }\n}\n` }
315                        ]
316                    },
317                    {
318                        category: "Queries for Provenance Activities",
319                        queries: [
320                            { id: 6, description: "Retrieve Provenance Activity Date Range", query: `SELECT DISTINCT ?provenance_activity ?begin_of_the_begin ?end_of_the_end\nWHERE {\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P4_has_time-span ?timespan .\n    OPTIONAL { ?timespan crm:P82a_begin_of_the_begin ?begin_of_the_begin . }\n    OPTIONAL { ?timespan crm:P82b_end_of_the_end ?end_of_the_end . }\n  }\n}\n` },
321                            { id: 7, description: "Retrieve Provenance Event Type", query: `SELECT DISTINCT ?provenance_activity ?activity_type\nWHERE {\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P2_has_type ?activity_type\n  }\n}\n` },
322                            { id: 8, description: "Retrieve Sender and Receiver of Ownership Transfer", query: `SELECT ?provenance_activity ?sender ?receiver ?physical_object\nWHERE {\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P9_consists_of ?acquisition .\n    ?acquisition crm:P24_transferred_title_of ?physical_object .\n    ?acquisition crm:P22_transferred_title_to ?receiver .\n    ?acquisition crm:P23_transferred_title_from ?sender .\n  }\n}\n` },
323                            { id: 9, description: "Retrieve Sender and Receiver of Custody Transfers", query: `SELECT ?provenance_activity ?sender ?receiver ?physical_object\nWHERE {\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P9_consists_of ?custody_change .\n    ?custody_change crm:P30_transferred_custody_of ?physical_object .\n    ?custody_change crm:P29_custody_received_by ?receiver .\n    ?custody_change crm:P28_custody_surrendered_by ?sender .\n  }\n}\n` },
324                            { id: 10, description: "Retrieve Agents Involved in Provenance Activities", query: `SELECT ?provenance_activity ?agent\nWHERE {\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P9_consists_of ?acquisition .\n    ?acquisition crm:P14_carried_out_by ?agent .\n  }\n}\n` },
325                        ]
326                    },
327                    {
328                        category: "Queries for Parties",
329                        queries: [
330                            { id: 11, description: "Retrieve Group Types of Parties", query: `SELECT DISTINCT ?party ?type\nWHERE {\n  GRAPH ?party_graph {\n    ?party a crm:E74_Group .\n    ?party crm:P2_has_type ?type .\n    ?type crm:P127_has_broader_term <http://vocab.getty.edu/aat/300192630> .\n  }\n}\n` },
331                            { id: 12, description: "Retrieve Gender Classification of Individuals", query: `SELECT DISTINCT ?party ?sex\nWHERE {\n  GRAPH ?party_graph {\n    ?party a crm:E21_Person .\n    ?party crm:P2_has_type ?sex .\n    ?sex crm:P127_has_broader_term <http://vocab.getty.edu/aat/300445640> .\n  }\n}\n` },
332                            { id: 13, description: "Retrieve Birth and Death Dates of Individuals", query: `SELECT DISTINCT ?party ?birth_begin_of_the_begin ?birth_end_of_the_end ?death_begin_of_the_begin ?death_end_of_the_end\nWHERE {\n  GRAPH ?party_graph {\n    ?party a crm:E21_Person .\n    ?party crm:P98i_was_born ?birth .\n    ?birth crm:P4_has_time-span ?birth_timespan .\n    ?birth_timespan crm:P82a_begin_of_the_begin ?birth_begin_of_the_begin .\n    ?birth_timespan crm:P82b_end_of_the_end ?birth_end_of_the_end .\n    ?party crm:P100i_died_in ?death .\n    ?death crm:P4_has_time-span ?death_timespan .\n    ?death_timespan crm:P82a_begin_of_the_begin ?death_begin_of_the_begin .\n    ?death_timespan crm:P82b_end_of_the_end ?death_end_of_the_end .\n  }\n}\n` },
333                            { id: 14, description: "Retrieve Names and Appellations of Individuals", query: `SELECT ?party ?party_label (GROUP_CONCAT(DISTINCT ?appellation_content; separator='; ') AS ?appellations)\nWHERE {\n  GRAPH ?party_graph {\n    ?party a crm:E21_Person .\n    ?party rdfs:label ?party_label .\n    ?party crm:P1_is_identified_by ?appellation .\n    ?appellation crm:P190_has_symbolic_content ?appellation_content .\n  }\n}\nGROUP BY ?party ?party_label\n` },
334                            { id: 15, description: "Retrieve Locations Associated with Indiv
334iduals", query: `SELECT ?party ?party_label (GROUP_CONCAT(DISTINCT ?location_label; separator='; ') AS ?locations)\nWHERE {\n  GRAPH ?party_graph {\n    ?party a crm:E21_Person .\n    ?party rdfs:label ?party_label .\n    ?party crm:P74_has_current_or_former_residence ?location .\n    ?location rdfs:label ?location_label .\n  }\n}\nGROUP BY ?party ?party_label\n` },
335                        ]
336                    },
337                    {
338                        category: "Queries for Provenance Assessments",
339                        queries: [
340                            { id: 16, description: "Retrieve Physical Objects in Provenance Assessments", query: `SELECT ?assessment ?physical_object\nWHERE {\n  GRAPH ?provenance_graph {\n    ?assessment a crminf:I15_Provenance_Assessment .\n    ?assessment crminf:J20_is_about_the_provenance_of ?physical_object .\n  }\n}\n` },
341                            { id: 17, description: "Retrieve Sources Used in Provenance Assessments", query: `SELECT ?assessment ?source_label\nWHERE {\n  GRAPH ?provenance_graph {\n    ?assessment a crminf:I15_Provenance_Assessment .\n    ?assessment crm:P16_used_specific_object ?source .\n    ?source rdfs:label ?source_label .\n  }\n}\n` },
342                            { id: 18, description: "Retrieve Authors of Provenance Assessments", query: `SELECT ?assessment ?author_label\nWHERE {\n  GRAPH ?provenance_graph {\n    ?assessment a crminf:I15_Provenance_Assessment .\n    ?assessment crm:P14_carried_out_by ?author .\n    ?author rdfs:label ?author_label .\n  }\n}\n` },
343                            { id: 19, description: "Retrieve Date Range of Provenance Assessments", query: `SELECT ?assessment ?begin_of_the_begin ?end_of_the_end\nWHERE {\n  GRAPH ?provenance_graph {\n    ?assessment a crminf:I15_Provenance_Assessment .\n    ?assessment crm:P4_has_time-span ?timespan .\n    ?timespan crm:P82a_begin_of_the_begin ?begin_of_the_begin .\n    ?timespan crm:P82b_end_of_the_end ?end_of_the_end .\n  }\n}\n` },
344                            { id: 20, description: "Retrieve Assertions in Provenance Assessments", query: `SELECT ?assessment ?assertion_graph\nWHERE {\n  GRAPH ?provenance_graph {\n    ?assessment a crminf:I15_Provenance_Assessment .\n    ?assessment crminf:J21_concluded_provenance ?belief .\n    ?belief crminf:J4_that ?assertion_graph .\n  }\n}\n` }
345                        ]
346                    },
347                    {
348                        category: "Queries Across Multiple Graphs",
349                        queries: [
350                            { id: 21, description: "Retrieve Activities Involving Female Parties", query: `SELECT ?activity ?party ?party_label\nWHERE {\n  GRAPH ?assertion_graph {\n    ?activity a crm:E7_Activity .\n    ?activity crm:P9_consists_of ?sub_activity .\n    ?sub_activity ?role ?party .\n  }\n  GRAPH ?party_graph {\n  	?party crm:P2_has_type <http://vocab.getty.edu/aat/300411837> .\n    ?party rdfs:label ?party_label .\n  }\n}\n` },
351                            { id: 22, description: "Retrieve Uncertain Activity Types", query: `SELECT ?provenance_activity ?activity_type\nWHERE {\n  GRAPH ?provenance_graph {\n    ?assessment a crminf:I15_Provenance_Assessment .\n    ?assessment crminf:J21_concluded_provenance ?belief .\n    ?belief crminf:J5_holds_to_be <http://vocab.getty.edu/aat/300435721> .\n    ?belief crminf:J4_that ?assertion_graph .\n  }\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P2_has_type ?activity_type .\n  }\n}\n` },
352                            { id: 23, description: "Retrieve Senders and Sources in Activities", query: `SELECT ?source_label ?party_label ?sender\nWHERE {\n  GRAPH ?provenance_graph {\n    ?assessment a crminf:I15_Provenance_Assessment .\n    ?assessment crm:P16_used_specific_object ?source .\n    ?source rdfs:label ?source_label .\n    ?assessment crminf:J21_concluded_provenance ?belief .\n    ?belief crminf:J4_that ?assertion_graph .\n  }\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P9_consists_of ?sub_activity .\n    ?sub_activity ?sender ?party .\n  }\n  GRAPH ?party_graph {\n    ?party rdfs:label ?party_label .\n  }\n  FILTER ( ?sender = crm:P23_transferred_title_from || ?sender = crm:P28_custody_surrendered_by )\n}\n` },
353                            { id: 24, description: "Retrieve Acquisition Receivers in Paris", query: `SELECT DISTINCT ?provenance_activity ?party_label\nWHERE {\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P9_consists_of ?sub_activity .\n    ?sub_activity crm:P22_transferred_title_to ?party .\n  }\n  GRAPH ?party_graph {\n    ?party rdfs:label ?party_label .\n    ?party crm:P74_has_current_or_former_residence ?location .\n    ?location owl
353:sameAs <https://www.wikidata.org/wiki/Q90> .\n  }\n}\n` },
354                            { id: 25, description: "Retrieve Activity Dates and Object Titles", query: `SELECT DISTINCT ?title_content ?end_of_the_end\nWHERE {\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P9_consists_of ?sub_activity .\n    ?sub_activity ?involved ?physical_object .\n    ?provenance_activity a crm:E7_Activity .\n    ?provenance_activity crm:P4_has_time-span ?timespan .\n    OPTIONAL { ?timespan crm:P82b_end_of_the_end ?end_of_the_end . }\n  }\n  GRAPH ?object_graph {\n    ?physical_object a crm:E19_Physical_Object .\n    ?physical_object crm:P102_has_title ?title.\n    ?title crm:P190_has_symbolic_content ?title_content.\n  }\n  FILTER ( ?involved = crm:P24_transferred_title_of || ?involved = crm:P30_transferred_custody_of )\n}\nORDER BY ?end_of_the_end\n` }
355                        ]
356                    },
357                    {
358                        category: "Query for Incomplete Records",
359                        queries: [
360                            { id: 26, description: "Retrieve Gaps Between Consecutive Activities", query: `SELECT DISTINCT ?activity_1 ?activity_2\nWHERE {\n  GRAPH ?assertion_graph_1 {\n    ?activity_1 crm:P9_consists_of ?sub_activity_1 .\n    ?sub_activity_1 ?receiver ?party_A .\n    VALUES ?receiver { crm:P29_custody_received_by crm:P22_transferred_title_to } \n  }\n  GRAPH ?assertion_graph_2 {\n    ?activity_2 crm:P183i_starts_after_the_end_of ?activity_1 .\n    FILTER NOT EXISTS {\n      ?activity_2 crm:P9_consists_of ?sub_activity_2 .\n      ?sub_activity_2 ?sender ?party_A .\n      VALUES ?sender { crm:P28_custody_surrendered_by crm:P23_transferred_title_from }     \n    }\n  }\n}\n` },
361                            { id: 27, description: "Retrieve Gaps After Object Creation", query: `SELECT DISTINCT ?activity_1 ?activity_2\nWHERE {\n  GRAPH ?assertion_graph_1 {\n    ?activity_1 crm:P9_consists_of ?sub_activity_1 .\n    ?sub_activity_1 a crm:E12_Production .\n    ?sub_activity_1 crm:P14_carried_out_by ?party_A .\n  }\n  GRAPH ?assertion_graph_2 {\n    ?activity_2 crm:P183i_starts_after_the_end_of ?activity_1 .\n    FILTER NOT EXISTS {\n      ?activity_2 crm:P9_consists_of ?sub_activity_2 .\n      ?sub_activity_2 ?sender ?party_A .\n      VALUES ?sender { crm:P28_custody_surrendered_by crm:P23_transferred_title_from }     \n    }\n  }\n}\n` },
362                            { id: 28, description: "Retrieve Activities Missing Dates", query: `SELECT DISTINCT ?provenance_activity\nWHERE {\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n    FILTER NOT EXISTS {\n      ?provenance_activity crm:P4_has_time-span ?timespan .\n    }\n  }\n}\n` },
363                            { id: 29, description: "Retrieve Assertions Missing Sources", query: `SELECT DISTINCT ?provenance_activity\nWHERE {\n  GRAPH ?provenance_graph {\n    ?assessment a crminf:I15_Provenance_Assessment .\n    ?assessment crminf:J21_concluded_provenance ?belief .\n    ?belief crminf:J4_that ?assertion_graph .\n    FILTER NOT EXISTS { ?assessment crm:P16_used_specific_object ?source . }\n  }\n  GRAPH ?assertion_graph {\n    ?provenance_activity a crm:E7_Activity .\n  }\n}\n` },
364                            { id: 30, description: "Retrieve People Missing ULAN Identifiers", query: `SELECT DISTINCT ?party ?party_label\nWHERE {\n  GRAPH ?party_graph {\n    ?party a crm:E21_Person .\n    ?party rdfs:label ?party_label .\n    FILTER NOT EXISTS {\n      ?party owl:sameAs ?ulan .\n      FILTER(CONTAINS(STR(?ulan), 'ulan'))\n    }\n  }\n}\n` }
365                        ]
366                    }
367                ];
368
369                const $sparqlQueryList = $("#sparqlQueryList");
370                sparqlQuerySections.forEach((section, index) => {
371                    const categoryId = `category-${index}`;
372                    const $categoryTitle = $(`<h5 class="mt-3 text-primary">${section.category}</h5>`);
373                    $sparqlQueryList.append($categoryTitle);
374                    const $categoryAccordion = $(`
375                        <div class="accordion" id="${categoryId}"></div>
376                    `);
377                    section.queries.forEach((query, queryIndex) => {
378                        const queryId = `${categoryId}-query-${queryIndex}`;
379                        const $queryItem = $(`
380                            <div class="accordion-item">
381                                <h2 class="accordion-header" id="heading-${queryId}">
382                                    <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse-${queryId}" aria-expanded="false">
383                                        ${query.description}
384                                    </button>
385                                </h2>
386                                <div id="collapse-${queryId}" class="accordion-collapse collapse" aria-labelledby="heading-${queryId}" data-bs-parent="#${categoryId}">
387                                    <div class="accordion-body">
388                                        <pre class="bg-light p-2 border rounded">${query.query}</pre>
389                                        <button class="btn btn-sm btn-primary use-query-btn mt-2" data-query="${query.query}">Use</button>
390                                    </div>
391                                </div>
392                            </div>
393                        `);
394                        $queryItem.find(".use-query-btn").on("click", function () {
395                            const selectedQuery = sparqlPrefixes + $(this).data("query");
396                            $("#codeTextarea").val(selectedQuery);
397                            editor.setValue(selectedQuery);
398                            $('#sparqlModal').modal('hide');
399                        });
400                        $categoryAccordion.append($queryItem);
401                    });
402                    $sparqlQueryList.append($categoryAccordion);
403                });
404            }
405        });
406    </script>
406
407</body>
408</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.