diff --git a/ckan/public/base/datapreview/vendor/recline/css/recline.css b/ckan/public/base/datapreview/vendor/recline/css/recline.css index cc0c58e0047..6a7f23d7c9b 100644 --- a/ckan/public/base/datapreview/vendor/recline/css/recline.css +++ b/ckan/public/base/datapreview/vendor/recline/css/recline.css @@ -17,7 +17,24 @@ margin: auto; } -/********************************************************** +.flotr-mouse-value { + background-color: #FEE !important; + color: #000000 !important; + opacity: 0.8 !important; + border: 1px solid #fdd !important; +} + +.flotr-legend { + border: none !important; +} + +.flotr-legend-bg { + display: none; +} + +.flotr-legend-color-box { + padding: 5px; +}/********************************************************** * (Data) Grid *********************************************************/ diff --git a/ckan/public/base/datapreview/vendor/recline/recline.js b/ckan/public/base/datapreview/vendor/recline/recline.js index f863649826d..2a1c5071439 100644 --- a/ckan/public/base/datapreview/vendor/recline/recline.js +++ b/ckan/public/base/datapreview/vendor/recline/recline.js @@ -159,8 +159,14 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; // // @param {String} s The string to convert // @param {Object} options Options for loading CSV including - // @param {Boolean} [trim=false] If set to True leading and trailing whitespace is stripped off of each non-quoted field as it is imported - // @param {String} [separator=','] Separator for CSV file + // @param {Boolean} [trim=false] If set to True leading and trailing + // whitespace is stripped off of each non-quoted field as it is imported + // @param {String} [delimiter=','] A one-character string used to separate + // fields. It defaults to ',' + // @param {String} [quotechar='"'] A one-character string used to quote + // fields containing special characters, such as the delimiter or + // quotechar, or which contain new-line characters. It defaults to '"' + // // Heavily based on uselesscode's JS CSV parser (MIT Licensed): // http://www.uselesscode.org/javascript/csv/ my.parseCSV= function(s, options) { @@ -169,8 +175,8 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; var options = options || {}; var trm = (options.trim === false) ? false : true; - var separator = options.separator || ','; - var delimiter = options.delimiter || '"'; + var delimiter = options.delimiter || ','; + var quotechar = options.quotechar || '"'; var cur = '', // The character we are currently processing. inQuote = false, @@ -205,7 +211,7 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; cur = s.charAt(i); // If we are at a EOF or EOR - if (inQuote === false && (cur === separator || cur === "\n")) { + if (inQuote === false && (cur === delimiter || cur === "\n")) { field = processField(field); // Add the current field to the current row row.push(field); @@ -218,8 +224,8 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; field = ''; fieldQuoted = false; } else { - // If it's not a delimiter, add it to the field buffer - if (cur !== delimiter) { + // If it's not a quotechar, add it to the field buffer + if (cur !== quotechar) { field += cur; } else { if (!inQuote) { @@ -227,9 +233,9 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; inQuote = true; fieldQuoted = true; } else { - // Next char is delimiter, this is an escaped delimiter - if (s.charAt(i + 1) === delimiter) { - field += delimiter; + // Next char is quotechar, this is an escaped quotechar + if (s.charAt(i + 1) === quotechar) { + field += quotechar; // Skip the next char i += 1; } else { @@ -249,23 +255,48 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; return out; }; - // Converts an array of arrays into a Comma Separated Values string. - // Each array becomes a line in the CSV. + // ### serializeCSV + // + // Convert an Object or a simple array of arrays into a Comma + // Separated Values string. // // Nulls are converted to empty fields and integers or floats are converted to non-quoted numbers. // // @return The array serialized as a CSV // @type String // - // @param {Array} a The array of arrays to convert - // @param {Object} options Options for loading CSV including - // @param {String} [separator=','] Separator for CSV file - // Heavily based on uselesscode's JS CSV parser (MIT Licensed): + // @param {Object or Array} dataToSerialize The Object or array of arrays to convert. Object structure must be as follows: + // + // { + // fields: [ {id: .., ...}, {id: ..., + // records: [ { record }, { record }, ... ] + // ... // more attributes we do not care about + // } + // + // @param {object} options Options for serializing the CSV file including + // delimiter and quotechar (see parseCSV options parameter above for + // details on these). + // + // Heavily based on uselesscode's JS CSV serializer (MIT Licensed): // http://www.uselesscode.org/javascript/csv/ - my.serializeCSV= function(a, options) { + my.serializeCSV= function(dataToSerialize, options) { + var a = null; + if (dataToSerialize instanceof Array) { + a = dataToSerialize; + } else { + a = []; + var fieldNames = _.pluck(dataToSerialize.fields, 'id'); + a.push(fieldNames); + _.each(dataToSerialize.records, function(record, index) { + var tmp = _.map(fieldNames, function(fn) { + return record[fn]; + }); + a.push(tmp); + }); + } var options = options || {}; - var separator = options.separator || ','; - var delimiter = options.delimiter || '"'; + var delimiter = options.delimiter || ','; + var quotechar = options.quotechar || '"'; var cur = '', // The character we are currently processing. field = '', // Buffer for building up the current field @@ -281,7 +312,7 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; field = ''; } else if (typeof field === "string" && rxNeedsQuoting.test(field)) { // Convert string to delimited string - field = delimiter + field + delimiter; + field = quotechar + field + quotechar; } else if (typeof field === "number") { // Convert number to string field = field.toString(10); @@ -302,7 +333,7 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; row = ''; } else { // Add the current field to the current row - row += field + separator; + row += field + delimiter; } // Flush the field buffer field = ''; @@ -1001,20 +1032,23 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {}; this._applyFreeTextQuery = function(results, queryObj) { if (queryObj.q) { var terms = queryObj.q.split(' '); + var patterns=_.map(terms, function(term) { + return new RegExp(term.toLowerCase());; + }); results = _.filter(results, function(rawdoc) { var matches = true; - _.each(terms, function(term) { + _.each(patterns, function(pattern) { var foundmatch = false; _.each(self.fields, function(field) { var value = rawdoc[field.id]; - if (value !== null) { + if ((value !== null) && (value !== undefined)) { value = value.toString(); } else { // value can be null (apparently in some cases) value = ''; } // TODO regexes? - foundmatch = foundmatch || (value.toLowerCase() === term.toLowerCase()); + foundmatch = foundmatch || (pattern.test(value.toLowerCase())); // TODO: early out (once we are true should break to spare unnecessary testing) // if (foundmatch) return true; }); @@ -1848,26 +1882,27 @@ my.Graph = Backbone.View.extend({ return getFormattedX(x); }; + // infoboxes on mouse hover on points/bars etc var trackFormatter = function (obj) { - var x = obj.x; - var y = obj.y; - // it's horizontal so we have to flip - if (self.state.attributes.graphType === 'bars') { - var _tmp = x; - x = y; - y = _tmp; - } - - x = getFormattedX(x); - - var content = _.template('<%= group %> = <%= x %>, <%= series %> = <%= y %>', { - group: self.state.attributes.group, - x: x, - series: obj.series.label, - y: y - }); - - return content; + var x = obj.x; + var y = obj.y; + // it's horizontal so we have to flip + if (self.state.attributes.graphType === 'bars') { + var _tmp = x; + x = y; + y = _tmp; + } + + x = getFormattedX(x); + + var content = _.template('<%= group %> = <%= x %>, <%= series %> = <%= y %>', { + group: self.state.attributes.group, + x: x, + series: obj.series.label, + y: y + }); + + return content; }; var getFormattedX = function (x) { @@ -1938,18 +1973,18 @@ my.Graph = Backbone.View.extend({ xaxis: yaxis, yaxis: xaxis, mouse: { - track: true, - relative: true, - trackFormatter: trackFormatter, - fillColor: '#FFFFFF', - fillOpacity: 0.3, - position: 'e' + track: true, + relative: true, + trackFormatter: trackFormatter, + fillColor: '#FFFFFF', + fillOpacity: 0.3, + position: 'e' }, bars: { - show: true, - horizontal: true, - shadowSize: 0, - barWidth: 0.8 + show: true, + horizontal: true, + shadowSize: 0, + barWidth: 0.8 }, }, columns: { @@ -2470,6 +2505,11 @@ this.recline.View = this.recline.View || {}; // latField: {id of field containing latitude in the dataset} // } // +// +// Useful attributes to know about (if e.g. customizing) +// +// * map: the Leaflet map (L.Map) +// * features: Leaflet GeoJSON layer containing all the features (L.GeoJSON) my.Map = Backbone.View.extend({ template: ' \