123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577 |
- /* Copyright (c) 2012-2013 Epimorphics Ltd. Released under Apache License 2.0 http://www.apache.org/licenses/ */
- var qonsole = function() {
- "use strict";
- var YASQE = require('yasqe'),
- YASR = require('yasr');
-
- /**
- * Escape html function, inspired by http://stackoverflow.com/questions/5499078/fastest-method-to-escape-html-tags-as-html-entities
- */
- var escapeString = function(unescaped) {
- if (!unescaped) return '';
- return unescaped.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
- }
- /**
- * Some custom requirements for Jena, on how to present the bindings. I.e., bnodes prefixed with _:, literals with surrounding quotes, and URIs with brackets
- */
- YASR.plugins.table.defaults.getCellContent = function (yasr, plugin, bindings, variable, context) {
- var binding = bindings[variable];
- var value = null;
- if (binding.type == "uri") {
- var title = null;
- var href = binding.value;
- var visibleString = escapeString(href);
- var prefixed = false;
- if (context.usedPrefixes) {
- for (var prefix in context.usedPrefixes) {
- if (visibleString.indexOf(context.usedPrefixes[prefix]) == 0) {
- visibleString = prefix + ':' + href.substring(context.usedPrefixes[prefix].length);
- prefixed = true;
- break;
- }
- }
- }
- if (!prefixed) visibleString = "<" + visibleString + ">";
- value = "<a " + (title? "title='" + href + "' ": "") + "class='uri' target='_blank' href='" + href + "'>" + visibleString + "</a>";
- } else if (binding.type == "bnode"){
- value = "<span class='nonUri'>_:" + escapeString(binding.value) + "</span>";
- } else if (binding.type == "literal") {
- var stringRepresentation = escapeString(binding.value);
- if (binding["xml:lang"]) {
- stringRepresentation = '"' + stringRepresentation + '"@' + binding["xml:lang"];
- } else if (binding.datatype) {
- var xmlSchemaNs = "http://www.w3.org/2001/XMLSchema#";
- var dataType = binding.datatype;
- if (dataType.indexOf(xmlSchemaNs) == 0) {
- dataType = "xsd:" + dataType.substring(xmlSchemaNs.length);
- } else {
- dataType = "<" + dataType + ">";
- }
-
- stringRepresentation = '"' + stringRepresentation + '"^^' + dataType;
- } else {
- //just put quotes around it
- stringRepresentation = '"' + stringRepresentation + '"';
- }
- value = "<span class='nonUri'>" + stringRepresentation + "</span>";
- } else {
- //this is a catch-all: when using e.g. a csv content type, the bindings are not typed
- value = escapeString(binding.value);
- }
- return "<div>" + value + "</div>";
- };
-
- /* JsLint */
- /*
- * global sprintf, testCSS, loadConfig, bindEvents, $, onConfigLoaded,
- * updatePrefixDeclaration, _, showCurrentQuery, setCurrentEndpoint,
- * setCurrentFormat, elementVisible, runQuery, onLookupPrefix,
- * startTimingResults, onAddPrefix, initQuery, CodeMirror, onQuerySuccess,
- * onQueryFail, ajaxDataType, resetResults, XMLSerializer, showTableResult,
- * showCodeMirrorResult
- */
- /* --- module vars --- */
- /** The loaded configuration */
- var _config = {};
- var yasqe = null;
- var yasr = null;
- var _startTime = 0;
- var _outstandingQueries = 0;
- /* --- utils --- */
- /**
- * Return the string representation of the given XML value, which may be a
- * string or a DOM object
- */
- var xmlToString = function(xmlData) {
- var xs = _.isString(xmlData) ? xmlData : null;
- if (!xs && window.ActiveXObject && xmlData.xml) {
- xs = xmlData.xml;
- }
- if (!xs) {
- xs = new XMLSerializer().serializeToString(xmlData);
- }
- return xs;
- };
- /** Browser sniffing */
- var isOpera = function() {
- return !!(window.opera && window.opera.version);
- }; // Opera 8.0+
- var isFirefox = function() {
- return testCSS('MozBoxSizing');
- }; // FF 0.8+
- var isSafari = function() {
- return Object.prototype.toString.call(window.HTMLElement).indexOf(
- 'Constructor') > 0;
- }; // At least Safari 3+: "[object HTMLElementConstructor]"
- var isChrome = function() {
- return !isSafari() && testCSS('WebkitTransform');
- }; // Chrome 1+
- var isIE = function() {
- return /* @cc_on!@ */false || testCSS('msTransform');
- }; // At least IE6
- var testCSS = function(prop) {
- return document.documentElement.style.hasOwnProperty(prop);
- };
- /* --- application code --- */
- /** Initialisation - only called once */
- var init = function(config) {
- initYasqe();
- loadConfig(config);
- bindEvents();
- };
- var initYasqe = function() {
- yasqe = YASQE(document.getElementById("query-edit-cm"), {
- sparql: {
- showQueryButton: true,
- callbacks: {
- beforeSend: startTimingResults,
- complete: showTime,
- }
- }
- });
- yasr = YASR(document.getElementById("results"), {
- useGoogleCharts: false,
- //this way, the URLs in the results are prettified using the defined prefixes in the query
- getUsedPrefixes: yasqe.getPrefixesFromQuery
- });
-
- /**
- * Set some of the hooks to link YASR and YASQE
- */
- yasqe.options.sparql.callbacks.complete = yasr.setResponse;
- };
- /** Load the configuration definition */
- var loadConfig = function(config) {
- if (config.configURL) {
- $.getJSON(config.configURL, onConfigLoaded);
- } else {
- onConfigLoaded(config);
- }
- };
- /** Return the current config object */
- var config = function() {
- return _config;
- };
- /** Bind events that we want to manage */
- var bindEvents = function() {
- $("ul.prefixes").on(
- "click",
- "a.btn",
- function(e) {
- var elem = $(e.currentTarget);
- updatePrefixDeclaration($.trim(elem.text()), elem
- .data("uri"), !elem.is(".active"));
- });
- $("ul.examples").on("click", "a", function(e) {
- var elem = $(e.currentTarget);
- $("ul.examples a").removeClass("active");
- _.defer(function() {
- showCurrentQuery();
- });
- });
- $(".endpoints").on("click", "a", function(e) {
- var elem = $(e.currentTarget);
- setCurrentEndpoint($.trim(elem.text()));
- });
- $("#sparqlEndpoint").change(function() {
- yasqe.options.sparql.endpoint = $(this).val();
- });
- // dialogue events
- $("#prefixEditor").on("click", "#lookupPrefix", onLookupPrefix).on(
- "keyup", "#inputPrefix", function(e) {
- var elem = $(e.currentTarget);
- $("#lookupPrefix span").text(sprintf("'%s'", elem.val()));
- });
- $("#addPrefix").on("click", onAddPrefix);
-
- /**
- * register content type changes.
- * Do not need to set them on load, as their default values are already the default vals of YASQE as well
- */
- $("#graphContentType").change(function(){yasqe.options.sparql.acceptHeaderGraph = $(this).val()});
- $("#selectContentType").change(function(){yasqe.options.sparql.acceptHeaderSelect = $(this).val()});
- };
- /** List the current defined prefixes from the config */
- var initPrefixes = function(config) {
- var prefixAdd = $("ul.prefixes li:last");
- $
- .each(
- config.prefixes,
- function(key, value) {
- var html = sprintf(
- "<li><a class='btn btn-custom2 btn-sm' data-toggle='button' data-uri='%s'>%s</a></li>",
- value, key);
- $(html).insertBefore(prefixAdd);
- });
- };
- /** List the example queries from the config */
- var initExamples = function(config) {
- var examples = $("ul.examples");
- examples.empty();
- $
- .each(
- config.queries,
- function(i, queryDesc) {
- var html = sprintf(
- "<li><a class='btn btn-custom2 btn-sm' data-toggle='button'>%s</a></li>",
- queryDesc.name);
- examples.append(html);
- if (queryDesc.queryURL) {
- loadRemoteQuery(queryDesc.name,
- queryDesc.queryURL);
- }
- });
-
- setFirstQueryActive();
- };
- /** Set the default active query */
- var setFirstQueryActive = function() {
- if (_outstandingQueries === 0 && yasqe.getValue() == YASQE.defaults.value) {
- //only load the example query, when YASQE has not retrieved a previous query executed by the client
- $("ul.examples").find("a").first().addClass("active");
-
- showCurrentQuery();
- }
- };
- /** Load a remote query */
- var loadRemoteQuery = function(name, url) {
- _outstandingQueries++;
- var options = {
- success : function(data, xhr) {
- namedExample(name).query = data;
- _outstandingQueries--;
- setFirstQueryActive();
- },
- failure : function() {
- namedExample(name).query = "Not found: " + url;
- _outstandingQueries--;
- setFirstQueryActive();
- },
- dataType : "text"
- };
- $.ajax(url, options);
- };
- /** Set up the drop-down list of end-points */
- var initEndpoints = function(config) {
- var endpoints = $("ul.endpoints");
- endpoints.empty();
- if (config.endpoints) {
- $
- .each(
- config.endpoints,
- function(key, url) {
- var html = sprintf(
- "<li role='presentation'><a role='menuitem' tabindex='-1' href='#'>%s</a></li>",
- url);
- endpoints.append(html);
- });
- setCurrentEndpoint(config.endpoints["default"]);
- }
- };
- /** Successfully loaded the configuration */
- var onConfigLoaded = function(config, status, jqXHR) {
- _config = config;
- initPrefixes(config);
- initExamples(config);
- initEndpoints(config);
- };
- /** Set the current endpoint text */
- var setCurrentEndpoint = function(url) {
- yasqe.options.sparql.endpoint = url;
- $("[id=sparqlEndpoint]").val(url);
- };
- /** Return the current endpoint text */
- var currentEndpoint = function(url) {
- return $("[id=sparqlEndpoint]").val();
- };
- /** Return the query definition with the given name */
- var namedExample = function(name) {
- return _.find(config().queries, function(ex) {
- return ex.name === name;
- });
- };
- /** Return the currently active named example */
- var currentNamedExample = function() {
- return namedExample($.trim($("ul.examples a.active").first().text()));
- };
- /** Display the given query, with the currently defined prefixes */
- var showCurrentQuery = function() {
- var query = currentNamedExample();
- displayQuery(query);
- };
- /** Display the given query */
- var displayQuery = function(query) {
- if (query) {
- var queryBody = query.query ? query.query : query;
- var prefixes = assemblePrefixes(queryBody, query.prefixes)
- var q = sprintf("%s\n\n%s", renderPrefixes(prefixes),
- stripLeader(queryBody));
- yasqe.setValue(q);
- syncPrefixButtonState(prefixes);
- }
- };
- /** Return the currently selected output format */
- var selectedFormat = function() {
- return $("a.display-format").data("value");
- };
- /** Update the user's format selection */
- var setCurrentFormat = function(val, label) {
- $("a.display-format").data("value", val).find("span").text(label);
- };
- /** Assemble the set of prefixes to use when initially rendering the query */
- var assemblePrefixes = function(queryBody, queryDefinitionPrefixes) {
- if (queryBody.match(/^prefix/)) {
- // strategy 1: there are prefixes encoded in the query body
- return assemblePrefixesFromQuery(queryBody);
- } else if (queryDefinitionPrefixes) {
- // strategy 2: prefixes given in query def
- return _.map(queryDefinitionPrefixes, function(prefixName) {
- return {
- name : prefixName,
- uri : config().prefixes[prefixName]
- };
- });
- } else {
- return assembleCurrentPrefixes();
- }
- };
- /** Return an array comprising the currently selected prefixes */
- var assembleCurrentPrefixes = function() {
- var l = $("ul.prefixes a.active").map(function(i, elt) {
- return {
- name : $.trim($(elt).text()),
- uri : $(elt).data("uri")
- };
- });
- return $.makeArray(l);
- };
- // /** Return an array of the prefixes parsed from the given query body */
- // var assemblePrefixesFromQuery = function(queryBody) {
- // var leader = queryLeader(queryBody)[0].trim();
- // var pairs = _.compact(leader.split("prefix"));
- // var prefixes = [];
- //
- // _.each(pairs, function(pair) {
- // var m = pair.match("^\\s*(\\w+)\\s*:\\s*<([^>]*)>\\s*$");
- // prefixes.push({
- // name : m[1],
- // uri : m[2]
- // });
- // });
- //
- // return prefixes;
- // };
- /**
- * Ensure that the prefix buttons are in sync with the prefixes used in a
- * new query
- */
- var syncPrefixButtonState = function(prefixes) {
- $("ul.prefixes a").each(function(i, elt) {
- var name = $.trim($(elt).text());
- if (_.find(prefixes, function(p) {
- return p.name === name;
- })) {
- $(elt).addClass("active");
- } else {
- $(elt).removeClass("active");
- }
- });
- };
- /** Split a query into leader (prefixes and leading blank lines) and body */
- var queryLeader = function(query) {
- var pattern = /(prefix [^>]+>[\s\n]*)/;
- var queryBody = query;
- var i = 0;
- var m = queryBody.match(pattern);
- while (m) {
- i += m[1].length;
- queryBody = queryBody.substring(i);
- m = queryBody.match(pattern);
- }
- return [ query.substring(0, query.length - queryBody.length), queryBody ];
- };
- /** Remove the query leader */
- var stripLeader = function(query) {
- return queryLeader(query)[1];
- };
- /** Return a string comprising the given prefixes */
- var renderPrefixes = function(prefixes) {
- return _.map(prefixes, function(p) {
- return sprintf("prefix %s: <%s>", p.name, p.uri);
- }).join("\n");
- };
- /** Add or remove the given prefix declaration from the current query */
- var updatePrefixDeclaration = function(prefix, uri, added) {
- var prefixObj = {};
- prefixObj[prefix] = uri;
- if (added) {
- yasqe.addPrefixes(prefixObj);
- } else {
- yasqe.removePrefixes(prefixObj);
- }
- };
- /** Return the sparql service we're querying against */
- var sparqlService = function() {
- var service = config().service;
- if (!service) {
- // default is the remote service
- config().service = new RemoteSparqlService();
- service = config().service;
- }
- return service;
- };
- /** Hide or reveal an element using Bootstrap .hidden class */
- var elementVisible = function(elem, visible) {
- if (visible) {
- $(elem).removeClass("hidden");
- } else {
- $(elem).addClass("hidden");
- }
- };
- /** Prepare to show query time taken */
- var startTimingResults = function() {
- _startTime = new Date().getTime();
- elementVisible(".timeTaken");
- };
-
-
- /** Show results count and time */
- var showTime = function() {
- var duration = new Date().getTime() - _startTime;
- var ms = duration % 1000;
- duration = Math.floor(duration / 1000);
- var s = duration % 60;
- var m = Math.floor(duration / 60);
- var html = sprintf("time taken: %d min %d.%03d s", m, s, ms);
- $(".timeTaken").html(html);
- elementVisible(".timeTaken", true);
- };
- /** Lookup a prefix on prefix.cc */
- var onLookupPrefix = function(e) {
- e.preventDefault();
- var prefix = $.trim($("#inputPrefix").val());
- $("#inputURI").val("");
- if (prefix) {
- $.getJSON(sprintf("http://prefix.cc/%s.file.json", prefix),
- function(data) {
- $("#inputURI").val(data[prefix]);
- });
- }
- };
- /** User wishes to add the prefix */
- var onAddPrefix = function(e) {
- var prefix = $.trim($("#inputPrefix").val());
- var uri = $.trim($("#inputURI").val());
- if (uri) {
- _config.prefixes[prefix] = uri;
- } else {
- delete _config.prefixes[prefix];
- }
- // remember the state of current user selections, then re-create the
- // list
- var selections = {};
- $("ul.prefixes a.btn").each(function(i, a) {
- selections[$(a).text()] = $(a).hasClass("active");
- });
- $("ul.prefixes li[class!=keep]").remove();
- initPrefixes(_config);
- // restore selections state
- $.each(selections, function(k, v) {
- if (!v) {
- $(sprintf("ul.prefixes a.btn:contains('%s')", k)).removeClass(
- "active");
- }
- });
- var lines = yasqe.getValue().split("\n");
- lines = _.reject(lines, function(line) {
- return line.match(/^prefix/);
- });
- var q = sprintf("%s\n%s", renderPrefixes(assembleCurrentPrefixes()),
- lines.join("\n"));
- yasqe.setValue(q);
- };
- /** Disable or enable the button to submit a query */
- var disableSubmit = function(disable) {
- var elem = $("a.run-query");
- elem.prop('disabled', disable);
- if (disable) {
- elem.addClass("disabled");
- } else {
- elem.removeClass("disabled");
- }
- };
- return {
- init : init,
- setCurrentEndpoint: setCurrentEndpoint
- };
- }();
|