", {
38 | class: "errorHeader"
39 | }).appendTo($container);
40 |
41 | if (error.status !== 0) {
42 | var statusText = "Error";
43 | if (error.statusText && error.statusText.length < 100) {
44 | //use a max: otherwise the alert span will look ugly
45 | statusText = error.statusText;
46 | }
47 | statusText += " (#" + error.status + ")";
48 |
49 | $header
50 | .append(
51 | $("
", {
52 | class: "exception"
53 | }).text(statusText)
54 | )
55 | .append(getTryBtn());
56 |
57 | var responseText = null;
58 | if (error.responseText) {
59 | responseText = error.responseText;
60 | } else if (typeof error == "string") {
61 | //for backwards compatability (when creating the error string was done externally
62 | responseText = error;
63 | }
64 | if (responseText) $container.append($("").text(responseText));
65 | } else {
66 | $header.append(getTryBtn());
67 | //cors disabled, wrong url, or endpoint down
68 | $container.append(
69 | $("", {
70 | class: "corsMessage"
71 | }).append(options.corsMessage)
72 | );
73 | }
74 | };
75 |
76 | var canHandleResults = function(yasr) {
77 | return yasr.results.getException() || false;
78 | };
79 |
80 | return {
81 | name: null, //don't need to set this: we don't show it in the selection widget anyway, so don't need a human-friendly name
82 | draw: draw,
83 | getPriority: 20,
84 | hideFromSelection: true,
85 | canHandleResults: canHandleResults
86 | };
87 | };
88 |
89 | /**
90 | * Defaults for error plugin
91 | *
92 | * @type object
93 | * @attribute YASR.plugins.error.defaults
94 | */
95 | root.defaults = {
96 | corsMessage: "Unable to get response from endpoint",
97 | tryQueryLink: null
98 | };
99 |
--------------------------------------------------------------------------------
/src/error.scss:
--------------------------------------------------------------------------------
1 | .errorResult {
2 | .errorHeader {
3 | overflow:hidden;
4 | .yasr_tryQuery {
5 | float:right;
6 | padding-top: 3px;
7 | padding-bottom:3px;
8 | }
9 | span.exception {
10 | display: inline;
11 | padding: .2em .6em .3em;
12 | font-size: 75%;
13 | font-weight: 700;
14 | line-height: 1;
15 | color: #fff;
16 | text-align: center;
17 | white-space: nowrap;
18 | vertical-align: baseline;
19 | border-radius: .25em;
20 | background-color: #d9534f;
21 |
22 | }
23 | }
24 |
25 | padding: 10px;
26 |
27 | pre {
28 | display: block;
29 | padding: 10px;
30 | margin: 10px 0 10px;
31 | font-size: 13px;
32 | line-height: 1.42857;
33 | word-break: break-all;
34 | word-wrap: break-word;
35 | color: #333;
36 | background-color: #f5f5f5;
37 | border: 1px solid #ccc;
38 | border-radius: 4px;
39 | }
40 | .corsMessage {
41 | color: #a94442;
42 | background-color: #f2dede;
43 | margin-top: 10px;
44 | padding: 5px;
45 | border: 1px solid #ebccd1;
46 | border-radius: 4px;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/exceptions.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | GoogleTypeException: function(foundTypes, varName) {
3 | this.foundTypes = foundTypes;
4 | this.varName = varName;
5 | this.toString = function() {
6 | var string = "Conflicting data types found for variable " +
7 | this.varName +
8 | '. Assuming all values of this variable are "string".';
9 | string += " To avoid this issue, cast the values in your SPARQL query to the intended xsd datatype";
10 |
11 | return string;
12 | };
13 | this.toHtml = function() {
14 | var string = "Conflicting data types found for variable
" +
15 | this.varName +
16 | ' . Assuming all values of this variable are "string".';
17 | string += " As a result, several Google Charts will not render values of this particular variable.";
18 | string += " To avoid this issue, cast the values in your SPARQL query to the intended xsd datatype";
19 |
20 | return string;
21 | };
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/src/gChartLoader.js:
--------------------------------------------------------------------------------
1 | var EventEmitter = require("events").EventEmitter, $ = require("jquery");
2 | //cannot package google loader via browserify....
3 | var loadingMain = false;
4 | var loadingFailed = false;
5 |
6 | var loader = function() {
7 | EventEmitter.call(this);
8 | var mod = this;
9 | this.init = function() {
10 | if (!loadingFailed && !require("google") && !loadingMain) {
11 | //not initiated yet, not currently loading, and has not failed the previous time
12 | loadingMain = true;
13 | /**
14 | * It is extremely difficult to catch script loader errors (see http://www.html5rocks.com/en/tutorials/speed/script-loading/)
15 | * Existing libraries either ignore several browsers (e.g. jquery 2.x), or use ugly hacks (timeouts or something)
16 | * So, we use our own custom ugly hack (yes, timeouts)
17 | */
18 | //use protocol relative req when served via http. Otherwise, just use http:// (e.g. when yasr is served via file://)
19 | loadScript((window.location.protocol.indexOf("http") === 0 ? "//" : "http://") + "google.com/jsapi", function() {
20 | loadingMain = false;
21 | mod.emit("initDone");
22 | });
23 |
24 | var timeout = 100; //ms
25 | var maxTimeout = 6000; //so 6 sec max
26 | var startTime = +new Date();
27 | var checkAndWait = function() {
28 | if (!require("google")) {
29 | if (+new Date() - startTime > maxTimeout) {
30 | //ok, we've waited long enough. Obviously we could not load the googleloader...
31 | loadingFailed = true;
32 | loadingMain = false;
33 | mod.emit("initError");
34 |
35 | //TODO: clear initDone callbacks. they won't fire anymore anyway
36 | } else {
37 | setTimeout(checkAndWait, timeout);
38 | }
39 | } else {
40 | //TODO: clear initFailed callbacks. they won't fire anymore anyway
41 | }
42 | };
43 | checkAndWait();
44 | } else {
45 | if (require("google")) {
46 | //already loaded! everything is fine
47 | mod.emit("initDone");
48 | } else if (loadingFailed) {
49 | mod.emit("initError");
50 | } else {
51 | //hmmm, should never get here
52 | }
53 | }
54 | };
55 | this.googleLoad = function() {
56 | var load = function() {
57 | require("google").load("visualization", "1", {
58 | packages: ["corechart", "charteditor"],
59 | callback: function() {
60 | mod.emit("done");
61 | }
62 | });
63 | };
64 | if (loadingMain) {
65 | mod.once("initDone", load);
66 | mod.once("initError", function() {
67 | mod.emit("error", "Could not load google loader");
68 | });
69 | } else if (require("google")) {
70 | //google loader is there. use it
71 | load();
72 | } else if (loadingFailed) {
73 | mod.emit("error", "Could not load google loader");
74 | } else {
75 | //not loading, no loading error, and not loaded. it must not have been initialized yet. Do that
76 | mod.once("initDone", load);
77 | mod.once("initError", function() {
78 | mod.emit("error", "Could not load google loader");
79 | });
80 | }
81 | };
82 | };
83 |
84 | var loadScript = function(url, callback) {
85 | var script = document.createElement("script");
86 | script.type = "text/javascript";
87 |
88 | if (script.readyState) {
89 | //IE
90 | script.onreadystatechange = function() {
91 | if (script.readyState == "loaded" || script.readyState == "complete") {
92 | script.onreadystatechange = null;
93 | callback();
94 | }
95 | };
96 | } else {
97 | //Others
98 | script.onload = function() {
99 | callback();
100 | };
101 | }
102 |
103 | script.src = url;
104 | document.body.appendChild(script);
105 | };
106 | loader.prototype = new EventEmitter();
107 | module.exports = new loader();
108 |
--------------------------------------------------------------------------------
/src/gchart.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * todo: chart height as option
4 | *
5 | */
6 | var $ = require("jquery"), utils = require("./utils.js"), yUtils = require("yasgui-utils");
7 |
8 | var root = module.exports = function(yasr) {
9 | var options = $.extend(true, {}, root.defaults);
10 | var id = yasr.container.closest("[id]").attr("id");
11 |
12 | var chartWrapper = null;
13 | var editor = null;
14 |
15 | var initEditor = function(callback) {
16 | var google = require("google");
17 | editor = new google.visualization.ChartEditor();
18 | google.visualization.events.addListener(editor, "ok", function() {
19 | var tmp;
20 | chartWrapper = editor.getChartWrapper();
21 | tmp = chartWrapper.getDataTable();
22 | chartWrapper.setDataTable(null);
23 | //ugly: need to parse json string to json obj again, as google chart does not provide access to object directly
24 | options.chartConfig = JSON.parse(chartWrapper.toJSON());
25 | //remove container ID though, for portability
26 | if (options.chartConfig.containerId) delete options.chartConfig["containerId"];
27 | yasr.store();
28 | chartWrapper.setDataTable(tmp);
29 | var wrapperId = id + "_gchartWrapper";
30 | var $wrapper = $("#" + wrapperId);
31 | chartWrapper.setOption("width", $wrapper.width());
32 | chartWrapper.setOption("height", $wrapper.height());
33 | chartWrapper.draw();
34 | yasr.updateHeader();
35 | });
36 | if (callback) callback();
37 | };
38 |
39 | return {
40 | name: "Google Chart",
41 | hideFromSelection: false,
42 | priority: 7,
43 | options: options,
44 | getPersistentSettings: function() {
45 | return {
46 | chartConfig: options.chartConfig,
47 | motionChartState: options.motionChartState
48 | };
49 | },
50 | setPersistentSettings: function(persSettings) {
51 | if (persSettings["chartConfig"]) options.chartConfig = persSettings["chartConfig"];
52 | if (persSettings["motionChartState"]) options.motionChartState = persSettings["motionChartState"];
53 | },
54 | canHandleResults: function(yasr) {
55 | var results, variables;
56 | return (results = yasr.results) != null && (variables = results.getVariables()) && variables.length > 0;
57 | },
58 | getDownloadInfo: function() {
59 | if (!yasr.results) return null;
60 | var svgEl = yasr.resultsContainer.find("svg");
61 | if (svgEl.length > 0) {
62 | return {
63 | getContent: function() {
64 | if (svgEl[0].outerHTML) {
65 | return svgEl[0].outerHTML;
66 | } else {
67 | //outerHTML not supported. use workaround
68 | return $("
").append(svgEl.clone()).html();
69 | }
70 | },
71 | filename: "queryResults.svg",
72 | contentType: "image/svg+xml",
73 | buttonTitle: "Download SVG Image"
74 | };
75 | }
76 | //ok, not a svg. is it a table?
77 | var $table = yasr.resultsContainer.find(".google-visualization-table-table");
78 | if ($table.length > 0) {
79 | return {
80 | getContent: function() {
81 | return $table.tableToCsv();
82 | },
83 | filename: "queryResults.csv",
84 | contentType: "text/csv",
85 | buttonTitle: "Download as CSV"
86 | };
87 | }
88 | },
89 | getEmbedHtml: function() {
90 | if (!yasr.results) return null;
91 |
92 | var svgEl = yasr.resultsContainer
93 | .find("svg")
94 | .clone() //create clone, as we'd like to remove height/width attributes
95 | .removeAttr("height")
96 | .removeAttr("width")
97 | .css("height", "")
98 | .css("width", "");
99 | if (svgEl.length == 0) return null;
100 |
101 | var htmlString = svgEl[0].outerHTML;
102 | if (!htmlString) {
103 | //outerHTML not supported. use workaround
104 | htmlString = $("
").append(svgEl.clone()).html();
105 | }
106 | //wrap in div, so users can more easily tune width/height
107 | //don't use jquery, so we can easily influence indentation
108 | return '
\n' + htmlString + "\n
";
109 | },
110 | draw: function(_customOpts) {
111 | var customOpts = $.extend(true, {}, options, _customOpts);
112 | var doDraw = function() {
113 | //clear previous results (if any)
114 | yasr.resultsContainer.empty();
115 | var wrapperId = id + "_gchartWrapper";
116 |
117 | yasr.resultsContainer
118 | .append(
119 | $("
", {
120 | class: "openGchartBtn yasr_btn",type: "button"
121 | })
122 | .text("Chart Config")
123 | .click(function() {
124 | editor.openDialog(chartWrapper);
125 | })
126 | )
127 | .append(
128 | $("", {
129 | id: wrapperId,
130 | class: "gchartWrapper"
131 | })
132 | );
133 | var dataTable = new google.visualization.DataTable();
134 | //clone, because we'll be manipulating the literals types
135 | var jsonResults = $.extend(true, {}, yasr.results.getAsJson());
136 | jsonResults.head.vars.forEach(function(variable) {
137 | var type = "string";
138 | try {
139 | type = utils.getGoogleTypeForBindings(jsonResults.results.bindings, variable);
140 | } catch (e) {
141 | if (e instanceof require("./exceptions.js").GoogleTypeException) {
142 | yasr.warn(e.toHtml());
143 | } else {
144 | throw e;
145 | }
146 | }
147 | dataTable.addColumn(type, variable);
148 | });
149 | var usedPrefixes = null;
150 | if (yasr.options.getUsedPrefixes) {
151 | usedPrefixes = typeof yasr.options.getUsedPrefixes == "function"
152 | ? yasr.options.getUsedPrefixes(yasr)
153 | : yasr.options.getUsedPrefixes;
154 | }
155 | jsonResults.results.bindings.forEach(function(binding) {
156 | var row = [];
157 | jsonResults.head.vars.forEach(function(variable, columnId) {
158 | row.push(utils.castGoogleType(binding[variable], usedPrefixes, dataTable.getColumnType(columnId)));
159 | });
160 | dataTable.addRow(row);
161 | });
162 | if (customOpts.chartConfig && customOpts.chartConfig.chartType) {
163 | customOpts.chartConfig.containerId = wrapperId;
164 | chartWrapper = new google.visualization.ChartWrapper(customOpts.chartConfig);
165 | if (chartWrapper.getChartType() === "MotionChart" && customOpts.motionChartState) {
166 | chartWrapper.setOption("state", customOpts.motionChartState);
167 | google.visualization.events.addListener(chartWrapper, "ready", function() {
168 | var motionChart;
169 | motionChart = chartWrapper.getChart();
170 | google.visualization.events.addListener(motionChart, "statechange", function() {
171 | customOpts.motionChartState = motionChart.getState();
172 | yasr.store();
173 | });
174 | });
175 | }
176 | chartWrapper.setDataTable(dataTable);
177 | } else {
178 | chartWrapper = new google.visualization.ChartWrapper({
179 | chartType: "Table",
180 | dataTable: dataTable,
181 | containerId: wrapperId
182 | });
183 | }
184 | var $wrapper = $("#" + wrapperId);
185 | chartWrapper.setOption("width", $wrapper.width());
186 | chartWrapper.setOption("height", $wrapper.height());
187 | chartWrapper.draw();
188 | // introduce handler
189 | if ( customOpts.selectHandler && typeof(customOpts.selectHandler) == 'function')
190 | google.visualization.events.addListener(chartWrapper, "select", function() { customOpts.selectHandler(chartWrapper,jsonResults); });
191 |
192 | google.visualization.events.addListener(chartWrapper, "ready", yasr.updateHeader);
193 | };
194 |
195 | if (!require("google") || !require("google").visualization || !editor) {
196 | require("./gChartLoader.js")
197 | .on("done", function() {
198 | initEditor();
199 | doDraw();
200 | })
201 | .on("error", function() {
202 | //TODO: disable or something?
203 | })
204 | .googleLoad();
205 | } else {
206 | //everything (editor as well) is already initialized
207 | doDraw();
208 | }
209 | }
210 | };
211 | };
212 | root.defaults = {
213 | height: "100%",
214 | width: "100%",
215 | persistencyId: "gchart",
216 | chartConfig: null,
217 | motionChartState: null
218 | };
219 |
220 | function deepEq$(x, y, type) {
221 | var toString = ({}).toString,
222 | hasOwnProperty = ({}).hasOwnProperty,
223 | has = function(obj, key) {
224 | return hasOwnProperty.call(obj, key);
225 | };
226 | var first = true;
227 | return eq(x, y, []);
228 |
229 | function eq(a, b, stack) {
230 | var className, length, size, result, alength, blength, r, key, ref, sizeB;
231 | if (a == null || b == null) {
232 | return a === b;
233 | }
234 | if (a.__placeholder__ || b.__placeholder__) {
235 | return true;
236 | }
237 | if (a === b) {
238 | return a !== 0 || 1 / a == 1 / b;
239 | }
240 | className = toString.call(a);
241 | if (toString.call(b) != className) {
242 | return false;
243 | }
244 | switch (className) {
245 | case "[object String]":
246 | return a == String(b);
247 | case "[object Number]":
248 | return a != +a ? b != +b : a == 0 ? 1 / a == 1 / b : a == +b;
249 | case "[object Date]":
250 | case "[object Boolean]":
251 | return +a == +b;
252 | case "[object RegExp]":
253 | return a.source == b.source &&
254 | a.global == b.global &&
255 | a.multiline == b.multiline &&
256 | a.ignoreCase == b.ignoreCase;
257 | }
258 | if (typeof a != "object" || typeof b != "object") {
259 | return false;
260 | }
261 | length = stack.length;
262 | while (length--) {
263 | if (stack[length] == a) {
264 | return true;
265 | }
266 | }
267 | stack.push(a);
268 | size = 0;
269 | result = true;
270 | if (className == "[object Array]") {
271 | alength = a.length;
272 | blength = b.length;
273 | if (first) {
274 | switch (type) {
275 | case "===":
276 | result = alength === blength;
277 | break;
278 | case "<==":
279 | result = alength <= blength;
280 | break;
281 | case "<<=":
282 | result = alength < blength;
283 | break;
284 | }
285 | size = alength;
286 | first = false;
287 | } else {
288 | result = alength === blength;
289 | size = alength;
290 | }
291 | if (result) {
292 | while (size--) {
293 | if (!(result = size in a == size in b && eq(a[size], b[size], stack))) {
294 | break;
295 | }
296 | }
297 | }
298 | } else {
299 | if ("constructor" in a != "constructor" in b || a.constructor != b.constructor) {
300 | return false;
301 | }
302 | for (key in a) {
303 | if (has(a, key)) {
304 | size++;
305 | if (!(result = has(b, key) && eq(a[key], b[key], stack))) {
306 | break;
307 | }
308 | }
309 | }
310 | if (result) {
311 | sizeB = 0;
312 | for (key in b) {
313 | if (has(b, key)) {
314 | ++sizeB;
315 | }
316 | }
317 | if (first) {
318 | if (type === "<<=") {
319 | result = size < sizeB;
320 | } else if (type === "<==") {
321 | result = size <= sizeB;
322 | } else {
323 | result = size === sizeB;
324 | }
325 | } else {
326 | first = false;
327 | result = size === sizeB;
328 | }
329 | }
330 | }
331 | stack.pop();
332 | return result;
333 | }
334 | }
335 |
--------------------------------------------------------------------------------
/src/gchart.scss:
--------------------------------------------------------------------------------
1 |
2 | .openGchartBtn{
3 | float:right;
4 | position:relative;
5 | top:-35px;
6 | margin-bottom:-35px;
7 | }
8 | .gchartWrapper {
9 | width: 100%;
10 | height:600px;
11 | margin-top: 2px;
12 | }
13 |
--------------------------------------------------------------------------------
/src/imgs.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | module.exports = {
3 | cross: '
',
4 | check: '
',
5 | unsorted: '
',
6 | sortDesc: '
',
7 | sortAsc: '
',
8 | download: '
',
9 | move: '
image/svg+xml ',
10 | fullscreen: '
image/svg+xml ',
11 | smallscreen: '
image/svg+xml '
12 | };
13 |
--------------------------------------------------------------------------------
/src/jquery/extendJquery.js:
--------------------------------------------------------------------------------
1 | require("./tableToCsv.js");
2 |
--------------------------------------------------------------------------------
/src/jquery/tableToCsv.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 |
4 | $.fn.tableToCsv = function(config) {
5 | var csvString = "";
6 | config = $.extend(
7 | {
8 | quote: '"',
9 | delimiter: ",",
10 | lineBreak: "\n"
11 | },
12 | config
13 | );
14 |
15 | var needToQuoteString = function(value) {
16 | //quote when it contains whitespace or the delimiter
17 | var needQuoting = false;
18 | if (value.match("[\\w|" + config.delimiter + "|" + config.quote + "]")) {
19 | needQuoting = true;
20 | }
21 | return needQuoting;
22 | };
23 | var addValueToString = function(value) {
24 | //Quotes in the string need to be escaped
25 | value.replace(config.quote, config.quote + config.quote);
26 | if (needToQuoteString(value)) {
27 | value = config.quote + value + config.quote;
28 | }
29 | csvString += " " + value + " " + config.delimiter;
30 | };
31 |
32 | var addRowToString = function(rowArray) {
33 | rowArray.forEach(function(val) {
34 | addValueToString(val);
35 | });
36 | csvString += config.lineBreak;
37 | };
38 |
39 | var tableArrays = [];
40 | var $el = $(this);
41 | var rowspans = {};
42 |
43 | var totalColCount = 0;
44 | $el.find("tr:first *").each(function() {
45 | if ($(this).attr("colspan")) {
46 | totalColCount += +$(this).attr("colspan");
47 | } else {
48 | totalColCount++;
49 | }
50 | });
51 |
52 | $el.find("tr").each(function(rowId, tr) {
53 | var $tr = $(tr);
54 | var rowArray = [];
55 |
56 | var htmlColId = 0;
57 | var actualColId = 0;
58 | while (actualColId < totalColCount) {
59 | if (rowspans[actualColId]) {
60 | rowArray.push(rowspans[actualColId].text);
61 | rowspans[actualColId].rowSpan--;
62 | if (!rowspans[actualColId].rowSpan) rowspans[actualColId] = null;
63 | actualColId++;
64 | continue;
65 | }
66 |
67 | var $cell = $tr.find(":nth-child(" + (htmlColId + 1) + ")");
68 | if (!$cell) break;
69 | var colspan = $cell.attr("colspan") || 1;
70 | var rowspan = $cell.attr("rowspan") || 1;
71 |
72 | for (var i = 0; i < colspan; i++) {
73 | rowArray.push($cell.text());
74 | if (rowspan > 1) {
75 | rowspans[actualColId] = {
76 | rowSpan: rowspan - 1,
77 | text: $cell.text()
78 | };
79 | }
80 | actualColId++;
81 | }
82 | htmlColId++;
83 | }
84 | addRowToString(rowArray);
85 | });
86 |
87 | return csvString;
88 | };
89 |
--------------------------------------------------------------------------------
/src/leaflet.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 |
4 | var LibColor = require("color");
5 | var wellknown = require('wellknown')
6 | var colormap = require('colormap');
7 | var _colorbrewer = require('colorbrewer')
8 | var colorbrewer = {};
9 | //postprocess colorbrower so we store the identifiers case insensitive.
10 | //also make sure to only add 1 map per identifier (it has several maps, each with varying specificity)
11 | for (var color in _colorbrewer) {
12 | var mostSpecificScale = [];
13 | $.each(_colorbrewer[color], function(i, scale) {
14 | if (scale.length > mostSpecificScale.length) mostSpecificScale = scale;
15 | })
16 | colorbrewer[color.toLowerCase()] = mostSpecificScale
17 | }
18 |
19 | var colorScales = require('colormap/colorScale');
20 | function getHexFromScale(scaleType, scaleVal) {
21 | if (scaleVal > 1 || scaleVal < 0) return;
22 | if (!scaleType.length) return
23 | var hexScale;
24 | if (colorbrewer[scaleType.toLowerCase()]) {
25 | //colorbrewer: http://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3
26 | hexScale = colorbrewer[scaleType.toLowerCase()];
27 | } else if (colorScales[scaleType]) {
28 | //colormap: https://github.com/bpostlethwaite/colormap
29 | hexScale = colormap({colormap: scaleType});
30 | }
31 | if (!hexScale || !hexScale.length) return;
32 | var index = Math.max(Math.round(scaleVal * hexScale.length) -1, 0);
33 | return hexScale[index];
34 | }
35 | var root = (module.exports = function(yasr) {
36 | var plugin = {};
37 | var options = $.extend(true, {}, root.defaults);
38 | var defaultColor = LibColor(options.defaultColor);
39 | var defaultStyle = options.defaultStyle;
40 |
41 | var cm = null;
42 |
43 | var getOption = function(key) {
44 | // if (!options[key]) return {};
45 | if (options[key]) {
46 | if (typeof options[key] === "function") {
47 | return options[key](yasr, L);
48 | } else {
49 | return options[key];
50 | }
51 | } else {
52 | return undefined;
53 | }
54 | };
55 |
56 |
57 | var getSvgMarker = function(Colors) {
58 | var fillColor2 = Colors.fill.lighten(0.3).toString();
59 | var borderColor2 = Colors.border.lighten(0.3).toString();
60 | var fillId=''+Math.random();
61 | return (
62 | '
'
71 | );
72 | };
73 | var draw = function() {
74 | var _L = options.L;
75 |
76 | var zoomToEl = function(e) {
77 | map.setView(e.latlng, 15);
78 | };
79 | var plotVariables = getGeoVariables();
80 | if (plotVariables.length === 0)
81 | return $('
Nothing to draw
').appendTo(yasr.resultsContainer);
82 | var mapWrapper = $('
').appendTo(yasr.resultsContainer);
83 | var mapConstructor = options.map;
84 | if (!mapConstructor) mapConstructor = options.maps[options.defaultMap || "osm"];
85 | if (!mapConstructor) {
86 | console.error('Could not find leaflet configuration for map ' + options.defaultMap);
87 | return;
88 | }
89 | var map = new _L.Map(mapWrapper.get()[0], mapConstructor(yasr, L));
90 |
91 | var mapLayers = options.defaultOverlay;
92 | if(mapLayers) _L.control.layers(null, mapLayers).addTo(map);
93 |
94 | if (options.clickBeforeInteract) {
95 | map.scrollWheelZoom.disable();
96 | map.on('focus', function() { map.scrollWheelZoom.enable(); });
97 | map.on('blur', function() { map.scrollWheelZoom.disable(); });
98 | }
99 | var features = [];
100 | var bindings = yasr.results.getBindings();
101 | var hasLabel = false;
102 | for (var varId = 0; varId < plotVariables.length; varId++) {
103 | var plotVariable = plotVariables[varId];
104 |
105 | for (var i = 0; i < bindings.length; i++) {
106 | var binding = bindings[i];
107 | if (! binding[plotVariable] || !binding[plotVariable].value) continue;
108 |
109 | var getColor = function() {
110 | var colorBinding = binding[plotVariable + "Color"];
111 | if (colorBinding) {
112 | var colorVal = colorBinding.value;
113 | var scaleSettings = colorVal.split(',');
114 |
115 |
116 | if (scaleSettings.length === 2) {
117 | var colorFromScale = getHexFromScale(scaleSettings[0].trim(),scaleSettings[1].trim())
118 | if (colorFromScale) colorVal = colorFromScale;
119 | }
120 | try {
121 | return LibColor(colorVal);
122 | } catch(e) {
123 | //invalid color representation
124 | return LibColor('grey')
125 | }
126 | }
127 | return defaultColor;
128 | };
129 | var Colors = {
130 | fill: getColor()
131 | };
132 | Colors.border = Colors.fill.saturate(0.2);
133 | var mySVGIcon = _L.divIcon({
134 | iconSize: [25, 41],
135 | // shadowSize: [25, 45],
136 | iconAnchor: [12, 41],
137 | popupAnchor: [0, -41],
138 | html: getSvgMarker(Colors)
139 | });
140 |
141 |
142 | var style = $.extend({}, defaultStyle, { icon: mySVGIcon, color: Colors.fill.toString()})
143 | var wkt = wellknown(binding[plotVariable].value);
144 | if (!wkt) {
145 | console.error('Failed to read WKT value: ' + binding[plotVariable].value)
146 | continue;
147 | }
148 | var feature = _L.geoJson(wkt, {style:style,
149 |
150 | pointToLayer: function(feature, latlng) {
151 | return _L.marker(latlng, { icon: mySVGIcon });
152 | }
153 |
154 | });
155 |
156 | var popupContent = options.formatPopup && options.formatPopup(yasr, L, plotVariable, binding);
157 | if (popupContent) {
158 | function addPopupAndEventsToMarker(el) {
159 | el.on("dblclick", zoomToEl);
160 | var popupContent = options.formatPopup && options.formatPopup(yasr, L, plotVariable, binding);
161 | if (popupContent) {
162 | hasLabel = true;
163 | el.bindPopup(popupContent);
164 | }
165 | }
166 |
167 | var markerPos;
168 | if (feature.getBounds) {
169 | //get center of polygon or something
170 | markerPos = feature.getBounds().getCenter();
171 | } else if (feature.getLatLng) {
172 | //its a point, just get the lat/lng
173 | markerPos = feature.getLatLng();
174 | }
175 | if (markerPos) {
176 | if (wkt.type === 'Point') {
177 | addPopupAndEventsToMarker(feature);
178 | } else {
179 | addPopupAndEventsToMarker(_L.marker(markerPos, { icon: mySVGIcon }).addTo(map));
180 | }
181 | }
182 | }
183 | features.push(feature);
184 | }
185 | }
186 | if (features.length) {
187 | try {
188 | var group = new _L.featureGroup(features).addTo(map);
189 | map.fitBounds(group.getBounds());
190 | } catch(e) {
191 | //This is a strange issue. Depending on which leaflet instance was used (i.e. the window.L one, or the required one)
192 | //we might run into issues where the returned bounds are undefined...
193 | //solved it by simply preferring the global instance (though this can be turned off)
194 | throw e;
195 | }
196 | }
197 |
198 | // missingPopupMsg: function(yasr, L, geoVariables, bindings) {
199 | if (!hasLabel && options.missingPopupMsg) {
200 | var msg = null;
201 | if (typeof options.missingPopupMsg === "string") {
202 | msg = options.missingPopupMsg;
203 | } else if (typeof options.missingPopupMsg === "function") {
204 | msg = options.missingPopupMsg(yasr, L, plotVariables);
205 | }
206 | if (msg) yasr.resultsContainer.prepend($('
').html(msg))
207 | // if (msg) yasr.resultsContainer.prepend(msg);
208 | }
209 | };
210 |
211 | var geoKeywords = ["POINT", "POLYGON", "LINESTRING", "MULTIPOINT", "MULTILINESTRING", "MULTIPOLYGON"];
212 | var valueIsGeometric = function(val) {
213 | val = val.trim().toUpperCase();
214 | for (var i = 0; i < geoKeywords.length; i++) {
215 | if (val.indexOf(geoKeywords[i]) === 0) {
216 | if (!wellknown(val)) {
217 | console.error('Failed to parse WKT value ' + val)
218 | continue;
219 | }
220 | return true;
221 | }
222 | }
223 | return false;
224 | };
225 | var getGeoVariables = function() {
226 | if (!yasr.results) return [];
227 | var bindings = yasr.results.getBindings();
228 | if (!bindings || bindings.length === 0) {
229 | return [];
230 | }
231 | var geoVars = [];
232 | var checkedVars = [];
233 | for (var i = 0; i < bindings.length; i++) {
234 | //we'd like to have checked at least 1 value for all variables. So keep looping
235 | //in case the first row does not contain values for all bound vars (e.g. optional)
236 | var binding = bindings[i];
237 | for (var bindingVar in binding) {
238 | if (checkedVars.indexOf(bindingVar) === -1 && binding[bindingVar].value) {
239 | checkedVars.push(bindingVar);
240 | if (valueIsGeometric(binding[bindingVar].value)) geoVars.push(bindingVar);
241 | }
242 | }
243 | if (checkedVars.length === yasr.results.getVariables().length) {
244 | //checked all vars. can break now
245 | break;
246 | }
247 | }
248 | return geoVars;
249 | };
250 | var canHandleResults = function() {
251 | return getGeoVariables().length > 0;
252 | };
253 |
254 | return {
255 | draw: draw,
256 | name: "Geo",
257 | canHandleResults: canHandleResults,
258 | getPriority: 2
259 | };
260 | });
261 |
262 | var maps = {
263 | osm: function(yasr, L) {
264 | return {
265 | layers: [
266 | new L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
267 | attribution: '©
OpenStreetMap contributors'
268 | })
269 | ]
270 | };
271 | },
272 | nlmaps: function(yasr, L) {
273 | return {
274 | layers: [
275 | new L.tileLayer("https://geodata.nationaalgeoregister.nl/tiles/service/wmts/brtachtergrondkaart/EPSG:3857/{z}/{x}/{y}.png", {
276 | attribution: 'NLMaps | Kaartgegevens © Kadaster |
verbeter de kaart '
277 | })
278 | ]
279 | };
280 | },
281 | /* free only up to 25'000 megapixels/year see https://shop.swisstopo.admin.ch/en/products/geoservice/swisstopo_geoservices/WMTS_info for further informations */
282 | chmaps: function(yasr, L) {
283 | var url = 'https://wmts10.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/3857/{z}/{x}/{y}.jpeg';
284 | var stopoAttr = 'Map data ©
swisstopo , ';
285 | var tilelayer = new L.tileLayer(url,{id: 'stopo.light', attribution: stopoAttr, minZoom: 4, maxZoom: 19});
286 |
287 | return {
288 | layers: [tilelayer] ,
289 | crs: L.CRS.EPSG3857,
290 | continuousWorld: true,
291 | worldCopyJump: false
292 | };
293 | }
294 | };
295 | root.defaults = {
296 | maps: maps,
297 | L: require('leaflet'),
298 | formatPopup: function(yasr, L, forVariable, bindings) {
299 | var binding = bindings[forVariable+"Label"];
300 | if (binding && binding.value) {
301 | if (binding.type === 'uri') {
302 | //format as link
303 | return '
' + binding.value + ' '
304 | } else {
305 | return binding.value;
306 | }
307 | }
308 | },
309 | missingPopupMsg: function(yasr, L, geoVariables) {
310 | if (geoVariables && geoVariables.length) {
311 | return (
312 | "
Tip: Add a label variable prefixed with the geo variable name to show popups on the map. E.g. " +
313 | geoVariables[0] +
314 | "Label
. Or, append Color
to change the color of the shape or marker. "
315 | );
316 | }
317 | },
318 | disabledTitle: "Query for geo variables in WKT format to plot them on a map",
319 | defaultColor: "#2e6c97",
320 | clickBeforeInteract: false,
321 | defaultStyle: {},
322 | defaultOverlay: null,
323 | defaultMap: "osm" //or nlmaps
324 | };
325 |
326 | root.version = {
327 | leaflet: root.defaults.L.version
328 | };
329 |
--------------------------------------------------------------------------------
/src/leaflet.scss:
--------------------------------------------------------------------------------
1 |
2 | .yasr_results {
3 |
4 | .leaflet {
5 | height:800px;
6 | width:100%;
7 | margin-top:10px;
8 | .leaflet-marker-icon.leaflet-div-icon {
9 | background-color:transparent;
10 | border:0;
11 | }
12 |
13 | .leaflet-control-layers-toggle {
14 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAQAAABvcdNgAAAEsklEQVR4AWL4TydIhpZK1kpWOlg0w3ZXP6D2soBtG42jeI6ZmQTHzAxiTbSJsYLjO9HhP+WOmcuhciVnmHVQcJnp7DFvScowZorad/+V/fVzMdMT2g9Cv9guXGv/7pYOrXh2U+RRR3dSd9JRx6bIFc/ekqHI29JC6pJ5ZEh1yWkhkbcFeSjxgx3L2m1cb1C7bceyxA+CNjT/Ifff+/kDk2u/w/33/IeCMOSaWZ4glosqT3DNnNZQ7Cs58/3Ce5HL78iZH/vKVIaYlqzfdLu8Vi7dnvUbEza5Idt36tquZFldl6N5Z/POLof0XLK61mZCmJSWjVF9tEjUluu74IUXvgttuVIHE7YxSkaYhJZam7yiM9Pv82JYfl9nptxZaxMJE4YSPty+vF0+Y2up9d3wwijfjZbabqm/3bZ9ecKHsiGmRflnn1MW4pjHf9oLufyn2z3y1D6n8g8TZhxyzipLNPnAUpsOiuWimg52psrTZYnOWYNDTMuWBWa0tJb4rgq1UvmutpaYEbZlwU3CLJm/ayYjHW5/h7xWLn9Hh1vepDkyf7dE7MtT5LR4e7yYpHrkhOUpEfssBLq2pPhAqoSWKUkk7EDqkmK6RrCEzqDjhNDWNE+XSMvkJRDWlZTmCW0l0PHQGRZY5t1L83kT0Y3l2SItk5JAWHl2dCOBm+fPu3fo5/3v61RMCO9Jx2EEYYhb0rmNQMX/vm7gqOEJLcXTGw3CAuRNeyaPWwjR8PRqKQ1PDA/dpv+on9Shox52WFnx0KY8onHayrJzm87i5h9xGw/tfkev0jGsQizqezUKjk12hBMKJ4kbCqGPVNXudyyrShovGw5CgxsRICxF6aRmSjlBnHRzg7Gx8fKqEubI2rahQYdR1YgDIRQO7JvQyD52hoIQx0mxa0ODtW2Iozn1le2iIRdzwWewedyZzewidueOGqlsn1MvcnQpuVwLGG3/IR1hIKxCjelIDZ8ldqWz25jWAsnldEnK0Zxro19TGVb2ffIZEsIO89EIEDvKMPrzmBOQcKQ+rroye6NgRRxqR4U8EAkz0CL6uSGOm6KQCdWjvjRiSP1BPalCRS5iQYiEIvxuBMJEWgzSoHADcVMuN7IuqqTeyUPq22qFimFtxDyBBJEwNyt6TM88blFHao/6tWWhuuOM4SAK4EI4QmFHA+SEyWlp4EQoJ13cYGzMu7yszEIBOm2rVmHUNqwAIQabISNMRstmdhNWcFLsSm+0tjJH1MdRxO5Nx0WDMhCtgD6OKgZeljJqJKc9po8juskR9XN0Y1lZ3mWjLR9JCO1jRDMd0fpYC2VnvjBSEFg7wBENc0R9HFlb0xvF1+TBEpF68d+DHR6IOWVv2BECtxo46hOFUBd/APU57WIoEwJhIi2CdpyZX0m93BZicktMj1AS9dClteUFAUNUIEygRZCtik5zSxI9MubTBH1GOiHsiLJ3OCoSZkILa9PxiN0EbvhsAo8tdAf9Seepd36lGWHmtNANTv5Jd0z4QYyeo/UEJqxKRpg5LZx6btLPsOaEmdMyxYdlc8LMaJnikDlhclqmPiQnTEpLUIZEwkRagjYkEibQErwhkTAKCLQEbUgkzJQWc/0PstHHcfEdQ+UAAAAASUVORK5CYII=');
15 | }
16 |
17 | }
18 |
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main.scss:
--------------------------------------------------------------------------------
1 | .svgImg {
2 | display:inline-block;
3 | bottom: -2px;/**to properly align img**/
4 | }
5 | button.btn_smallscreen {
6 | display: none;
7 | }
8 | button.btn_smallscreen div, button.btn_fullscreen div {
9 | width: 15px;
10 | height: 15px;
11 | }
12 | &.yasr_fullscreen {
13 | z-index: $zIndex-fullscreen;
14 |
15 |
16 | .btn_smallscreen {
17 | display: inline-block;
18 | }
19 | .btn_fullscreen {
20 | display: none;
21 | }
22 | position: fixed;
23 | overflow: auto;
24 | top: 0;
25 | bottom:0;
26 | left:0;
27 | right:0;
28 |
29 | }
30 | a {
31 | color: #428bca;
32 | text-decoration: none;
33 | &:hover,&:active {
34 | outline: 0;
35 | color: #2a6496;
36 | text-decoration: underline;
37 | }
38 | }
39 | th {
40 | text-align: left;
41 | }
42 |
43 | .yasr_header {
44 | * {
45 | /* use position relative and z-index, as this fixes issue where results div overflows the button (do this to align controls), and divs are not clickable anymore*/
46 | z-index: 5;
47 | position: relative;
48 | }
49 | & > * {
50 | margin-left: 6px;
51 | }
52 | }
53 | .yasr_btn {
54 | color: #333;
55 | border: 1px solid transparent;
56 | background-color: #fff;
57 | border-color: #ccc;
58 | border-width: 1px;
59 | display: inline-block;
60 | text-align: center;
61 | vertical-align: middle;
62 |
63 | cursor: pointer;
64 | white-space: nowrap;
65 | padding: 6px 12px;
66 | border-radius: 4px;
67 | -webkit-user-select: none;
68 | -moz-user-select: none;
69 | -ms-user-select: none;
70 | user-select: none;
71 | -webkit-appearance: button;
72 | /* margin: 0; */
73 | overflow: visible;
74 | box-sizing: border-box;
75 | &.btn_icon {
76 | padding: 4px 8px;
77 | }
78 | &[disabled], &.disabled {
79 | cursor: default;
80 | opacity: .50;
81 | filter: alpha(opacity=50);
82 | -webkit-box-shadow: none;
83 | box-shadow: none;
84 | }
85 | &:hover {
86 | outline:0;
87 | background-color: #ebebeb;
88 | border-color: #adadad;
89 | }
90 | &:focus, &.selected {
91 | color: #fff;
92 | outline:0;
93 | background-color: #337ab7;
94 | border-color: #337ab7;
95 | }
96 | &.btn_icon:focus {
97 | color: #333;
98 | border: 1px solid transparent;
99 | background-color: #fff;
100 | border-color: #ccc;
101 | }
102 | }
103 | .yasr_downloadIcon.yasr_btn.btn_icon {
104 | div {
105 | height: 14px;
106 | width: 15px;
107 | }
108 | padding-top: 6px;
109 | padding-bottom: 6px;
110 |
111 | }
112 | .yasr_embedBtn.yasr_btn {
113 | font-family: Consolas,monospace;
114 | padding-left: 4px;
115 | padding-right: 4px;
116 | }
117 |
118 | .yasr_embedPopup {
119 | position:absolute;
120 | padding: 6px;
121 | background-color: #f5f5f5;
122 | border: 1px solid #e3e3e3;
123 | border-radius: 4px;
124 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
125 | box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
126 | width: 700px;
127 | height: 300px;
128 | font-family: Consolas,monospace;
129 | textarea {
130 | width: 100%;
131 | height: 100%;
132 | border:0;
133 | }
134 | }
135 | .yasr_btnGroup {
136 | display: inline-block;
137 | vertical-align: middle;
138 | &>button:first-child:not(:last-child) {
139 | border-bottom-right-radius: 0;
140 | border-top-right-radius: 0;
141 | }
142 | &>button:last-child:not(:first-child) {
143 | border-bottom-left-radius: 0;
144 | border-top-left-radius: 0;
145 | }
146 | &>button:not(:first-child):not(:last-child) {
147 | border-radius: 0;
148 | }
149 | button+button {
150 | margin-left: -1px;
151 | }
152 | }
153 |
154 |
155 | .toggableWarning{
156 | color: #8a6d3b;
157 | background-color: #fcf8e3;
158 | border-color: #faebcc;
159 | padding: 15px 35px 15px 15px;
160 | border: 1px solid transparent;
161 | border-radius: 4px;
162 |
163 | .toggableMsg {
164 | }
165 | .toggleWarning {
166 | float: right;
167 | font-size: 21px;
168 | cursor: pointer;
169 | font-weight: 700;
170 | line-height: 1;
171 | color: #000;
172 | text-shadow: 0 1px 0 #fff;
173 | opacity: .2;
174 | position: relative;
175 | top: -2px;
176 | right: -21px;
177 | color: inherit;
178 | &:hover {
179 | color: #000;
180 | cursor: pointer;
181 | filter: alpha(opacity=50);
182 | opacity: .5;
183 | }
184 | }
185 |
186 | }
187 |
--------------------------------------------------------------------------------
/src/parsers/csv.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 | var root = module.exports = function(queryResponse) {
4 | return require("./dlv.js")(queryResponse, ",");
5 | };
6 |
--------------------------------------------------------------------------------
/src/parsers/dlv.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 | require("../../lib/jquery.csv-0.71.js");
4 | var root = (module.exports = function(queryResponse, separator, opts) {
5 | opts = opts || {};
6 |
7 | var json = {};
8 | var arrays = $.csv.toArrays(queryResponse, {
9 | separator: separator
10 | });
11 | var detectType = function(value) {
12 | if (value.indexOf("http") == 0) {
13 | return "uri";
14 | } else {
15 | return null;
16 | }
17 | };
18 |
19 | var getBoolean = function() {
20 | if (
21 | arrays.length == 2 &&
22 | arrays[0].length == 1 &&
23 | arrays[1].length == 1 &&
24 | arrays[0][0] == "boolean" &&
25 | (arrays[1][0] == "1" || arrays[1][0] == "0")
26 | ) {
27 | json.boolean = arrays[1][0] == "1" ? true : false;
28 | return true;
29 | }
30 | return false;
31 | };
32 |
33 | var getVariables = function() {
34 | if (arrays.length > 0 && arrays[0].length > 0) {
35 | json.head = {
36 | vars: arrays[0].map(function(v) {
37 | if (opts.mapVariable) return opts.mapVariable(v);
38 | return v;
39 | })
40 | };
41 | return true;
42 | }
43 | return false;
44 | };
45 |
46 | var getBindings = function() {
47 | if (arrays.length > 1) {
48 | json.results = {
49 | bindings: []
50 | };
51 | for (var rowIt = 1; rowIt < arrays.length; rowIt++) {
52 | var binding = {};
53 | for (var colIt = 0; colIt < arrays[rowIt].length; colIt++) {
54 | var varName = json.head.vars[colIt];
55 | if (varName) {
56 | var value = opts.mapValue ? opts.mapValue(arrays[rowIt][colIt]) : arrays[rowIt][colIt];
57 | var detectedType = detectType(value);
58 | binding[varName] = {
59 | value: value
60 | };
61 | if (detectedType) binding[varName].type = detectedType;
62 | }
63 | }
64 |
65 | json.results.bindings.push(binding);
66 | }
67 | return true;
68 | }
69 | return false;
70 | };
71 | var isBoolean = getBoolean();
72 | if (!isBoolean) {
73 | var varsFetched = getVariables();
74 | if (varsFetched) getBindings();
75 | }
76 |
77 | return json;
78 | });
79 |
--------------------------------------------------------------------------------
/src/parsers/graphJson.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 | var map = require("lodash/map");
4 | var reduce = require("lodash/reduce");
5 |
6 | var getAsObject = function(entity) {
7 | if (typeof entity == "object") {
8 | if ("bnode" == entity.type) {
9 | entity.value = entity.value.slice(2);
10 | }
11 | return entity;
12 | }
13 | if (entity.indexOf("_:") == 0) {
14 | return {
15 | type: "bnode",
16 | value: entity.slice(2)
17 | };
18 | }
19 | return {
20 | type: "uri",
21 | value: entity
22 | };
23 | };
24 | var root = module.exports = function(responseJson) {
25 | if (responseJson) {
26 | var hasContext = false;
27 | var mapped = map(responseJson, function(value, subject) {
28 | return map(value, function(value1, predicate) {
29 | return map(value1, function(object) {
30 | if (object.graphs) {
31 | hasContext = true;
32 | return map(object.graphs, function(context) {
33 | return [getAsObject(subject), getAsObject(predicate), getAsObject(object), getAsObject(context)];
34 | });
35 | } else {
36 | return [getAsObject(subject), getAsObject(predicate), getAsObject(object)];
37 | }
38 | });
39 | });
40 | });
41 | var reduced = reduce(
42 | mapped,
43 | function(memo, el) {
44 | return memo.concat(el);
45 | },
46 | []
47 | );
48 | reduced = reduce(
49 | reduced,
50 | function(memo, el) {
51 | return memo.concat(el);
52 | },
53 | []
54 | );
55 | var bindings;
56 | if (!hasContext) {
57 | bindings = reduced.map(function(triple) {
58 | return { subject: triple[0], predicate: triple[1], object: triple[2] };
59 | });
60 | } else {
61 | reduced = reduce(
62 | reduced,
63 | function(memo, el) {
64 | return memo.concat(el);
65 | },
66 | []
67 | );
68 | bindings = reduced.map(function(triple) {
69 | return { subject: triple[0], predicate: triple[1], object: triple[2], context: triple[3] };
70 | });
71 | }
72 | var variables = hasContext ? ["subject", "predicate", "object", "context"] : ["subject", "predicate", "object"];
73 | return {
74 | head: {
75 | vars: variables
76 | },
77 | results: {
78 | bindings: bindings
79 | }
80 | };
81 | }
82 | return false;
83 | };
84 |
--------------------------------------------------------------------------------
/src/parsers/json.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 | var root = module.exports = function(queryResponse) {
4 | if (typeof queryResponse == "string") {
5 | try {
6 | return JSON.parse(queryResponse);
7 | } catch (e) {
8 | return false;
9 | }
10 | }
11 | if (typeof queryResponse == "object" && queryResponse.constructor === ({}).constructor) {
12 | return queryResponse;
13 | }
14 | return false;
15 | };
16 |
--------------------------------------------------------------------------------
/src/parsers/tsv.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 | var root = (module.exports = function(queryResponse) {
4 | return require("./dlv.js")(queryResponse, "\t", {
5 | mapVariable: function(variable) {
6 | if (variable[0] === "?") return variable.substring(1);
7 | return variable;
8 | },
9 | mapValue: function(val) {
10 | if (val[0] === "<" && val[val.length - 1] === ">") return val.substring(1, val.length - 1);
11 | return val;
12 | }
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/parsers/wrapper.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 |
4 | /**
5 | * arg1 can be:
6 | * - a string (an exception, or e.g. a csv result string)
7 | * - an object (e.g. xml or json object)
8 | * - an object with exception key (contains solely a string to display)
9 | * - a jqXHR object (when this function is used as 'fail' callback for jquery)
10 | * arg2 can be:
11 | * - the textstatus of the response
12 | * arg3 can be:
13 | * - a jqXHR object (when this function is used as 'done/success' callback for jquery)
14 | * - an 'errorThrown' string (
15 | */
16 | var root = (module.exports = function(dataOrJqXhr, textStatus, jqXhrOrErrorString) {
17 | var parsers = {
18 | xml: require("./xml.js"),
19 | json: require("./json.js"),
20 | tsv: require("./tsv.js"),
21 | csv: require("./csv.js"),
22 | graphJson: require("./graphJson.js")
23 | };
24 | var contentType = null;
25 | var origResponse = null;
26 | var json = null;
27 | var type = null; //json, xml, csv, or tsv
28 | var exception = null;
29 |
30 | var init = function() {
31 | if (typeof dataOrJqXhr == "object") {
32 | /**
33 | * Extract exception info (if there is any)
34 | */
35 | if (dataOrJqXhr.exception) {
36 | //this object just has this exception string, nothing more. (here for backwards compatability)
37 | exception = dataOrJqXhr.exception;
38 | } else if (dataOrJqXhr.status != undefined && (dataOrJqXhr.status >= 300 || dataOrJqXhr.status === 0)) {
39 | //this is an exception, and jquery response
40 | exception = {
41 | status: dataOrJqXhr.status
42 | };
43 | if (typeof jqXhrOrErrorString == "string") exception.errorString = jqXhrOrErrorString;
44 | if (dataOrJqXhr.responseText) exception.responseText = dataOrJqXhr.responseText;
45 | if (dataOrJqXhr.statusText) exception.statusText = dataOrJqXhr.statusText;
46 | }
47 |
48 | /**
49 | * Extract content type info (if there is any)
50 | */
51 | if (dataOrJqXhr.contentType) {
52 | //this is not a jqXhr object, but a manually generated object (mostly for backwards compatability)
53 | contentType = dataOrJqXhr.contentType.toLowerCase();
54 | } else if (dataOrJqXhr.getResponseHeader && dataOrJqXhr.getResponseHeader("content-type")) {
55 | var ct = dataOrJqXhr.getResponseHeader("content-type").trim().toLowerCase();
56 | if (ct.length > 0) contentType = ct;
57 | }
58 |
59 | /**
60 | * extract original response
61 | */
62 | if (dataOrJqXhr.response) {
63 | //this is not a jqXhr object, but a manually generated object (mostly for backwards compatability)
64 | origResponse = dataOrJqXhr.response;
65 | } else if (!textStatus && !jqXhrOrErrorString) {
66 | //not called from jquery, as these other arguments are undefined.
67 | //so, we can only assume the current object is a proper response (e.g. xml or json) object
68 | origResponse = dataOrJqXhr;
69 | }
70 | }
71 | if (!exception && !origResponse) {
72 | //if this is called via a jquery complete callback, we should fetch the result for the jqXHR object
73 | if (dataOrJqXhr.responseText) {
74 | origResponse = dataOrJqXhr.responseText;
75 | } else {
76 | //if all else fails, assume first arg to be data object
77 | //(which should be the case for most situations)
78 | origResponse = dataOrJqXhr;
79 | }
80 | }
81 | };
82 |
83 | var getAsJson = function() {
84 | if (json) return json;
85 | if (json === false || exception) return false; //already tried parsing this, and failed. do not try again...
86 | var getParserFromContentType = function() {
87 | if (contentType) {
88 | if (contentType.indexOf("json") > -1) {
89 | try {
90 | if (contentType.indexOf("sparql-results+json") > -1) {
91 | json = parsers.json(origResponse);
92 | } else if (contentType.indexOf("application/rdf+json") > -1) {
93 | json = parsers.graphJson(parsers.json(origResponse));
94 | }
95 | } catch (e) {
96 | exception = e;
97 | }
98 | type = "json";
99 | } else if (contentType.indexOf("xml") > -1) {
100 | try {
101 | json = parsers.xml(origResponse);
102 | } catch (e) {
103 | exception = e;
104 | }
105 | type = "xml";
106 | } else if (contentType.indexOf("csv") > -1) {
107 | try {
108 | json = parsers.csv(origResponse);
109 | } catch (e) {
110 | exception = e;
111 | }
112 | type = "csv";
113 | } else if (contentType.indexOf("tab-separated") > -1) {
114 | try {
115 | json = parsers.tsv(origResponse);
116 | } catch (e) {
117 | exception = e;
118 | }
119 | type = "tsv";
120 | }
121 | }
122 | };
123 |
124 | var doLuckyGuess = function() {
125 | json = parsers.json(origResponse);
126 | if (json) {
127 | type = "json";
128 | } else {
129 | try {
130 | json = parsers.xml(origResponse);
131 | if (json) type = "xml";
132 | } catch (err) {}
133 | }
134 | };
135 |
136 | getParserFromContentType();
137 | if (!json) {
138 | doLuckyGuess();
139 | }
140 | if (!json) json = false; //explicitly set to false, so we don't try to parse this thing again..
141 | return json;
142 | };
143 |
144 | var getVariables = function() {
145 | var json = getAsJson();
146 | if (json && "head" in json) {
147 | return json.head.vars;
148 | } else {
149 | return null;
150 | }
151 | };
152 |
153 | var getBindings = function() {
154 | var json = getAsJson();
155 | if (json && "results" in json) {
156 | return json.results.bindings;
157 | } else {
158 | return null;
159 | }
160 | };
161 |
162 | var getBoolean = function() {
163 | var json = getAsJson();
164 | if (json && "boolean" in json) {
165 | return json.boolean;
166 | } else {
167 | return null;
168 | }
169 | };
170 | var getOriginalResponse = function() {
171 | return origResponse;
172 | };
173 | var getOriginalResponseAsString = function() {
174 | var responseString = "";
175 | if (typeof origResponse == "string") {
176 | responseString = origResponse;
177 | } else if (type == "json") {
178 | responseString = JSON.stringify(origResponse, undefined, 2); //prettifies as well
179 | } else if (type == "xml") {
180 | responseString = new XMLSerializer().serializeToString(origResponse);
181 | }
182 | return responseString;
183 | };
184 | var getException = function() {
185 | return exception;
186 | };
187 | var getType = function() {
188 | if (type == null) getAsJson(); //detects type as well
189 | return type;
190 | };
191 |
192 | //process the input parameters in such a way that we can store it in local storage (i.e., no function)
193 | //and, make sure we can easily pass it on back to this wrapper function when loading it again from storage
194 | var getAsStoreObject = function() {
195 | var storeArray = [];
196 | var arg1 = {};
197 | if (dataOrJqXhr.status) {
198 | //jqXhr object
199 | arg1.status = dataOrJqXhr.status;
200 | arg1.responseText = dataOrJqXhr.responseText;
201 | arg1.statusText = dataOrJqXhr.statusText;
202 | arg1.contentType = contentType; //this is a function in a jqXhr object (problem for storing). but this wrapper will read it as string as well
203 | } else {
204 | //the other instances of this param (whether it is a json, xml, or exception object), we can normally store
205 | arg1 = dataOrJqXhr;
206 | }
207 |
208 | var arg2 = textStatus;
209 | var arg3 = undefined;
210 | if (typeof jqXhrOrErrorString == "string") arg3 = jqXhrOrErrorString;
211 |
212 | return [arg1, arg2, arg3];
213 | };
214 |
215 | init();
216 | json = getAsJson();
217 |
218 | return {
219 | getAsStoreObject: getAsStoreObject,
220 | getAsJson: getAsJson,
221 | getOriginalResponse: getOriginalResponse,
222 | getOriginalResponseAsString: getOriginalResponseAsString,
223 | getOriginalContentType: function() {
224 | return contentType;
225 | },
226 | getVariables: getVariables,
227 | getBindings: getBindings,
228 | getBoolean: getBoolean,
229 | getType: getType,
230 | getException: getException
231 | };
232 | });
233 |
--------------------------------------------------------------------------------
/src/parsers/xml.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery");
3 | var root = module.exports = function(xml) {
4 | /**
5 | * head
6 | */
7 | var parseHead = function(node) {
8 | json.head = {};
9 | for (var headNodeIt = 0; headNodeIt < node.childNodes.length; headNodeIt++) {
10 | var headNode = node.childNodes[headNodeIt];
11 | if (headNode.nodeName == "variable") {
12 | if (!json.head.vars) json.head.vars = [];
13 | var name = headNode.getAttribute("name");
14 | if (name) json.head.vars.push(name);
15 | }
16 | }
17 | };
18 |
19 | var parseResults = function(node) {
20 | json.results = {};
21 | json.results.bindings = [];
22 | for (var resultIt = 0; resultIt < node.childNodes.length; resultIt++) {
23 | var resultNode = node.childNodes[resultIt];
24 | var jsonResult = null;
25 |
26 | for (var bindingIt = 0; bindingIt < resultNode.childNodes.length; bindingIt++) {
27 | var bindingNode = resultNode.childNodes[bindingIt];
28 | if (bindingNode.nodeName == "binding") {
29 | var varName = bindingNode.getAttribute("name");
30 | if (varName) {
31 | jsonResult = jsonResult || {};
32 | jsonResult[varName] = {};
33 | for (var bindingInfIt = 0; bindingInfIt < bindingNode.childNodes.length; bindingInfIt++) {
34 | var bindingInf = bindingNode.childNodes[bindingInfIt];
35 | var type = bindingInf.nodeName;
36 | if (type == "#text") continue;
37 | jsonResult[varName].type = type;
38 | jsonResult[varName].value = bindingInf.innerHTML;
39 | var dataType = bindingInf.getAttribute("datatype");
40 | if (dataType) jsonResult[varName].datatype = dataType;
41 | }
42 | }
43 | }
44 | }
45 | if (jsonResult) json.results.bindings.push(jsonResult);
46 | }
47 | };
48 |
49 | var parseBoolean = function(node) {
50 | if (node.innerHTML == "true") {
51 | json.boolean = true;
52 | } else {
53 | json.boolean = false;
54 | }
55 | };
56 | var mainXml = null;
57 | if (typeof xml == "string") {
58 | mainXml = $.parseXML(xml);
59 | } else if ($.isXMLDoc(xml)) {
60 | mainXml = xml;
61 | }
62 | var xml = null;
63 | if (mainXml.childNodes.length > 0) {
64 | //enter the main 'sparql' node
65 | xml = mainXml.childNodes[0];
66 | } else {
67 | return null;
68 | }
69 | var json = {};
70 |
71 | for (var i = 0; i < xml.childNodes.length; i++) {
72 | var node = xml.childNodes[i];
73 | if (node.nodeName == "head") parseHead(node);
74 | if (node.nodeName == "results") parseResults(node);
75 | if (node.nodeName == "boolean") parseBoolean(node);
76 | }
77 |
78 | return json;
79 | };
80 |
--------------------------------------------------------------------------------
/src/pivot.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery"), utils = require("./utils.js"), yUtils = require("yasgui-utils"), imgs = require("./imgs.js");
3 | require("jquery-ui/sortable");
4 | require("pivottable");
5 |
6 | if (!$.fn.pivotUI) throw new Error("Pivot lib not loaded");
7 | var root = module.exports = function(yasr) {
8 | var plugin = {};
9 | var options = $.extend(true, {}, root.defaults);
10 |
11 | if (options.useD3Chart) {
12 | try {
13 | var d3 = require("d3");
14 | if (d3) require("pivottable/dist/d3_renderers.js");
15 | } catch (e) {
16 | //do nothing. just make sure we don't use this renderer
17 | }
18 | if ($.pivotUtilities.d3_renderers) $.extend(true, $.pivotUtilities.renderers, $.pivotUtilities.d3_renderers);
19 | }
20 |
21 | var $pivotWrapper;
22 | var mergeLabelPostfix = null;
23 | var getShownVariables = function() {
24 | var variables = yasr.results.getVariables();
25 | if (!options.mergeLabelsWithUris) return variables;
26 | var shownVariables = [];
27 |
28 | mergeLabelPostfix = typeof options.mergeLabelsWithUris == "string" ? options.mergeLabelsWithUris : "Label";
29 | variables.forEach(function(variable) {
30 | if (variable.indexOf(mergeLabelPostfix, variable.length - mergeLabelPostfix.length) !== -1) {
31 | //this one ends with a postfix
32 | if (variables.indexOf(variable.substring(0, variable.length - mergeLabelPostfix.length)) >= 0) {
33 | //we have a shorter version of this variable. So, do not include the ..
variable in the table
34 | return;
35 | }
36 | }
37 | shownVariables.push(variable);
38 | });
39 | return shownVariables;
40 | };
41 |
42 | var formatForPivot = function(callback) {
43 | var vars = getShownVariables();
44 | var usedPrefixes = null;
45 | if (yasr.options.getUsedPrefixes) {
46 | usedPrefixes = typeof yasr.options.getUsedPrefixes == "function"
47 | ? yasr.options.getUsedPrefixes(yasr)
48 | : yasr.options.getUsedPrefixes;
49 | }
50 | yasr.results.getBindings().forEach(function(binding) {
51 | var rowObj = {};
52 | vars.forEach(function(variable) {
53 | if (variable in binding) {
54 | var val = binding[variable].value;
55 | if (mergeLabelPostfix && binding[variable + mergeLabelPostfix]) {
56 | val = binding[variable + mergeLabelPostfix].value;
57 | } else if (binding[variable].type == "uri") {
58 | val = utils.uriToPrefixed(usedPrefixes, val);
59 | }
60 | rowObj[variable] = val;
61 | } else {
62 | rowObj[variable] = null;
63 | }
64 | });
65 | callback(rowObj);
66 | });
67 | };
68 |
69 | var validatePivotTableOptions = function(pivotOptions) {
70 | //validate settings. we may have different variables, or renderers might be gone
71 | if (pivotOptions) {
72 | if (yasr.results) {
73 | var vars = yasr.results.getVariables();
74 | var keepColsAndRows = true;
75 | pivotOptions.cols.forEach(function(variable) {
76 | if (vars.indexOf(variable) < 0) keepColsAndRows = false;
77 | });
78 | if (keepColsAndRows) {
79 | pivotOptionse.rows.forEach(function(variable) {
80 | if (vars.indexOf(variable) < 0) keepColsAndRows = false;
81 | });
82 | }
83 | if (!keepColsAndRows) {
84 | pivotOptions.cols = [];
85 | pivotOptions.rows = [];
86 | }
87 | if (!$.pivotUtilities.renderers[settings.rendererName]) delete pivotOptions.rendererName;
88 | }
89 | } else {
90 | pivotOptions = {};
91 | }
92 | return pivotOptions;
93 | };
94 | var draw = function() {
95 | var doDraw = function() {
96 | var onRefresh = function(pivotObj) {
97 | options.pivotTable.cols = pivotObj.cols;
98 | options.pivotTable.rows = pivotObj.rows;
99 | options.pivotTable.rendererName = pivotObj.rendererName;
100 | options.pivotTable.aggregatorName = pivotObj.aggregatorName;
101 | options.pivotTable.vals = pivotObj.vals;
102 | yasr.store();
103 |
104 | if (pivotObj.rendererName.toLowerCase().indexOf(" chart") >= 0) {
105 | openGchartBtn.show();
106 | } else {
107 | openGchartBtn.hide();
108 | }
109 | yasr.updateHeader();
110 | };
111 |
112 | var openGchartBtn = $("", {
113 | class: "openPivotGchart yasr_btn"
114 | })
115 | .text("Chart Config")
116 | .click(function() {
117 | $pivotWrapper.find('div[dir="ltr"]').dblclick();
118 | })
119 | .appendTo(yasr.resultsContainer);
120 | $pivotWrapper = $("", {
121 | class: "pivotTable"
122 | }).appendTo($(yasr.resultsContainer));
123 |
124 | options.pivotTable.onRefresh = (function() {
125 | var originalRefresh = options.pivotTable.onRefresh;
126 | return function(pivotObj) {
127 | onRefresh(pivotObj);
128 | if (originalRefresh) originalRefresh(pivotObj);
129 | };
130 | })();
131 |
132 | window.pivot = $pivotWrapper.pivotUI(formatForPivot, options.pivotTable);
133 |
134 | /**
135 | * post process
136 | */
137 | //use 'move' handler for variables. This removes the 'filter' button though. Might want to re-enable this in the future
138 | var icon = $(yUtils.svg.getElement(imgs.move));
139 | $pivotWrapper.find(".pvtTriangle").replaceWith(icon);
140 |
141 | //add headers to selector rows
142 | $(".pvtCols").prepend(
143 | $("
", {
144 | class: "containerHeader"
145 | }).text("Columns")
146 | );
147 | $(".pvtRows").prepend(
148 | $("
", {
149 | class: "containerHeader"
150 | }).text("Rows")
151 | );
152 | $(".pvtUnused").prepend(
153 | $("
", {
154 | class: "containerHeader"
155 | }).text("Available Variables")
156 | );
157 | $(".pvtVals").prepend(
158 | $("
", {
159 | class: "containerHeader"
160 | }).text("Cells")
161 | );
162 |
163 | //hmmm, directly after the callback finishes (i.e., directly after this line), the svg is draw.
164 | //just use a short timeout to update the header
165 | setTimeout(yasr.updateHeader, 400);
166 | };
167 |
168 | if (yasr.options.useGoogleCharts && options.useGoogleCharts && !$.pivotUtilities.gchart_renderers) {
169 | require("./gChartLoader.js")
170 | .on("done", function() {
171 | try {
172 | require("pivottable/dist/gchart_renderers.js");
173 | $.extend(true, $.pivotUtilities.renderers, $.pivotUtilities.gchart_renderers);
174 | } catch (e) {
175 | //hmm, still something went wrong. forget about it;
176 | options.useGoogleCharts = false;
177 | }
178 | doDraw();
179 | })
180 | .on("error", function() {
181 | console.log("could not load gchart");
182 | options.useGoogleCharts = false;
183 | doDraw();
184 | })
185 | .googleLoad();
186 | } else {
187 | //everything is already loaded. just draw
188 | doDraw();
189 | }
190 | };
191 | var canHandleResults = function() {
192 | return yasr.results &&
193 | yasr.results.getVariables &&
194 | yasr.results.getVariables() &&
195 | yasr.results.getVariables().length > 0;
196 | };
197 |
198 | var getDownloadInfo = function() {
199 | if (!yasr.results) return null;
200 | var svgEl = yasr.resultsContainer.find(".pvtRendererArea svg");
201 | if (svgEl.length > 0) {
202 | return {
203 | getContent: function() {
204 | if (svgEl[0].outerHTML) {
205 | return svgEl[0].outerHTML;
206 | } else {
207 | //outerHTML not supported. use workaround
208 | return $("
").append(svgEl.clone()).html();
209 | }
210 | },
211 |
212 | filename: "queryResults.svg",
213 | contentType: "image/svg+xml",
214 | buttonTitle: "Download SVG Image"
215 | };
216 | }
217 |
218 | //ok, not a svg. is it a table?
219 | var $table = yasr.resultsContainer.find(".pvtRendererArea table");
220 | if ($table.length > 0) {
221 | return {
222 | getContent: function() {
223 | return $table.tableToCsv();
224 | },
225 | filename: "queryResults.csv",
226 | contentType: "text/csv",
227 | buttonTitle: "Download as CSV"
228 | };
229 | }
230 | };
231 | var getEmbedHtml = function() {
232 | if (!yasr.results) return null;
233 |
234 | var svgEl = yasr.resultsContainer
235 | .find(".pvtRendererArea svg")
236 | .clone() //create clone, as we'd like to remove height/width attributes
237 | .removeAttr("height")
238 | .removeAttr("width")
239 | .css("height", "")
240 | .css("width", "");
241 | if (svgEl.length == 0) return null;
242 |
243 | var htmlString = svgEl[0].outerHTML;
244 | if (!htmlString) {
245 | //outerHTML not supported. use workaround
246 | htmlString = $("
").append(svgEl.clone()).html();
247 | }
248 | //wrap in div, so users can more easily tune width/height
249 | //don't use jquery, so we can easily influence indentation
250 | return '
\n' + htmlString + "\n
";
251 | };
252 | return {
253 | getPersistentSettings: function() {
254 | return {
255 | pivotTable: options.pivotTable
256 | };
257 | },
258 | setPersistentSettings: function(newSettings) {
259 | if (newSettings.pivotTable) {
260 | options.pivotTable = validatePivotTableOptions(newSettings.pivotTable);
261 | }
262 | },
263 | getDownloadInfo: getDownloadInfo,
264 | getEmbedHtml: getEmbedHtml,
265 | options: options,
266 | draw: draw,
267 | name: "Pivot Table",
268 | canHandleResults: canHandleResults,
269 | getPriority: 4
270 | };
271 | };
272 |
273 | root.defaults = {
274 | mergeLabelsWithUris: false,
275 | useGoogleCharts: true,
276 | useD3Chart: true,
277 | persistencyId: "pivot",
278 | pivotTable: {}
279 | };
280 |
281 | root.version = {
282 | "YASR-rawResponse": require("../package.json").version,
283 | jquery: $.fn.jquery
284 | };
285 |
--------------------------------------------------------------------------------
/src/pivot.scss:
--------------------------------------------------------------------------------
1 | .pivotTable {
2 | & > table {
3 | background-color: white;
4 | }
5 | margin-top: 5px;
6 | td.pvtAxisContainer, td.pvtVals {
7 | /**where vars are dragged to/from**/
8 | border: 1px solid $nav-tabs-border-color;
9 | background-color: transparent;
10 | }
11 | li span.pvtAttr {
12 | background-color: #337ab7;
13 | color: #fff;
14 | padding: 4px 7px;
15 |
16 | svg {
17 | fill: #fff;
18 | }
19 | div {
20 | /**svg container**/
21 | margin-left: 6px;
22 | vertical-align:middle;
23 | }
24 | }
25 | .pvtCols {
26 | vertical-align: top;
27 | }
28 | table.pvtTable tr th {
29 | background-color: #f2f2f2;
30 | &.pvtAxisLabel {
31 | background-color: #337ab7;
32 | color: #fff;
33 | }
34 | }
35 | .containerHeader {
36 | margin-left: 8px;
37 | margin-bottom: 8px;
38 | font-style: italic;
39 | font-size: 110%;
40 | color: #999;
41 | text-align:left;
42 | }
43 | .pvtAttr {
44 | .svgImg {
45 | width: 14px;
46 | height:14px;
47 | }
48 | }
49 | .node {
50 | border: solid 1px white;
51 | font: 10px sans-serif;
52 | line-height: 12px;
53 | overflow: hidden;
54 | position: absolute;
55 | text-indent: 2px;
56 | }
57 |
58 | }
59 | .openPivotGchart{
60 | float:right;
61 | position:relative;
62 | display:none;
63 | top:-38px;
64 | margin-bottom:-38px;
65 | }
66 |
--------------------------------------------------------------------------------
/src/rawResponse.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery"), CodeMirror = require("codemirror");
3 |
4 | require("codemirror/addon/fold/foldcode.js");
5 | require("codemirror/addon/fold/foldgutter.js");
6 | require("codemirror/addon/fold/xml-fold.js");
7 | require("codemirror/addon/fold/brace-fold.js");
8 |
9 | require("codemirror/addon/edit/matchbrackets.js");
10 | require("codemirror/mode/xml/xml.js");
11 | require("codemirror/mode/javascript/javascript.js");
12 |
13 | var root = module.exports = function(yasr) {
14 | var plugin = {};
15 | var options = $.extend(true, {}, root.defaults);
16 | var cm = null;
17 | var draw = function() {
18 | var cmOptions = options.CodeMirror;
19 | cmOptions.value = yasr.results.getOriginalResponseAsString();
20 |
21 | var mode = yasr.results.getType();
22 | if (mode) {
23 | if (mode == "json") {
24 | mode = {
25 | name: "javascript",
26 | json: true
27 | };
28 | }
29 | cmOptions.mode = mode;
30 | }
31 |
32 | cm = CodeMirror(yasr.resultsContainer.get()[0], cmOptions);
33 |
34 | //CM has some issues with folding and unfolding (blank parts in the codemirror area, which are only filled after clicking it)
35 | //so, refresh cm after folding/unfolding
36 | cm.on("fold", function() {
37 | cm.refresh();
38 | });
39 | cm.on("unfold", function() {
40 | cm.refresh();
41 | });
42 | };
43 | var canHandleResults = function() {
44 | if (!yasr.results) return false;
45 | if (!yasr.results.getOriginalResponseAsString) return false;
46 | var response = yasr.results.getOriginalResponseAsString();
47 | if ((!response || response.length == 0) && yasr.results.getException()) return false; //in this case, show exception instead, as we have nothing to show anyway
48 | return true;
49 | };
50 |
51 | var getDownloadInfo = function() {
52 | if (!yasr.results) return null;
53 | var contentType = yasr.results.getOriginalContentType();
54 | var type = yasr.results.getType();
55 | return {
56 | getContent: function() {
57 | return yasr.results.getOriginalResponse();
58 | },
59 | filename: "queryResults" + (type ? "." + type : ""),
60 | contentType: contentType ? contentType : "text/plain",
61 | buttonTitle: "Download response"
62 | };
63 | };
64 |
65 | return {
66 | draw: draw,
67 | name: "Response",
68 | canHandleResults: canHandleResults,
69 | getPriority: 2,
70 | getDownloadInfo: getDownloadInfo
71 | };
72 | };
73 |
74 | root.defaults = {
75 | CodeMirror: {
76 | readOnly: true,
77 | lineNumbers: true,
78 | lineWrapping: true,
79 | foldGutter: true,
80 | gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
81 | }
82 | };
83 |
84 | root.version = {
85 | "YASR-rawResponse": require("../package.json").version,
86 | jquery: $.fn.jquery,
87 | CodeMirror: CodeMirror.version
88 | };
89 |
--------------------------------------------------------------------------------
/src/rawResponse.scss:
--------------------------------------------------------------------------------
1 |
2 | .yasr_results {
3 | .CodeMirror {
4 | border: 1px solid #d1d1d1;
5 | margin-top: 5px;
6 | height: 100%;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/scss/cssIncludes/_codemirror.scss:
--------------------------------------------------------------------------------
1 | /* BASICS */
2 |
3 | .CodeMirror {
4 | /* Set height, width, borders, and global font properties here */
5 | font-family: monospace;
6 | height: 300px;
7 | color: black;
8 | }
9 |
10 | /* PADDING */
11 |
12 | .CodeMirror-lines {
13 | padding: 4px 0; /* Vertical padding around content */
14 | }
15 | .CodeMirror pre {
16 | padding: 0 4px; /* Horizontal padding of content */
17 | }
18 |
19 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
20 | background-color: white; /* The little square between H and V scrollbars */
21 | }
22 |
23 | /* GUTTER */
24 |
25 | .CodeMirror-gutters {
26 | border-right: 1px solid #ddd;
27 | background-color: #f7f7f7;
28 | white-space: nowrap;
29 | }
30 | .CodeMirror-linenumbers {}
31 | .CodeMirror-linenumber {
32 | padding: 0 3px 0 5px;
33 | min-width: 20px;
34 | text-align: right;
35 | color: #999;
36 | white-space: nowrap;
37 | }
38 |
39 | .CodeMirror-guttermarker { color: black; }
40 | .CodeMirror-guttermarker-subtle { color: #999; }
41 |
42 | /* CURSOR */
43 |
44 | .CodeMirror-cursor {
45 | border-left: 1px solid black;
46 | border-right: none;
47 | width: 0;
48 | }
49 | /* Shown when moving in bi-directional text */
50 | .CodeMirror div.CodeMirror-secondarycursor {
51 | border-left: 1px solid silver;
52 | }
53 | .cm-fat-cursor .CodeMirror-cursor {
54 | width: auto;
55 | border: 0 !important;
56 | background: #7e7;
57 | }
58 | .cm-fat-cursor div.CodeMirror-cursors {
59 | z-index: 1;
60 | }
61 |
62 | .cm-animate-fat-cursor {
63 | width: auto;
64 | border: 0;
65 | -webkit-animation: blink 1.06s steps(1) infinite;
66 | -moz-animation: blink 1.06s steps(1) infinite;
67 | animation: blink 1.06s steps(1) infinite;
68 | background-color: #7e7;
69 | }
70 | @-moz-keyframes blink {
71 | 0% {}
72 | 50% { background-color: transparent; }
73 | 100% {}
74 | }
75 | @-webkit-keyframes blink {
76 | 0% {}
77 | 50% { background-color: transparent; }
78 | 100% {}
79 | }
80 | @keyframes blink {
81 | 0% {}
82 | 50% { background-color: transparent; }
83 | 100% {}
84 | }
85 |
86 | /* Can style cursor different in overwrite (non-insert) mode */
87 | .CodeMirror-overwrite .CodeMirror-cursor {}
88 |
89 | .cm-tab { display: inline-block; text-decoration: inherit; }
90 |
91 | .CodeMirror-rulers {
92 | position: absolute;
93 | left: 0; right: 0; top: -50px; bottom: -20px;
94 | overflow: hidden;
95 | }
96 | .CodeMirror-ruler {
97 | border-left: 1px solid #ccc;
98 | top: 0; bottom: 0;
99 | position: absolute;
100 | }
101 |
102 | /* DEFAULT THEME */
103 |
104 | .cm-s-default .cm-header {color: blue;}
105 | .cm-s-default .cm-quote {color: #090;}
106 | .cm-negative {color: #d44;}
107 | .cm-positive {color: #292;}
108 | .cm-header, .cm-strong {font-weight: bold;}
109 | .cm-em {font-style: italic;}
110 | .cm-link {text-decoration: underline;}
111 | .cm-strikethrough {text-decoration: line-through;}
112 |
113 | .cm-s-default .cm-keyword {color: #708;}
114 | .cm-s-default .cm-atom {color: #219;}
115 | .cm-s-default .cm-number {color: #164;}
116 | .cm-s-default .cm-def {color: #00f;}
117 | .cm-s-default .cm-variable,
118 | .cm-s-default .cm-punctuation,
119 | .cm-s-default .cm-property,
120 | .cm-s-default .cm-operator {}
121 | .cm-s-default .cm-variable-2 {color: #05a;}
122 | .cm-s-default .cm-variable-3 {color: #085;}
123 | .cm-s-default .cm-comment {color: #a50;}
124 | .cm-s-default .cm-string {color: #a11;}
125 | .cm-s-default .cm-string-2 {color: #f50;}
126 | .cm-s-default .cm-meta {color: #555;}
127 | .cm-s-default .cm-qualifier {color: #555;}
128 | .cm-s-default .cm-builtin {color: #30a;}
129 | .cm-s-default .cm-bracket {color: #997;}
130 | .cm-s-default .cm-tag {color: #170;}
131 | .cm-s-default .cm-attribute {color: #00c;}
132 | .cm-s-default .cm-hr {color: #999;}
133 | .cm-s-default .cm-link {color: #00c;}
134 |
135 | .cm-s-default .cm-error {color: #f00;}
136 | .cm-invalidchar {color: #f00;}
137 |
138 | .CodeMirror-composing { border-bottom: 2px solid; }
139 |
140 | /* Default styles for common addons */
141 |
142 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
143 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
144 | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
145 | .CodeMirror-activeline-background {background: #e8f2ff;}
146 |
147 | /* STOP */
148 |
149 | /* The rest of this file contains styles related to the mechanics of
150 | the editor. You probably shouldn't touch them. */
151 |
152 | .CodeMirror {
153 | position: relative;
154 | overflow: hidden;
155 | background: white;
156 | }
157 |
158 | .CodeMirror-scroll {
159 | overflow: scroll !important; /* Things will break if this is overridden */
160 | /* 30px is the magic margin used to hide the element's real scrollbars */
161 | /* See overflow: hidden in .CodeMirror */
162 | margin-bottom: -30px; margin-right: -30px;
163 | padding-bottom: 30px;
164 | height: 100%;
165 | outline: none; /* Prevent dragging from highlighting the element */
166 | position: relative;
167 | }
168 | .CodeMirror-sizer {
169 | position: relative;
170 | border-right: 30px solid transparent;
171 | }
172 |
173 | /* The fake, visible scrollbars. Used to force redraw during scrolling
174 | before actual scrolling happens, thus preventing shaking and
175 | flickering artifacts. */
176 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
177 | position: absolute;
178 | z-index: 6;
179 | display: none;
180 | }
181 | .CodeMirror-vscrollbar {
182 | right: 0; top: 0;
183 | overflow-x: hidden;
184 | overflow-y: scroll;
185 | }
186 | .CodeMirror-hscrollbar {
187 | bottom: 0; left: 0;
188 | overflow-y: hidden;
189 | overflow-x: scroll;
190 | }
191 | .CodeMirror-scrollbar-filler {
192 | right: 0; bottom: 0;
193 | }
194 | .CodeMirror-gutter-filler {
195 | left: 0; bottom: 0;
196 | }
197 |
198 | .CodeMirror-gutters {
199 | position: absolute; left: 0; top: 0;
200 | min-height: 100%;
201 | z-index: 3;
202 | }
203 | .CodeMirror-gutter {
204 | white-space: normal;
205 | height: 100%;
206 | display: inline-block;
207 | vertical-align: top;
208 | margin-bottom: -30px;
209 | /* Hack to make IE7 behave */
210 | *zoom:1;
211 | *display:inline;
212 | }
213 | .CodeMirror-gutter-wrapper {
214 | position: absolute;
215 | z-index: 4;
216 | background: none !important;
217 | border: none !important;
218 | }
219 | .CodeMirror-gutter-background {
220 | position: absolute;
221 | top: 0; bottom: 0;
222 | z-index: 4;
223 | }
224 | .CodeMirror-gutter-elt {
225 | position: absolute;
226 | cursor: default;
227 | z-index: 4;
228 | }
229 | .CodeMirror-gutter-wrapper {
230 | -webkit-user-select: none;
231 | -moz-user-select: none;
232 | user-select: none;
233 | }
234 |
235 | .CodeMirror-lines {
236 | cursor: text;
237 | min-height: 1px; /* prevents collapsing before first draw */
238 | }
239 | .CodeMirror pre {
240 | /* Reset some styles that the rest of the page might have set */
241 | -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
242 | border-width: 0;
243 | background: transparent;
244 | font-family: inherit;
245 | font-size: inherit;
246 | margin: 0;
247 | white-space: pre;
248 | word-wrap: normal;
249 | line-height: inherit;
250 | color: inherit;
251 | z-index: 2;
252 | position: relative;
253 | overflow: visible;
254 | -webkit-tap-highlight-color: transparent;
255 | -webkit-font-variant-ligatures: none;
256 | font-variant-ligatures: none;
257 | }
258 | .CodeMirror-wrap pre {
259 | word-wrap: break-word;
260 | white-space: pre-wrap;
261 | word-break: normal;
262 | }
263 |
264 | .CodeMirror-linebackground {
265 | position: absolute;
266 | left: 0; right: 0; top: 0; bottom: 0;
267 | z-index: 0;
268 | }
269 |
270 | .CodeMirror-linewidget {
271 | position: relative;
272 | z-index: 2;
273 | overflow: auto;
274 | }
275 |
276 | .CodeMirror-widget {}
277 |
278 | .CodeMirror-code {
279 | outline: none;
280 | }
281 |
282 | /* Force content-box sizing for the elements where we expect it */
283 | .CodeMirror-scroll,
284 | .CodeMirror-sizer,
285 | .CodeMirror-gutter,
286 | .CodeMirror-gutters,
287 | .CodeMirror-linenumber {
288 | -moz-box-sizing: content-box;
289 | box-sizing: content-box;
290 | }
291 |
292 | .CodeMirror-measure {
293 | position: absolute;
294 | width: 100%;
295 | height: 0;
296 | overflow: hidden;
297 | visibility: hidden;
298 | }
299 |
300 | .CodeMirror-cursor {
301 | position: absolute;
302 | pointer-events: none;
303 | }
304 | .CodeMirror-measure pre { position: static; }
305 |
306 | div.CodeMirror-cursors {
307 | visibility: hidden;
308 | position: relative;
309 | z-index: 3;
310 | }
311 | div.CodeMirror-dragcursors {
312 | visibility: visible;
313 | }
314 |
315 | .CodeMirror-focused div.CodeMirror-cursors {
316 | visibility: visible;
317 | }
318 |
319 | .CodeMirror-selected { background: #d9d9d9; }
320 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
321 | .CodeMirror-crosshair { cursor: crosshair; }
322 | .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
323 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
324 |
325 | .cm-searching {
326 | background: #ffa;
327 | background: rgba(255, 255, 0, .4);
328 | }
329 |
330 | /* IE7 hack to prevent it from returning funny offsetTops on the spans */
331 | .CodeMirror span { *vertical-align: text-bottom; }
332 |
333 | /* Used to force a border model for a node */
334 | .cm-force-border { padding-right: .1px; }
335 |
336 | @media print {
337 | /* Hide the cursor when printing */
338 | .CodeMirror div.CodeMirror-cursors {
339 | visibility: hidden;
340 | }
341 | }
342 |
343 | /* See issue #2901 */
344 | .cm-tab-wrap-hack:after { content: ''; }
345 |
346 | /* Help users use markselection to safely style text background */
347 | span.CodeMirror-selectedtext { background: none; }
348 |
--------------------------------------------------------------------------------
/src/scss/cssIncludes/_foldgutter.scss:
--------------------------------------------------------------------------------
1 | .CodeMirror-foldmarker {
2 | color: blue;
3 | text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
4 | font-family: arial;
5 | line-height: .3;
6 | cursor: pointer;
7 | }
8 | .CodeMirror-foldgutter {
9 | width: .7em;
10 | }
11 | .CodeMirror-foldgutter-open,
12 | .CodeMirror-foldgutter-folded {
13 | cursor: pointer;
14 | }
15 | .CodeMirror-foldgutter-open:after {
16 | content: "\25BE";
17 | }
18 | .CodeMirror-foldgutter-folded:after {
19 | content: "\25B8";
20 | }
21 |
--------------------------------------------------------------------------------
/src/scss/cssIncludes/_leaflet.scss:
--------------------------------------------------------------------------------
1 | /* required styles */
2 |
3 | .leaflet-pane,
4 | .leaflet-tile,
5 | .leaflet-marker-icon,
6 | .leaflet-marker-shadow,
7 | .leaflet-tile-container,
8 | .leaflet-pane > svg,
9 | .leaflet-pane > canvas,
10 | .leaflet-zoom-box,
11 | .leaflet-image-layer,
12 | .leaflet-layer {
13 | position: absolute;
14 | left: 0;
15 | top: 0;
16 | }
17 | .leaflet-container {
18 | overflow: hidden;
19 | }
20 | .leaflet-tile,
21 | .leaflet-marker-icon,
22 | .leaflet-marker-shadow {
23 | -webkit-user-select: none;
24 | -moz-user-select: none;
25 | user-select: none;
26 | -webkit-user-drag: none;
27 | }
28 | /* Safari renders non-retina tile on retina better with this, but Chrome is worse */
29 | .leaflet-safari .leaflet-tile {
30 | image-rendering: -webkit-optimize-contrast;
31 | }
32 | /* hack that prevents hw layers "stretching" when loading new tiles */
33 | .leaflet-safari .leaflet-tile-container {
34 | width: 1600px;
35 | height: 1600px;
36 | -webkit-transform-origin: 0 0;
37 | }
38 | .leaflet-marker-icon,
39 | .leaflet-marker-shadow {
40 | display: block;
41 | }
42 | /* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
43 | /* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
44 | .leaflet-container .leaflet-overlay-pane svg,
45 | .leaflet-container .leaflet-marker-pane img,
46 | .leaflet-container .leaflet-shadow-pane img,
47 | .leaflet-container .leaflet-tile-pane img,
48 | .leaflet-container img.leaflet-image-layer {
49 | max-width: none !important;
50 | }
51 |
52 | .leaflet-container.leaflet-touch-zoom {
53 | -ms-touch-action: pan-x pan-y;
54 | touch-action: pan-x pan-y;
55 | }
56 | .leaflet-container.leaflet-touch-drag {
57 | -ms-touch-action: pinch-zoom;
58 | }
59 | .leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
60 | -ms-touch-action: none;
61 | touch-action: none;
62 | }
63 | .leaflet-container {
64 | -webkit-tap-highlight-color: transparent;
65 | }
66 | .leaflet-container a {
67 | -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
68 | }
69 | .leaflet-tile {
70 | filter: inherit;
71 | visibility: hidden;
72 | }
73 | .leaflet-tile-loaded {
74 | visibility: inherit;
75 | }
76 | .leaflet-zoom-box {
77 | width: 0;
78 | height: 0;
79 | -moz-box-sizing: border-box;
80 | box-sizing: border-box;
81 | z-index: 800;
82 | }
83 | /* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
84 | .leaflet-overlay-pane svg {
85 | -moz-user-select: none;
86 | }
87 |
88 | .leaflet-pane { z-index: 400; }
89 |
90 | .leaflet-tile-pane { z-index: 200; }
91 | .leaflet-overlay-pane { z-index: 400; }
92 | .leaflet-shadow-pane { z-index: 500; }
93 | .leaflet-marker-pane { z-index: 600; }
94 | .leaflet-tooltip-pane { z-index: 650; }
95 | .leaflet-popup-pane { z-index: 700; }
96 |
97 | .leaflet-map-pane canvas { z-index: 100; }
98 | .leaflet-map-pane svg { z-index: 200; }
99 |
100 | .leaflet-vml-shape {
101 | width: 1px;
102 | height: 1px;
103 | }
104 | .lvml {
105 | behavior: url(#default#VML);
106 | display: inline-block;
107 | position: absolute;
108 | }
109 |
110 |
111 | /* control positioning */
112 |
113 | .leaflet-control {
114 | position: relative;
115 | z-index: 800;
116 | pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
117 | pointer-events: auto;
118 | }
119 | .leaflet-top,
120 | .leaflet-bottom {
121 | position: absolute;
122 | z-index: 1000;
123 | pointer-events: none;
124 | }
125 | .leaflet-top {
126 | top: 0;
127 | }
128 | .leaflet-right {
129 | right: 0;
130 | }
131 | .leaflet-bottom {
132 | bottom: 0;
133 | }
134 | .leaflet-left {
135 | left: 0;
136 | }
137 | .leaflet-control {
138 | float: left;
139 | clear: both;
140 | }
141 | .leaflet-right .leaflet-control {
142 | float: right;
143 | }
144 | .leaflet-top .leaflet-control {
145 | margin-top: 10px;
146 | }
147 | .leaflet-bottom .leaflet-control {
148 | margin-bottom: 10px;
149 | }
150 | .leaflet-left .leaflet-control {
151 | margin-left: 10px;
152 | }
153 | .leaflet-right .leaflet-control {
154 | margin-right: 10px;
155 | }
156 |
157 |
158 | /* zoom and fade animations */
159 |
160 | .leaflet-fade-anim .leaflet-tile {
161 | will-change: opacity;
162 | }
163 | .leaflet-fade-anim .leaflet-popup {
164 | opacity: 0;
165 | -webkit-transition: opacity 0.2s linear;
166 | -moz-transition: opacity 0.2s linear;
167 | -o-transition: opacity 0.2s linear;
168 | transition: opacity 0.2s linear;
169 | }
170 | .leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
171 | opacity: 1;
172 | }
173 | .leaflet-zoom-animated {
174 | -webkit-transform-origin: 0 0;
175 | -ms-transform-origin: 0 0;
176 | transform-origin: 0 0;
177 | }
178 | .leaflet-zoom-anim .leaflet-zoom-animated {
179 | will-change: transform;
180 | }
181 | .leaflet-zoom-anim .leaflet-zoom-animated {
182 | -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
183 | -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
184 | -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
185 | transition: transform 0.25s cubic-bezier(0,0,0.25,1);
186 | }
187 | .leaflet-zoom-anim .leaflet-tile,
188 | .leaflet-pan-anim .leaflet-tile {
189 | -webkit-transition: none;
190 | -moz-transition: none;
191 | -o-transition: none;
192 | transition: none;
193 | }
194 |
195 | .leaflet-zoom-anim .leaflet-zoom-hide {
196 | visibility: hidden;
197 | }
198 |
199 |
200 | /* cursors */
201 |
202 | .leaflet-interactive {
203 | cursor: pointer;
204 | }
205 | .leaflet-grab {
206 | cursor: -webkit-grab;
207 | cursor: -moz-grab;
208 | }
209 | .leaflet-crosshair,
210 | .leaflet-crosshair .leaflet-interactive {
211 | cursor: crosshair;
212 | }
213 | .leaflet-popup-pane,
214 | .leaflet-control {
215 | cursor: auto;
216 | }
217 | .leaflet-dragging .leaflet-grab,
218 | .leaflet-dragging .leaflet-grab .leaflet-interactive,
219 | .leaflet-dragging .leaflet-marker-draggable {
220 | cursor: move;
221 | cursor: -webkit-grabbing;
222 | cursor: -moz-grabbing;
223 | }
224 |
225 | /* marker & overlays interactivity */
226 | .leaflet-marker-icon,
227 | .leaflet-marker-shadow,
228 | .leaflet-image-layer,
229 | .leaflet-pane > svg path,
230 | .leaflet-tile-container {
231 | pointer-events: none;
232 | }
233 |
234 | .leaflet-marker-icon.leaflet-interactive,
235 | .leaflet-image-layer.leaflet-interactive,
236 | .leaflet-pane > svg path.leaflet-interactive {
237 | pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
238 | pointer-events: auto;
239 | }
240 |
241 | /* visual tweaks */
242 |
243 | .leaflet-container {
244 | background: #ddd;
245 | outline: 0;
246 | }
247 | .leaflet-container a {
248 | color: #0078A8;
249 | }
250 | .leaflet-container a.leaflet-active {
251 | outline: 2px solid orange;
252 | }
253 | .leaflet-zoom-box {
254 | border: 2px dotted #38f;
255 | background: rgba(255,255,255,0.5);
256 | }
257 |
258 |
259 | /* general typography */
260 | .leaflet-container {
261 | font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
262 | }
263 |
264 |
265 | /* general toolbar styles */
266 |
267 | .leaflet-bar {
268 | box-shadow: 0 1px 5px rgba(0,0,0,0.65);
269 | border-radius: 4px;
270 | }
271 | .leaflet-bar a,
272 | .leaflet-bar a:hover {
273 | background-color: #fff;
274 | border-bottom: 1px solid #ccc;
275 | width: 26px;
276 | height: 26px;
277 | line-height: 26px;
278 | display: block;
279 | text-align: center;
280 | text-decoration: none;
281 | color: black;
282 | }
283 | .leaflet-bar a,
284 | .leaflet-control-layers-toggle {
285 | background-position: 50% 50%;
286 | background-repeat: no-repeat;
287 | display: block;
288 | }
289 | .leaflet-bar a:hover {
290 | background-color: #f4f4f4;
291 | }
292 | .leaflet-bar a:first-child {
293 | border-top-left-radius: 4px;
294 | border-top-right-radius: 4px;
295 | }
296 | .leaflet-bar a:last-child {
297 | border-bottom-left-radius: 4px;
298 | border-bottom-right-radius: 4px;
299 | border-bottom: none;
300 | }
301 | .leaflet-bar a.leaflet-disabled {
302 | cursor: default;
303 | background-color: #f4f4f4;
304 | color: #bbb;
305 | }
306 |
307 | .leaflet-touch .leaflet-bar a {
308 | width: 30px;
309 | height: 30px;
310 | line-height: 30px;
311 | }
312 | .leaflet-touch .leaflet-bar a:first-child {
313 | border-top-left-radius: 2px;
314 | border-top-right-radius: 2px;
315 | }
316 | .leaflet-touch .leaflet-bar a:last-child {
317 | border-bottom-left-radius: 2px;
318 | border-bottom-right-radius: 2px;
319 | }
320 |
321 | /* zoom control */
322 |
323 | .leaflet-control-zoom-in,
324 | .leaflet-control-zoom-out {
325 | font: bold 18px 'Lucida Console', Monaco, monospace;
326 | text-indent: 1px;
327 | }
328 |
329 | .leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
330 | font-size: 22px;
331 | }
332 |
333 |
334 | /* layers control */
335 |
336 | .leaflet-control-layers {
337 | box-shadow: 0 1px 5px rgba(0,0,0,0.4);
338 | background: #fff;
339 | border-radius: 5px;
340 | }
341 | .leaflet-control-layers-toggle {
342 | background-image: url(images/layers.png);
343 | width: 36px;
344 | height: 36px;
345 | }
346 | .leaflet-retina .leaflet-control-layers-toggle {
347 | background-image: url(images/layers-2x.png);
348 | background-size: 26px 26px;
349 | }
350 | .leaflet-touch .leaflet-control-layers-toggle {
351 | width: 44px;
352 | height: 44px;
353 | }
354 | .leaflet-control-layers .leaflet-control-layers-list,
355 | .leaflet-control-layers-expanded .leaflet-control-layers-toggle {
356 | display: none;
357 | }
358 | .leaflet-control-layers-expanded .leaflet-control-layers-list {
359 | display: block;
360 | position: relative;
361 | }
362 | .leaflet-control-layers-expanded {
363 | padding: 6px 10px 6px 6px;
364 | color: #333;
365 | background: #fff;
366 | }
367 | .leaflet-control-layers-scrollbar {
368 | overflow-y: scroll;
369 | overflow-x: hidden;
370 | padding-right: 5px;
371 | }
372 | .leaflet-control-layers-selector {
373 | margin-top: 2px;
374 | position: relative;
375 | top: 1px;
376 | }
377 | .leaflet-control-layers label {
378 | display: block;
379 | }
380 | .leaflet-control-layers-separator {
381 | height: 0;
382 | border-top: 1px solid #ddd;
383 | margin: 5px -10px 5px -6px;
384 | }
385 |
386 | /* Default icon URLs */
387 | .leaflet-default-icon-path {
388 | background-image: url(images/marker-icon.png);
389 | }
390 |
391 |
392 | /* attribution and scale controls */
393 |
394 | .leaflet-container .leaflet-control-attribution {
395 | background: #fff;
396 | background: rgba(255, 255, 255, 0.7);
397 | margin: 0;
398 | }
399 | .leaflet-control-attribution,
400 | .leaflet-control-scale-line {
401 | padding: 0 5px;
402 | color: #333;
403 | }
404 | .leaflet-control-attribution a {
405 | text-decoration: none;
406 | }
407 | .leaflet-control-attribution a:hover {
408 | text-decoration: underline;
409 | }
410 | .leaflet-container .leaflet-control-attribution,
411 | .leaflet-container .leaflet-control-scale {
412 | font-size: 11px;
413 | }
414 | .leaflet-left .leaflet-control-scale {
415 | margin-left: 5px;
416 | }
417 | .leaflet-bottom .leaflet-control-scale {
418 | margin-bottom: 5px;
419 | }
420 | .leaflet-control-scale-line {
421 | border: 2px solid #777;
422 | border-top: none;
423 | line-height: 1.1;
424 | padding: 2px 5px 1px;
425 | font-size: 11px;
426 | white-space: nowrap;
427 | overflow: hidden;
428 | -moz-box-sizing: border-box;
429 | box-sizing: border-box;
430 |
431 | background: #fff;
432 | background: rgba(255, 255, 255, 0.5);
433 | }
434 | .leaflet-control-scale-line:not(:first-child) {
435 | border-top: 2px solid #777;
436 | border-bottom: none;
437 | margin-top: -2px;
438 | }
439 | .leaflet-control-scale-line:not(:first-child):not(:last-child) {
440 | border-bottom: 2px solid #777;
441 | }
442 |
443 | .leaflet-touch .leaflet-control-attribution,
444 | .leaflet-touch .leaflet-control-layers,
445 | .leaflet-touch .leaflet-bar {
446 | box-shadow: none;
447 | }
448 | .leaflet-touch .leaflet-control-layers,
449 | .leaflet-touch .leaflet-bar {
450 | border: 2px solid rgba(0,0,0,0.2);
451 | background-clip: padding-box;
452 | }
453 |
454 |
455 | /* popup */
456 |
457 | .leaflet-popup {
458 | position: absolute;
459 | text-align: center;
460 | margin-bottom: 20px;
461 | }
462 | .leaflet-popup-content-wrapper {
463 | padding: 1px;
464 | text-align: left;
465 | border-radius: 12px;
466 | }
467 | .leaflet-popup-content {
468 | margin: 13px 19px;
469 | line-height: 1.4;
470 | }
471 | .leaflet-popup-content p {
472 | margin: 18px 0;
473 | }
474 | .leaflet-popup-tip-container {
475 | width: 40px;
476 | height: 20px;
477 | position: absolute;
478 | left: 50%;
479 | margin-left: -20px;
480 | overflow: hidden;
481 | pointer-events: none;
482 | }
483 | .leaflet-popup-tip {
484 | width: 17px;
485 | height: 17px;
486 | padding: 1px;
487 |
488 | margin: -10px auto 0;
489 |
490 | -webkit-transform: rotate(45deg);
491 | -moz-transform: rotate(45deg);
492 | -ms-transform: rotate(45deg);
493 | -o-transform: rotate(45deg);
494 | transform: rotate(45deg);
495 | }
496 | .leaflet-popup-content-wrapper,
497 | .leaflet-popup-tip {
498 | background: white;
499 | color: #333;
500 | box-shadow: 0 3px 14px rgba(0,0,0,0.4);
501 | }
502 | .leaflet-container a.leaflet-popup-close-button {
503 | position: absolute;
504 | top: 0;
505 | right: 0;
506 | padding: 4px 4px 0 0;
507 | border: none;
508 | text-align: center;
509 | width: 18px;
510 | height: 14px;
511 | font: 16px/14px Tahoma, Verdana, sans-serif;
512 | color: #c3c3c3;
513 | text-decoration: none;
514 | font-weight: bold;
515 | background: transparent;
516 | }
517 | .leaflet-container a.leaflet-popup-close-button:hover {
518 | color: #999;
519 | }
520 | .leaflet-popup-scrolled {
521 | overflow: auto;
522 | border-bottom: 1px solid #ddd;
523 | border-top: 1px solid #ddd;
524 | }
525 |
526 | .leaflet-oldie .leaflet-popup-content-wrapper {
527 | zoom: 1;
528 | }
529 | .leaflet-oldie .leaflet-popup-tip {
530 | width: 24px;
531 | margin: 0 auto;
532 |
533 | -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
534 | filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
535 | }
536 | .leaflet-oldie .leaflet-popup-tip-container {
537 | margin-top: -1px;
538 | }
539 |
540 | .leaflet-oldie .leaflet-control-zoom,
541 | .leaflet-oldie .leaflet-control-layers,
542 | .leaflet-oldie .leaflet-popup-content-wrapper,
543 | .leaflet-oldie .leaflet-popup-tip {
544 | border: 1px solid #999;
545 | }
546 |
547 |
548 | /* div icon */
549 |
550 | .leaflet-div-icon {
551 | background: #fff;
552 | border: 1px solid #666;
553 | }
554 |
555 |
556 | /* Tooltip */
557 | /* Base styles for the element that has a tooltip */
558 | .leaflet-tooltip {
559 | position: absolute;
560 | padding: 6px;
561 | background-color: #fff;
562 | border: 1px solid #fff;
563 | border-radius: 3px;
564 | color: #222;
565 | white-space: nowrap;
566 | -webkit-user-select: none;
567 | -moz-user-select: none;
568 | -ms-user-select: none;
569 | user-select: none;
570 | pointer-events: none;
571 | box-shadow: 0 1px 3px rgba(0,0,0,0.4);
572 | }
573 | .leaflet-tooltip.leaflet-clickable {
574 | cursor: pointer;
575 | pointer-events: auto;
576 | }
577 | .leaflet-tooltip-top:before,
578 | .leaflet-tooltip-bottom:before,
579 | .leaflet-tooltip-left:before,
580 | .leaflet-tooltip-right:before {
581 | position: absolute;
582 | pointer-events: none;
583 | border: 6px solid transparent;
584 | background: transparent;
585 | content: "";
586 | }
587 |
588 | /* Directions */
589 |
590 | .leaflet-tooltip-bottom {
591 | margin-top: 6px;
592 | }
593 | .leaflet-tooltip-top {
594 | margin-top: -6px;
595 | }
596 | .leaflet-tooltip-bottom:before,
597 | .leaflet-tooltip-top:before {
598 | left: 50%;
599 | margin-left: -6px;
600 | }
601 | .leaflet-tooltip-top:before {
602 | bottom: 0;
603 | margin-bottom: -12px;
604 | border-top-color: #fff;
605 | }
606 | .leaflet-tooltip-bottom:before {
607 | top: 0;
608 | margin-top: -12px;
609 | margin-left: -6px;
610 | border-bottom-color: #fff;
611 | }
612 | .leaflet-tooltip-left {
613 | margin-left: -6px;
614 | }
615 | .leaflet-tooltip-right {
616 | margin-left: 6px;
617 | }
618 | .leaflet-tooltip-left:before,
619 | .leaflet-tooltip-right:before {
620 | top: 50%;
621 | margin-top: -6px;
622 | }
623 | .leaflet-tooltip-left:before {
624 | right: 0;
625 | margin-right: -12px;
626 | border-left-color: #fff;
627 | }
628 | .leaflet-tooltip-right:before {
629 | left: 0;
630 | margin-left: -12px;
631 | border-right-color: #fff;
632 | }
633 |
--------------------------------------------------------------------------------
/src/scss/cssIncludes/_pivot.scss:
--------------------------------------------------------------------------------
1 | .pvtUi { color: #333; }
2 |
3 |
4 | table.pvtTable {
5 | font-size: 8pt;
6 | text-align: left;
7 | border-collapse: collapse;
8 | }
9 | table.pvtTable thead tr th, table.pvtTable tbody tr th {
10 | background-color: #e6EEEE;
11 | border: 1px solid #CDCDCD;
12 | font-size: 8pt;
13 | padding: 5px;
14 | }
15 |
16 | table.pvtTable .pvtColLabel {text-align: center;}
17 | table.pvtTable .pvtTotalLabel {text-align: right;}
18 |
19 | table.pvtTable tbody tr td {
20 | color: #3D3D3D;
21 | padding: 5px;
22 | background-color: #FFF;
23 | border: 1px solid #CDCDCD;
24 | vertical-align: top;
25 | text-align: right;
26 | }
27 |
28 | .pvtTotal, .pvtGrandTotal { font-weight: bold; }
29 |
30 | .pvtVals { text-align: center;}
31 | .pvtAggregator { margin-bottom: 5px ;}
32 |
33 | .pvtAxisContainer, .pvtVals {
34 | border: 1px solid gray;
35 | background: #EEE;
36 | padding: 5px;
37 | min-width: 20px;
38 | min-height: 20px;
39 | }
40 | .pvtAxisContainer li {
41 | padding: 8px 6px;
42 | list-style-type: none;
43 | cursor:move;
44 | }
45 | .pvtAxisContainer li.pvtPlaceholder {
46 | -webkit-border-radius: 5px;
47 | padding: 3px 15px;
48 | -moz-border-radius: 5px;
49 | border-radius: 5px;
50 | border: 1px dashed #aaa;
51 | }
52 |
53 | .pvtAxisContainer li span.pvtAttr {
54 | -webkit-text-size-adjust: 100%;
55 | background: #F3F3F3;
56 | border: 1px solid #DEDEDE;
57 | padding: 2px 5px;
58 | white-space:nowrap;
59 | -webkit-border-radius: 5px;
60 | -moz-border-radius: 5px;
61 | border-radius: 5px;
62 | }
63 |
64 | .pvtTriangle {
65 | cursor:pointer;
66 | color: grey;
67 | }
68 |
69 | .pvtHorizList li { display: inline; }
70 | .pvtVertList { vertical-align: top; }
71 |
72 | .pvtFilteredAttribute { font-style: italic }
73 |
74 | .pvtFilterBox{
75 | z-index: 100;
76 | width: 280px;
77 | border: 1px solid gray;
78 | background-color: #fff;
79 | position: absolute;
80 | padding: 20px;
81 | text-align: center;
82 | }
83 |
84 | .pvtFilterBox h4{ margin:0; }
85 | .pvtFilterBox p { margin: 1em auto; }
86 | .pvtFilterBox label { font-weight: normal; }
87 | .pvtFilterBox input[type='checkbox'] { margin-right: 5px; }
88 |
89 | .pvtCheckContainer{
90 | text-align: left;
91 | overflow: scroll;
92 | width: 100%;
93 | max-height: 200px;
94 | }
95 | .pvtCheckContainer p{ margin: 5px; }
96 |
97 | .pvtRendererArea { padding: 5px;}
--------------------------------------------------------------------------------
/src/scss/global.scss:
--------------------------------------------------------------------------------
1 | @import "./variables.scss";
2 | /**need to reset this: the modal-dialog class conflicts with bootstrap**/
3 | .modal-dialog.google-visualization-charteditor-dialog {
4 | z-index: $zIndex-global;
5 | width: auto;
6 | margin: inherit;
7 | .charts-flat-menu-button {
8 | box-sizing: content-box;
9 | }
10 | }
--------------------------------------------------------------------------------
/src/scss/scoped.scss:
--------------------------------------------------------------------------------
1 |
2 | .yasr {
3 | @import "../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap/_variables.scss";
4 |
5 | @import "cssIncludes/_jquery.dataTables.scss";
6 | @import "cssIncludes/_pivot.scss";
7 | @import "cssIncludes/_codemirror.scss";
8 | @import "cssIncludes/_foldgutter.scss";
9 | @import "cssIncludes/_leaflet.scss";
10 |
11 | @import "./yasr.scss";
12 | }
13 |
--------------------------------------------------------------------------------
/src/scss/variables.scss:
--------------------------------------------------------------------------------
1 | $zIndex-fullscreen: 10;
2 | $zIndex-global: $zIndex-fullscreen +1;
--------------------------------------------------------------------------------
/src/scss/yasr.scss:
--------------------------------------------------------------------------------
1 | @import "./variables.scss";
2 | @import "../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap/_variables.scss";
3 | & {
4 |
5 | padding-top: 5px;
6 | background-color:white;
7 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
8 | font-size: 14px;
9 | line-height: 1.428571429;
10 | color: #333333;
11 |
12 | @import "../main.scss";
13 | @import "../boolean.scss";
14 | @import "../error.scss";
15 | @import "../rawResponse.scss";
16 | @import "../table.scss";
17 | @import "../pivot.scss";
18 | @import "../gchart.scss";
19 | @import "../leaflet.scss";
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/table.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery"), yutils = require("yasgui-utils"), utils = require("./utils.js"), imgs = require("./imgs.js");
3 | require("datatables.net")();
4 | require("../lib/colResizable-1.4.js");
5 |
6 | /**
7 | * Constructor of plugin which displays results as a table
8 | *
9 | * @param yasr {object}
10 | * @param parent {DOM element}
11 | * @param options {object}
12 | * @class YASR.plugins.table
13 | * @return yasr-table (doc)
14 | *
15 | */
16 | var root = (module.exports = function(yasr) {
17 | var table = null;
18 | var plugin = {
19 | name: "Table",
20 | getPriority: 10
21 | };
22 | var options = (plugin.options = $.extend(true, {}, root.defaults));
23 | var tableLengthPersistencyId = options.persistency ? yasr.getPersistencyId(options.persistency.tableLength) : null;
24 |
25 | var getRows = function() {
26 | var rows = [];
27 | var bindings = yasr.results.getBindings();
28 | var vars = yasr.results.getVariables();
29 | var usedPrefixes = null;
30 | if (yasr.options.getUsedPrefixes) {
31 | usedPrefixes = typeof yasr.options.getUsedPrefixes == "function"
32 | ? yasr.options.getUsedPrefixes(yasr)
33 | : yasr.options.getUsedPrefixes;
34 | }
35 | for (var rowId = 0; rowId < bindings.length; rowId++) {
36 | var row = [];
37 | row.push(""); //row numbers
38 | var binding = bindings[rowId];
39 | for (var colId = 0; colId < vars.length; colId++) {
40 | var sparqlVar = vars[colId];
41 | if (sparqlVar in binding) {
42 | if (options.getCellContent) {
43 | row.push(
44 | options.getCellContent(yasr, plugin, binding, sparqlVar, {
45 | rowId: rowId,
46 | colId: colId,
47 | usedPrefixes: usedPrefixes
48 | })
49 | );
50 | } else {
51 | row.push("");
52 | }
53 | } else {
54 | row.push("");
55 | }
56 | }
57 | rows.push(row);
58 | }
59 | return rows;
60 | };
61 |
62 | var eventId = yasr.getPersistencyId("eventId") || "yasr_" + $(yasr.container).closest("[id]").attr("id");
63 | var addEvents = function() {
64 | table.on("order.dt", function() {
65 | drawSvgIcons();
66 | });
67 | if (tableLengthPersistencyId) {
68 | table.on("length.dt", function(e, settings, len) {
69 | yutils.storage.set(tableLengthPersistencyId, len, "month", yasr.options.onQuotaExceeded);
70 | });
71 | }
72 | $.extend(true, options.callbacks, options.handlers);
73 | table
74 | .delegate("td", "click", function(event) {
75 | if (options.callbacks && options.callbacks.onCellClick) {
76 | var result = options.callbacks.onCellClick(this, event);
77 | if (result === false) return false;
78 | }
79 | })
80 | .delegate("td", "mouseenter", function(event) {
81 | if (options.callbacks && options.callbacks.onCellMouseEnter) {
82 | options.callbacks.onCellMouseEnter(this, event);
83 | }
84 | var tdEl = $(this);
85 | if (
86 | options.fetchTitlesFromPreflabel &&
87 | tdEl.attr("title") === undefined &&
88 | tdEl.text().trim().indexOf("http") == 0
89 | ) {
90 | addPrefLabel(tdEl);
91 | }
92 | })
93 | .delegate("td", "mouseleave", function(event) {
94 | if (options.callbacks && options.callbacks.onCellMouseLeave) {
95 | options.callbacks.onCellMouseLeave(this, event);
96 | }
97 | });
98 | };
99 |
100 | plugin.draw = function() {
101 | table = $('
');
102 | $(yasr.resultsContainer).html(table);
103 |
104 | var dataTableConfig = options.datatable;
105 | dataTableConfig.data = getRows();
106 | dataTableConfig.columns = options.getColumns(yasr, plugin);
107 |
108 | //fetch stored datatables length value
109 | var pLength = yutils.storage.get(tableLengthPersistencyId);
110 | if (pLength) dataTableConfig.pageLength = pLength;
111 |
112 | table.DataTable($.extend(true, {}, dataTableConfig)); //make copy. datatables adds properties for backwards compatability reasons, and don't want this cluttering our own
113 |
114 | drawSvgIcons();
115 |
116 | addEvents();
117 |
118 | //finally, make the columns dragable:
119 | table.colResizable();
120 | };
121 |
122 | var drawSvgIcons = function() {
123 | var sortings = {
124 | sorting: "unsorted",
125 | sorting_asc: "sortAsc",
126 | sorting_desc: "sortDesc"
127 | };
128 | table.find(".sortIcons").remove();
129 | for (var sorting in sortings) {
130 | var svgDiv = $("
");
131 | yutils.svg.draw(svgDiv, imgs[sortings[sorting]]);
132 | table.find("th." + sorting).append(svgDiv);
133 | }
134 | };
135 | /**
136 | * Check whether this plugin can handler the current results
137 | *
138 | * @property canHandleResults
139 | * @type function
140 | * @default If resultset contains variables in the resultset, return true
141 | */
142 | plugin.canHandleResults = function() {
143 | return (
144 | yasr.results && yasr.results.getVariables && yasr.results.getVariables() && yasr.results.getVariables().length > 0
145 | );
146 | };
147 |
148 | plugin.getDownloadInfo = function() {
149 | if (!yasr.results) return null;
150 | return {
151 | getContent: function() {
152 | return require("./bindingsToCsv.js")(yasr.results.getAsJson());
153 | },
154 | filename: "queryResults.csv",
155 | contentType: "text/csv",
156 | buttonTitle: "Download as CSV"
157 | };
158 | };
159 |
160 | return plugin;
161 | });
162 |
163 | var formatLiteral = function(yasr, plugin, literalBinding) {
164 | var stringRepresentation = utils.escapeHtmlEntities(literalBinding.value);
165 | if (literalBinding["xml:lang"]) {
166 | stringRepresentation = '"' + stringRepresentation + '"
@' + literalBinding["xml:lang"] + " ";
167 | } else if (literalBinding.datatype) {
168 | var xmlSchemaNs = "http://www.w3.org/2001/XMLSchema#";
169 | var dataType = literalBinding.datatype;
170 | if (dataType.indexOf(xmlSchemaNs) === 0) {
171 | dataType = "xsd:" + dataType.substring(xmlSchemaNs.length);
172 | } else {
173 | dataType = "<" + dataType + ">";
174 | }
175 |
176 | stringRepresentation = '"' + stringRepresentation + '"
^^' + dataType + " ";
177 | }
178 | return stringRepresentation;
179 | };
180 | var getCellContent = function(yasr, plugin, bindings, sparqlVar, context) {
181 | var binding = bindings[sparqlVar];
182 | var value = null;
183 | if (binding.type == "uri") {
184 | var title = null;
185 | var href = binding.value;
186 | var visibleString = href;
187 | if (context.usedPrefixes) {
188 | for (var prefix in context.usedPrefixes) {
189 | if (visibleString.indexOf(context.usedPrefixes[prefix]) == 0) {
190 | visibleString = prefix + ":" + href.substring(context.usedPrefixes[prefix].length);
191 | break;
192 | }
193 | }
194 | }
195 | if (plugin.options.mergeLabelsWithUris) {
196 | var postFix = typeof plugin.options.mergeLabelsWithUris == "string"
197 | ? plugin.options.mergeLabelsWithUris
198 | : "Label";
199 | if (bindings[sparqlVar + postFix]) {
200 | visibleString = formatLiteral(yasr, plugin, bindings[sparqlVar + postFix]);
201 | title = href;
202 | }
203 | }
204 | value =
205 | "
" +
212 | visibleString +
213 | " ";
214 | } else {
215 | value = "
" + formatLiteral(yasr, plugin, binding) + " ";
216 | }
217 | return "
" + value + "
";
218 | };
219 |
220 | var addPrefLabel = function(td) {
221 | var addEmptyTitle = function() {
222 | td.attr("title", ""); //this avoids trying to fetch the label again on next hover
223 | };
224 | $.get("//preflabel.org/api/v1/label/" + encodeURIComponent(td.text()) + "?silent=true")
225 | .success(function(data) {
226 | if (typeof data == "object" && data.label) {
227 | td.attr("title", data.label);
228 | } else if (typeof data == "string" && data.length > 0) {
229 | td.attr("title", data);
230 | } else {
231 | addEmptyTitle();
232 | }
233 | })
234 | .fail(addEmptyTitle);
235 | };
236 |
237 | var openCellUriInNewWindow = function(cell) {
238 | if (cell.className.indexOf("uri") >= 0) {
239 | window.open(this.innerHTML);
240 | }
241 | };
242 |
243 | /**
244 | * Defaults for table plugin
245 | *
246 | * @type object
247 | * @attribute YASR.plugins.table.defaults
248 | */
249 | root.defaults = {
250 | /**
251 | * Draw the cell content, from a given binding
252 | *
253 | * @property drawCellContent
254 | * @param binding {object}
255 | * @type function
256 | * @return string
257 | * @default YASR.plugins.table.getFormattedValueFromBinding
258 | */
259 | getCellContent: getCellContent,
260 |
261 | persistency: {
262 | tableLength: "tableLength"
263 | },
264 |
265 | getColumns: function(yasr, plugin) {
266 | var includeVariable = function(variableToCheck) {
267 | if (!plugin.options.mergeLabelsWithUris) return true;
268 | var postFix = typeof plugin.options.mergeLabelsWithUris == "string"
269 | ? plugin.options.mergeLabelsWithUris
270 | : "Label";
271 | if (variableToCheck.indexOf(postFix, variableToCheck.length - postFix.length) !== -1) {
272 | //this one ends with a postfix
273 | if (
274 | yasr.results.getVariables().indexOf(variableToCheck.substring(0, variableToCheck.length - postFix.length)) >=
275 | 0
276 | ) {
277 | //we have a shorter version of this variable. So, do not include the ..
variable in the table
278 | return false;
279 | }
280 | }
281 | return true;
282 | };
283 |
284 | var cols = [];
285 | cols.push({
286 | title: ""
287 | }); //row numbers column
288 | yasr.results.getVariables().forEach(function(variable) {
289 | cols.push({
290 | title: "" + variable + " ",
291 | visible: includeVariable(variable)
292 | });
293 | });
294 | return cols;
295 | },
296 | /**
297 | * Try to fetch the label representation for each URI, using the preflabel.org services. (fetching occurs when hovering over the cell)
298 | *
299 | * @property fetchTitlesFromPreflabel
300 | * @type boolean
301 | * @default false, if YASR is served via https
302 | */
303 | //important to keep supporting serving yasr via file:// protocol
304 | fetchTitlesFromPreflabel: window.location.protocol === "https:" ? false : true,
305 |
306 | mergeLabelsWithUris: false,
307 | /**
308 | * Set a number of handlers for the table
309 | *
310 | * @property handlers
311 | * @type object
312 | */
313 | callbacks: {
314 | /**
315 | * Mouse-enter-cell event
316 | *
317 | * @property handlers.onCellMouseEnter
318 | * @type function
319 | * @param td-element
320 | * @default null
321 | */
322 | onCellMouseEnter: null,
323 | /**
324 | * Mouse-leave-cell event
325 | *
326 | * @property handlers.onCellMouseLeave
327 | * @type function
328 | * @param td-element
329 | * @default null
330 | */
331 | onCellMouseLeave: null,
332 | /**
333 | * Cell clicked event
334 | *
335 | * @property handlers.onCellClick
336 | * @type function
337 | * @param td-element
338 | * @default null
339 | */
340 | onCellClick: null
341 | },
342 | /**
343 | * This plugin uses the datatables jquery plugin (See datatables.net). For any datatables specific defaults, change this object.
344 | * See the datatables reference for more information
345 | *
346 | * @property datatable
347 | * @type object
348 | */
349 | datatable: {
350 | autoWidth: true,
351 | dom: '<"dtTopHeader"ilf>rtip',
352 | order: [], //disable initial sorting
353 | pageLength: 50, //default page length
354 | lengthMenu: [[10, 50, 100, 1000, -1], [10, 50, 100, 1000, "All"]], //possible page lengths
355 | lengthChange: true, //allow changing page length
356 | pagingType: "full_numbers", //how to show the pagination options
357 | drawCallback: function(oSettings) {
358 | //trick to show row numbers
359 | for (var i = 0; i < oSettings.aiDisplay.length; i++) {
360 | $("td:eq(0)", oSettings.aoData[oSettings.aiDisplay[i]].nTr).html(i + 1);
361 | }
362 |
363 | //Hide pagination when we have a single page
364 | var activePaginateButton = false;
365 | $(oSettings.nTableWrapper).find(".paginate_button").each(function() {
366 | if ($(this).attr("class").indexOf("current") == -1 && $(this).attr("class").indexOf("disabled") == -1) {
367 | activePaginateButton = true;
368 | }
369 | });
370 | if (activePaginateButton) {
371 | $(oSettings.nTableWrapper).find(".dataTables_paginate").show();
372 | } else {
373 | $(oSettings.nTableWrapper).find(".dataTables_paginate").hide();
374 | }
375 | },
376 | columnDefs: [
377 | {
378 | width: "32px",
379 | orderable: false,
380 | targets: 0
381 | } //disable row sorting for first col
382 | ]
383 | }
384 | };
385 | root.version = {
386 | "YASR-table": require("../package.json").version,
387 | jquery: $.fn.jquery,
388 | "jquery-datatables": $.fn.DataTable.version
389 | };
390 |
--------------------------------------------------------------------------------
/src/table.scss:
--------------------------------------------------------------------------------
1 | .dataTables_wrapper {
2 | margin-top: 10px;
3 | .dataTables_length {
4 | float:right;
5 | margin-left: 10px;
6 | label, select {
7 | vertical-align: middle;
8 | }
9 | }
10 | }
11 | table.dataTable.no-footer.resultsTable {
12 | border-bottom: 1px solid #ddd;
13 | }
14 | table.dataTable thead th {
15 | &:first-child, &:last-child {
16 | border-right: 0;
17 | }
18 |
19 | border-bottom: 2px solid #ddd;
20 | //hide icons (we use svg)
21 | background:none !important;
22 | border-right: 1px dotted gray;
23 | padding: 7px 0px;
24 | span {
25 | margin-left: 5px;
26 | }
27 | }
28 | table.dataTable {
29 | tr:nth-child(even) {background-color: #f9f9f9;}
30 | }
31 | table.dataTable td {
32 | border-top: 1px solid #ddd;
33 | div {
34 | -ms-word-break: break-all;
35 | word-break: break-all;
36 |
37 | /* Non standard for webkit */
38 | word-break: break-word;
39 |
40 | -webkit-hyphens: auto;
41 | -moz-hyphens: auto;
42 | -ms-hyphens: auto;
43 | hyphens: auto;
44 | padding: 0px 5px;
45 | }
46 | }
47 |
48 |
49 | .sortIcons {
50 | float:right;
51 | width: 8px;
52 | height: 13px;
53 | margin-right: 10px;
54 | }
55 | .dtTopHeader {
56 | .dataTables_info {
57 | padding-top: 0px;
58 | margin: 0px 10px;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var $ = require("jquery"), GoogleTypeException = require("./exceptions.js").GoogleTypeException;
3 |
4 | module.exports = {
5 | escapeHtmlEntities: function(unescaped) {
6 | //taken from http://stackoverflow.com/questions/5499078/fastest-method-to-escape-html-tags-as-html-entities
7 | //cast to string first, to avoid problems with e.g. integers
8 | return ("" + unescaped).replace(/&/g, "&").replace(//g, ">");
9 | },
10 | uriToPrefixed: function(prefixes, uri) {
11 | if (prefixes) {
12 | for (var prefix in prefixes) {
13 | if (uri.indexOf(prefixes[prefix]) == 0) {
14 | uri = prefix + ":" + uri.substring(prefixes[prefix].length);
15 | break;
16 | }
17 | }
18 | }
19 | return uri;
20 | },
21 | getGoogleTypeForBinding: function(binding) {
22 | if (binding == null) return null;
23 | if (binding.type != null && (binding.type === "typed-literal" || binding.type === "literal")) {
24 | switch (binding.datatype) {
25 | case "http://www.w3.org/2001/XMLSchema#double":
26 | case "http://www.w3.org/2001/XMLSchema#float":
27 | case "http://www.w3.org/2001/XMLSchema#decimal":
28 | case "http://www.w3.org/2001/XMLSchema#int":
29 | case "http://www.w3.org/2001/XMLSchema#integer":
30 | case "http://www.w3.org/2001/XMLSchema#long":
31 | case "http://www.w3.org/2001/XMLSchema#gYearMonth":
32 | case "http://www.w3.org/2001/XMLSchema#gYear":
33 | case "http://www.w3.org/2001/XMLSchema#gMonthDay":
34 | case "http://www.w3.org/2001/XMLSchema#gDay":
35 | case "http://www.w3.org/2001/XMLSchema#gMonth":
36 | return "number";
37 | case "http://www.w3.org/2001/XMLSchema#date":
38 | return "date";
39 | case "http://www.w3.org/2001/XMLSchema#dateTime":
40 | return "datetime";
41 | case "http://www.w3.org/2001/XMLSchema#time":
42 | return "timeofday";
43 | default:
44 | return "string";
45 | }
46 | } else {
47 | return "string";
48 | }
49 | },
50 | getGoogleTypeForBindings: function(bindings, varName) {
51 | var types = {};
52 | var typeCount = 0;
53 | bindings.forEach(function(binding) {
54 | var type = module.exports.getGoogleTypeForBinding(binding[varName]);
55 | if (type != null) {
56 | if (!(type in types)) {
57 | types[type] = 0;
58 | typeCount++;
59 | }
60 | types[type]++;
61 | }
62 | });
63 | if (typeCount == 0) {
64 | return "string";
65 | } else if (typeCount == 1) {
66 | for (var type in types) {
67 | return type; //just return this one
68 | }
69 | } else {
70 | //we have conflicting types. Throw error
71 | throw new GoogleTypeException(types, varName);
72 | }
73 | },
74 |
75 | castGoogleType: function(binding, prefixes, googleType) {
76 | if (binding == null) {
77 | return null;
78 | }
79 |
80 | if (
81 | googleType != "string" && binding.type != null && (binding.type === "typed-literal" || binding.type === "literal")
82 | ) {
83 | switch (binding.datatype) {
84 | case "http://www.w3.org/2001/XMLSchema#float":
85 | case "http://www.w3.org/2001/XMLSchema#decimal":
86 | case "http://www.w3.org/2001/XMLSchema#int":
87 | case "http://www.w3.org/2001/XMLSchema#integer":
88 | case "http://www.w3.org/2001/XMLSchema#long":
89 | case "http://www.w3.org/2001/XMLSchema#gYearMonth":
90 | case "http://www.w3.org/2001/XMLSchema#gYear":
91 | case "http://www.w3.org/2001/XMLSchema#gMonthDay":
92 | case "http://www.w3.org/2001/XMLSchema#gDay":
93 | case "http://www.w3.org/2001/XMLSchema#gMonth":
94 | return Number(binding.value);
95 | case "http://www.w3.org/2001/XMLSchema#double":
96 | return Number(parseFloat(binding.value));
97 | case "http://www.w3.org/2001/XMLSchema#date":
98 | //grrr, the date function does not parse -any- date (including most xsd dates!)
99 | //datetime and time seem to be fine though.
100 | //so, first try our custom parser. if that does not work, try the regular date parser anyway
101 | var date = parseXmlSchemaDate(binding.value);
102 | if (date) return date;
103 | case "http://www.w3.org/2001/XMLSchema#dateTime":
104 | case "http://www.w3.org/2001/XMLSchema#time":
105 | return new Date(binding.value);
106 | default:
107 | return binding.value;
108 | }
109 | } else {
110 | if (binding.type = "uri") {
111 | return module.exports.uriToPrefixed(prefixes, binding.value);
112 | } else {
113 | return binding.value;
114 | }
115 | }
116 | },
117 | fireClick: function($els) {
118 | if (!$els) return;
119 | $els.each(function(i, el) {
120 | var $el = $(el);
121 | if (document.dispatchEvent) {
122 | // W3C
123 | var oEvent = document.createEvent("MouseEvents");
124 | oEvent.initMouseEvent("click", true, true, window, 1, 1, 1, 1, 1, false, false, false, false, 0, $el[0]);
125 | $el[0].dispatchEvent(oEvent);
126 | } else if (document.fireEvent) {
127 | // IE
128 | $el[0].click();
129 | }
130 | });
131 | }
132 | };
133 | //There are no PROPER xml schema to js date parsers
134 | //A few libraries exist: moment, jsdate, Xdate, but none of them parse valid xml schema dates (e.g. 1999-11-05+02:00).
135 | //And: I'm not going to write one myself
136 | //There are other hacky solutions (regular expressions based on trial/error) such as http://stackoverflow.com/questions/2731579/convert-an-xml-schema-date-string-to-a-javascript-date
137 | //But if we're doing hacky stuff, I at least want to do it MYSELF!
138 | var parseXmlSchemaDate = function(dateString) {
139 | //change +02:00 to Z+02:00 (something which is parseable by js date)
140 | var date = new Date(dateString.replace(/(\d)([\+-]\d{2}:\d{2})/, "$1Z$2"));
141 | if (isNaN(date)) return null;
142 | return date;
143 | };
144 |
--------------------------------------------------------------------------------