Merge branch 'master' into gh-pages
This commit is contained in:
commit
d4a0ea6093
4
.travis.yml
Normal file
4
.travis.yml
Normal file
@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
script: phantomjs test/qunit/runner.js test/index.html
|
||||
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2011 Max Ogden & Contributors
|
||||
Copyright (c) 2011-2014 Max Ogden, Rufus Pollock and Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
[](https://travis-ci.org/okfn/recline)
|
||||
|
||||
A simple but powerful library for building data applications in pure Javascript and HTML.
|
||||
|
||||
<h3><a href="http://okfnlabs.org/recline/">Recline Website - including Overview, Documentation, Demos etc</a></h3>
|
||||
@ -35,12 +37,15 @@ See CONTRIBUTING.md.
|
||||
|
||||
Possible breaking changes
|
||||
|
||||
* Many backends moved to their own repositories #314
|
||||
* Updated Leaflet to latest version 0.4.4 #220
|
||||
* Added marker clustering in map view to handle a large number of markers
|
||||
* Dataset.restore method removed (not used internally except from Multiview.restore)
|
||||
* Views no longer call render in initialize but must be called client code
|
||||
* Backend.Memory.Store attribute for holding 'records' renamed to `records` from `data`
|
||||
* Require new underscore.deferred vendor library for all use (jQuery no longer required if just using recline.dataset.js)
|
||||
* View.el is now the raw DOM element. If you want a jQuery-wrapped version, use view.$el. #350
|
||||
* Upgraded timelinejs lib - #316
|
||||
|
||||
### v0.5 - July 5th 2012 (first public release)
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<li><a href="https://github.com/okfn/recline.backend.gdocs">gdocs: Google Docs (Spreadsheet)</a></li>
|
||||
<li><a href="{{page.root}}/docs/src/backend.csv.html">csv: CSV files</a></li>
|
||||
<li><a href="https://github.com/okfn/recline.backend.solr">solr: SOLR</a> (partial)</li>
|
||||
<li><a href="{{page.root}}/docs/src/backend.elasticsearch.html">elasticsearch: ElasticSearch</a></li>
|
||||
<li><a href="https://github.com/okfn/elasticsearch.js">elasticsearch: ElasticSearch</a></li>
|
||||
<li><a href="{{page.root}}/docs/src/backend.dataproxy.html">dataproxy: DataProxy (CSV and XLS on the Web)</a></li>
|
||||
<li><a href="https://github.com/okfn/recline.backend.ckan">ckan: CKAN</a> – support for <a href="http://docs.ckan.org/en/latest/datastore.html">CKAN datastore</a></li>
|
||||
<li><a href="https://github.com/okfn/recline.backend.couchdb">couchdb: CouchDB</a></li>
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
var dataset = new recline.Model.Dataset({
|
||||
url: 'http://datahub.io/dataset/rendition-on-record/ac5a28ea-eb52-4b0a-a399-5dcc1becf9d9/api',
|
||||
backend: 'elasticsearch'
|
||||
});
|
||||
|
||||
dataset.fetch();
|
||||
|
||||
// For demonstrations purposes display the data in a grid
|
||||
var grid = new recline.View.SlickGrid({
|
||||
model: dataset
|
||||
});
|
||||
$('#my-elasticsearch').append(grid.el);
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/leaflet.markercluster/MarkerCluster.Default.ie.css" />
|
||||
<![endif]-->
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/slickgrid/2.0.1/slick.grid.css">
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/timeline/20120520/css/timeline.css">
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/timeline/css/timeline.css">
|
||||
|
||||
<!-- Recline CSS components -->
|
||||
<link rel="stylesheet" href="{{page.root}}css/grid.css">
|
||||
@ -21,21 +21,22 @@
|
||||
|
||||
<!-- 3rd party JS libraries -->
|
||||
<script type="text/javascript" src="{{page.root}}vendor/jquery/1.7.1/jquery.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/underscore/1.4.2/underscore.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/backbone/0.9.2/backbone.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/underscore/1.4.4/underscore.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/backbone/1.0.0/backbone.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/mustache/0.5.0-dev/mustache.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/bootstrap/2.0.2/bootstrap.js"></script>
|
||||
<!--[if lte IE 8]>
|
||||
<script language="javascript" type="text/javascript" src="{{page.root}}vendor/flot/excanvas.min.js"></script>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" src="{{page.root}}vendor/flot/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/flot/jquery.flot.time.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/leaflet/0.4.4/leaflet.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/leaflet.markercluster/leaflet.markercluster.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/slickgrid/2.0.1/jquery-ui-1.8.16.custom.min.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/slickgrid/2.0.1/jquery.event.drag-2.0.min.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/slickgrid/2.0.1/slick.grid.min.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/moment/1.6.2/moment.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/timeline/20120520/js/timeline.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/moment/2.0.0/moment.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/timeline/js/timeline.js"></script>
|
||||
<!--[if lte IE 7]>
|
||||
<script language="javascript" type="text/javascript" src="{{page.root}}vendor/json/json2.js"></script>
|
||||
<![endif]-->
|
||||
@ -52,8 +53,7 @@
|
||||
<script type="text/javascript" src="{{page.root}}src/model.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}src/backend.memory.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}src/backend.dataproxy.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}src/backend.gdocs.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}src/backend.elasticsearch.js"></script>
|
||||
<script type="text/javascript" src="http://okfnlabs.org/recline.backend.gdocs/backend.gdocs.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}src/backend.csv.js"></script>
|
||||
|
||||
<!-- views -->
|
||||
|
||||
@ -73,7 +73,18 @@ var createExplorer = function(dataset, state) {
|
||||
id: 'grid',
|
||||
label: 'Grid',
|
||||
view: new recline.View.SlickGrid({
|
||||
model: dataset
|
||||
model: dataset,
|
||||
state: {
|
||||
gridOptions: {
|
||||
editable: true,
|
||||
enabledAddRow: true,
|
||||
enableCellNavigation: true
|
||||
},
|
||||
columnsEditor: [
|
||||
{ column: 'date', editor: Slick.Editors.Date },
|
||||
{ column: 'title', editor: Slick.Editors.Text }
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
@ -81,6 +92,7 @@ var createExplorer = function(dataset, state) {
|
||||
label: 'Graph',
|
||||
view: new recline.View.Graph({
|
||||
model: dataset
|
||||
|
||||
})
|
||||
},
|
||||
{
|
||||
|
||||
36
dist/recline.dataset.js
vendored
36
dist/recline.dataset.js
vendored
@ -3,9 +3,10 @@ this.recline = this.recline || {};
|
||||
this.recline.Model = this.recline.Model || {};
|
||||
|
||||
(function(my) {
|
||||
"use strict";
|
||||
|
||||
// use either jQuery or Underscore Deferred depending on what is available
|
||||
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
|
||||
var Deferred = (typeof jQuery !== "undefined" && jQuery.Deferred) || _.Deferred;
|
||||
|
||||
// ## <a id="dataset">Dataset</a>
|
||||
my.Dataset = Backbone.Model.extend({
|
||||
@ -15,6 +16,7 @@ my.Dataset = Backbone.Model.extend({
|
||||
|
||||
// ### initialize
|
||||
initialize: function() {
|
||||
var self = this;
|
||||
_.bindAll(this, 'query');
|
||||
this.backend = null;
|
||||
if (this.get('backend')) {
|
||||
@ -34,8 +36,9 @@ my.Dataset = Backbone.Model.extend({
|
||||
this.facets = new my.FacetList();
|
||||
this.recordCount = null;
|
||||
this.queryState = new my.Query();
|
||||
this.queryState.bind('change', this.query);
|
||||
this.queryState.bind('facet:add', this.query);
|
||||
this.queryState.bind('change facet:add', function () {
|
||||
self.query(); // We want to call query() without any arguments.
|
||||
});
|
||||
// store is what we query and save against
|
||||
// store will either be the backend or be a memory store if Backend fetch
|
||||
// tells us to use memory store
|
||||
@ -68,7 +71,13 @@ my.Dataset = Backbone.Model.extend({
|
||||
}
|
||||
|
||||
function handleResults(results) {
|
||||
var out = self._normalizeRecordsAndFields(results.records, results.fields);
|
||||
// if explicitly given the fields
|
||||
// (e.g. var dataset = new Dataset({fields: fields, ...})
|
||||
// use that field info over anything we get back by parsing the data
|
||||
// (results.fields)
|
||||
var fields = self.get('fields') || results.fields;
|
||||
|
||||
var out = self._normalizeRecordsAndFields(results.records, fields);
|
||||
if (results.useMemoryStore) {
|
||||
self._store = new recline.Backend.Memory.Store(out.records, out.fields);
|
||||
}
|
||||
@ -298,7 +307,7 @@ my.Record = Backbone.Model.extend({
|
||||
//
|
||||
// NB: if field is undefined a default '' value will be returned
|
||||
getFieldValue: function(field) {
|
||||
val = this.getFieldValueUnrendered(field);
|
||||
var val = this.getFieldValueUnrendered(field);
|
||||
if (field && !_.isUndefined(field.renderer)) {
|
||||
val = field.renderer(val, field, this.toJSON());
|
||||
}
|
||||
@ -588,10 +597,11 @@ this.recline.Backend = this.recline.Backend || {};
|
||||
this.recline.Backend.Memory = this.recline.Backend.Memory || {};
|
||||
|
||||
(function(my) {
|
||||
"use strict";
|
||||
my.__type__ = 'memory';
|
||||
|
||||
// private data - use either jQuery or Underscore Deferred depending on what is available
|
||||
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
|
||||
var Deferred = (typeof jQuery !== "undefined" && jQuery.Deferred) || _.Deferred;
|
||||
|
||||
// ## Data Wrapper
|
||||
//
|
||||
@ -692,9 +702,9 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
|
||||
integer: function (e) { return parseFloat(e, 10); },
|
||||
'float': function (e) { return parseFloat(e, 10); },
|
||||
number: function (e) { return parseFloat(e, 10); },
|
||||
string : function (e) { return e.toString() },
|
||||
date : function (e) { return new Date(e).valueOf() },
|
||||
datetime : function (e) { return new Date(e).valueOf() }
|
||||
string : function (e) { return e.toString(); },
|
||||
date : function (e) { return moment(e).valueOf(); },
|
||||
datetime : function (e) { return new Date(e).valueOf(); }
|
||||
};
|
||||
var keyedFields = {};
|
||||
_.each(self.fields, function(field) {
|
||||
@ -725,8 +735,8 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
|
||||
}
|
||||
|
||||
function range(record, filter) {
|
||||
var startnull = (filter.start == null || filter.start === '');
|
||||
var stopnull = (filter.stop == null || filter.stop === '');
|
||||
var startnull = (filter.start === null || filter.start === '');
|
||||
var stopnull = (filter.stop === null || filter.stop === '');
|
||||
var parse = getDataParser(filter);
|
||||
var value = parse(record[filter.field]);
|
||||
var start = parse(filter.start);
|
||||
@ -750,8 +760,8 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
|
||||
if (queryObj.q) {
|
||||
var terms = queryObj.q.split(' ');
|
||||
var patterns=_.map(terms, function(term) {
|
||||
return new RegExp(term.toLowerCase());;
|
||||
});
|
||||
return new RegExp(term.toLowerCase());
|
||||
});
|
||||
results = _.filter(results, function(rawdoc) {
|
||||
var matches = true;
|
||||
_.each(patterns, function(pattern) {
|
||||
|
||||
1044
dist/recline.js
vendored
1044
dist/recline.js
vendored
File diff suppressed because it is too large
Load Diff
@ -76,8 +76,8 @@ much more limited if you are just using a Backend. Specifically:
|
||||
<script type="text/javascript" src="vendor/jquery/1.7.1/jquery.js"></script>
|
||||
<script type="text/javascript" src="vendor/underscore/1.1.6/underscore.js"></script>
|
||||
<script type="text/javascript" src="vendor/backbone/0.5.1/backbone.js"></script>
|
||||
<!-- include the backend code you need e.g. here for gdocs -->
|
||||
<script type="text/javascript" src="src/backend.gdocs.js"></script>
|
||||
<!-- include the backend code you need e.g. here for csv -->
|
||||
<script type="text/javascript" src="src/backend.csv.js"></script>
|
||||
|
||||
<!-- Or you can just include all of recline. -->
|
||||
<script type="text/javascript" src="dist/recline.js"></script>
|
||||
@ -99,6 +99,8 @@ a bespoke chooser and a Kartograph (svg-only) map.
|
||||
</div>
|
||||
|
||||
{% highlight javascript %}
|
||||
// include the Recline backend for Google Docs
|
||||
<script type="text/javascript" src="http://okfnlabs.org/recline.backend.gdocs/backend.gdocs.js"></script>
|
||||
{% include example-backends-gdocs.js %}
|
||||
{% endhighlight %}
|
||||
|
||||
@ -106,26 +108,19 @@ a bespoke chooser and a Kartograph (svg-only) map.
|
||||
|
||||
<div id="my-gdocs" class="doc-ex-rendered"> </div>
|
||||
|
||||
<script type="text/javascript" src="http://okfnlabs.org/recline.backend.gdocs/backend.gdocs.js"> </script>
|
||||
|
||||
<script type="text/javascript">
|
||||
{% include example-backends-gdocs.js %}
|
||||
</script>
|
||||
|
||||
|
||||
## Loading Data from ElasticSearch and the DataHub
|
||||
## Loading Data from ElasticSearch
|
||||
|
||||
Recline supports ElasticSearch as a full read/write/query backend. It also means that Recline can load data from the [DataHub's](http://datahub.io/) data API as that is ElasticSearch compatible. Here's an example, using [this dataset about Rendition flights](http://datahub.io/dataset/rendition-on-record/ac5a28ea-eb52-4b0a-a399-5dcc1becf9d9') on the DataHub:
|
||||
Recline supports ElasticSearch as a full read/write/query backend via the
|
||||
[ElasticSearch.js library][esjs]. See the library for examples.
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include example-backends-elasticsearch.js %}
|
||||
{% endhighlight %}
|
||||
|
||||
### Result
|
||||
|
||||
<div id="my-elasticsearch" class="doc-ex-rendered"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
{% include example-backends-elasticsearch.js %}
|
||||
</script>
|
||||
[esjs]: https://github.com/okfn/elasticsearch.js
|
||||
|
||||
|
||||
## Loading data from CSV files
|
||||
|
||||
@ -102,3 +102,30 @@ view.featureparse = function (e) {
|
||||
};
|
||||
{% endhighlight %}
|
||||
|
||||
|
||||
### Turning on clustering
|
||||
|
||||
You can turn on clustering of markers by setting the cluster option:
|
||||
|
||||
var map = new recline.View.Map({
|
||||
model: dataset
|
||||
state: {
|
||||
cluster: true;
|
||||
}
|
||||
});
|
||||
|
||||
You could also enable marker clustering only if you have more than a
|
||||
certain number of markers. Here's an example:
|
||||
|
||||
// var map is recline.View.Map instance
|
||||
// marker cluster threshold
|
||||
var threshold = 65;
|
||||
|
||||
// enable clustering if there is a large number of markers
|
||||
var countAfter = 0;
|
||||
map.features.eachLayer(function(){countAfter++;});
|
||||
if (countAfter > threshold) {
|
||||
// note the map will auto-redraw when you change state!
|
||||
map.state.set({cluster: true});
|
||||
}
|
||||
|
||||
|
||||
@ -130,6 +130,7 @@ library and the Recline Flot Graph view:
|
||||
<script language="javascript" type="text/javascript" src="vendor/flot/excanvas.min.js"></script>
|
||||
<![endif]-->
|
||||
<script type="text/javascript" src="vendor/flot/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="vendor/flot/jquery.flot.time.js"></script>
|
||||
<script type="text/javascript" src="src/view.graph.js"></script>
|
||||
{% endhighlight %}
|
||||
|
||||
@ -247,11 +248,11 @@ First, add the additional dependencies for the timeline view. The timeline is bu
|
||||
|
||||
{% highlight html %}
|
||||
<!-- css -->
|
||||
<link rel="stylesheet" href="vendor/timeline/20120520/css/timeline.css">
|
||||
<link rel="stylesheet" href="vendor/timeline/css/timeline.css">
|
||||
|
||||
<!-- javascript -->
|
||||
<script type="text/javascript" src="vendor/moment/1.6.2/moment.js"></script>
|
||||
<script type="text/javascript" src="vendor/timeline/20120520/js/timeline.js"></script>
|
||||
<script type="text/javascript" src="vendor/moment/2.0.0/moment.js"></script>
|
||||
<script type="text/javascript" src="vendor/timeline/js/timeline.js"></script>
|
||||
{% endhighlight %}
|
||||
|
||||
Now, create a new div for the map (must have an explicit height for the timeline to render):
|
||||
|
||||
@ -4,10 +4,11 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {};
|
||||
|
||||
// Note that provision of jQuery is optional (it is **only** needed if you use fetch on a remote file)
|
||||
(function(my) {
|
||||
"use strict";
|
||||
my.__type__ = 'csv';
|
||||
|
||||
// use either jQuery or Underscore Deferred depending on what is available
|
||||
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
|
||||
var Deferred = (typeof jQuery !== "undefined" && jQuery.Deferred) || _.Deferred;
|
||||
|
||||
// ## fetch
|
||||
//
|
||||
@ -32,37 +33,46 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {};
|
||||
var reader = new FileReader();
|
||||
var encoding = dataset.encoding || 'UTF-8';
|
||||
reader.onload = function(e) {
|
||||
var rows = my.parseCSV(e.target.result, dataset);
|
||||
dfd.resolve({
|
||||
records: rows,
|
||||
metadata: {
|
||||
filename: dataset.file.name
|
||||
},
|
||||
useMemoryStore: true
|
||||
});
|
||||
var out = my.extractFields(my.parseCSV(e.target.result, dataset), dataset);
|
||||
out.useMemoryStore = true;
|
||||
out.metadata = {
|
||||
filename: dataset.file.name
|
||||
}
|
||||
dfd.resolve(out);
|
||||
};
|
||||
reader.onerror = function (e) {
|
||||
alert('Failed to load file. Code: ' + e.target.error.code);
|
||||
};
|
||||
reader.readAsText(dataset.file, encoding);
|
||||
} else if (dataset.data) {
|
||||
var rows = my.parseCSV(dataset.data, dataset);
|
||||
dfd.resolve({
|
||||
records: rows,
|
||||
useMemoryStore: true
|
||||
});
|
||||
var out = my.extractFields(my.parseCSV(dataset.data, dataset), dataset);
|
||||
out.useMemoryStore = true;
|
||||
dfd.resolve(out);
|
||||
} else if (dataset.url) {
|
||||
jQuery.get(dataset.url).done(function(data) {
|
||||
var rows = my.parseCSV(data, dataset);
|
||||
dfd.resolve({
|
||||
records: rows,
|
||||
useMemoryStore: true
|
||||
});
|
||||
var out = my.extractFields(my.parseCSV(data, dataset), dataset);
|
||||
out.useMemoryStore = true;
|
||||
dfd.resolve(out);
|
||||
});
|
||||
}
|
||||
return dfd.promise();
|
||||
};
|
||||
|
||||
// Convert array of rows in { records: [ ...] , fields: [ ... ] }
|
||||
// @param {Boolean} noHeaderRow If true assume that first row is not a header (i.e. list of fields but is data.
|
||||
my.extractFields = function(rows, noFields) {
|
||||
if (noFields.noHeaderRow !== true && rows.length > 0) {
|
||||
return {
|
||||
fields: rows[0],
|
||||
records: rows.slice(1)
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
records: rows
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ## parseCSV
|
||||
//
|
||||
// Converts a Comma Separated Values string into an array of arrays.
|
||||
@ -83,6 +93,8 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {};
|
||||
// fields containing special characters, such as the delimiter or
|
||||
// quotechar, or which contain new-line characters. It defaults to '"'
|
||||
//
|
||||
// @param {Integer} skipInitialRows A integer number of rows to skip (default 0)
|
||||
//
|
||||
// Heavily based on uselesscode's JS CSV parser (MIT Licensed):
|
||||
// http://www.uselesscode.org/javascript/csv/
|
||||
my.parseCSV= function(s, options) {
|
||||
@ -128,7 +140,7 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {};
|
||||
|
||||
// If we are at a EOF or EOR
|
||||
if (inQuote === false && (cur === delimiter || cur === "\n")) {
|
||||
field = processField(field);
|
||||
field = processField(field);
|
||||
// Add the current field to the current row
|
||||
row.push(field);
|
||||
// If this is EOR append row to output and flush row
|
||||
@ -168,6 +180,9 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {};
|
||||
row.push(field);
|
||||
out.push(row);
|
||||
|
||||
// Expose the ability to discard initial rows
|
||||
if (options.skipInitialRows) out = out.slice(options.skipInitialRows);
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ this.recline.Backend = this.recline.Backend || {};
|
||||
this.recline.Backend.DataProxy = this.recline.Backend.DataProxy || {};
|
||||
|
||||
(function(my) {
|
||||
"use strict";
|
||||
my.__type__ = 'dataproxy';
|
||||
// URL for the dataproxy
|
||||
my.dataproxy_url = '//jsonpdataproxy.appspot.com';
|
||||
@ -12,7 +13,7 @@ this.recline.Backend.DataProxy = this.recline.Backend.DataProxy || {};
|
||||
|
||||
|
||||
// use either jQuery or Underscore Deferred depending on what is available
|
||||
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
|
||||
var Deferred = (typeof jQuery !== "undefined" && jQuery.Deferred) || _.Deferred;
|
||||
|
||||
// ## load
|
||||
//
|
||||
|
||||
@ -1,285 +0,0 @@
|
||||
this.recline = this.recline || {};
|
||||
this.recline.Backend = this.recline.Backend || {};
|
||||
this.recline.Backend.ElasticSearch = this.recline.Backend.ElasticSearch || {};
|
||||
|
||||
(function($, my) {
|
||||
my.__type__ = 'elasticsearch';
|
||||
|
||||
// use either jQuery or Underscore Deferred depending on what is available
|
||||
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
|
||||
|
||||
// ## ElasticSearch Wrapper
|
||||
//
|
||||
// A simple JS wrapper around an [ElasticSearch](http://www.elasticsearch.org/) endpoints.
|
||||
//
|
||||
// @param {String} endpoint: url for ElasticSearch type/table, e.g. for ES running
|
||||
// on http://localhost:9200 with index twitter and type tweet it would be:
|
||||
//
|
||||
// <pre>http://localhost:9200/twitter/tweet</pre>
|
||||
//
|
||||
// @param {Object} options: set of options such as:
|
||||
//
|
||||
// * headers - {dict of headers to add to each request}
|
||||
// * dataType: dataType for AJAx requests e.g. set to jsonp to make jsonp requests (default is json requests)
|
||||
my.Wrapper = function(endpoint, options) {
|
||||
var self = this;
|
||||
this.endpoint = endpoint;
|
||||
this.options = _.extend({
|
||||
dataType: 'json'
|
||||
},
|
||||
options);
|
||||
|
||||
// ### mapping
|
||||
//
|
||||
// Get ES mapping for this type/table
|
||||
//
|
||||
// @return promise compatible deferred object.
|
||||
this.mapping = function() {
|
||||
var schemaUrl = self.endpoint + '/_mapping';
|
||||
var jqxhr = makeRequest({
|
||||
url: schemaUrl,
|
||||
dataType: this.options.dataType
|
||||
});
|
||||
return jqxhr;
|
||||
};
|
||||
|
||||
// ### get
|
||||
//
|
||||
// Get record corresponding to specified id
|
||||
//
|
||||
// @return promise compatible deferred object.
|
||||
this.get = function(id) {
|
||||
var base = this.endpoint + '/' + id;
|
||||
return makeRequest({
|
||||
url: base,
|
||||
dataType: 'json'
|
||||
});
|
||||
};
|
||||
|
||||
// ### upsert
|
||||
//
|
||||
// create / update a record to ElasticSearch backend
|
||||
//
|
||||
// @param {Object} doc an object to insert to the index.
|
||||
// @return deferred supporting promise API
|
||||
this.upsert = function(doc) {
|
||||
var data = JSON.stringify(doc);
|
||||
url = this.endpoint;
|
||||
if (doc.id) {
|
||||
url += '/' + doc.id;
|
||||
}
|
||||
return makeRequest({
|
||||
url: url,
|
||||
type: 'POST',
|
||||
data: data,
|
||||
dataType: 'json'
|
||||
});
|
||||
};
|
||||
|
||||
// ### delete
|
||||
//
|
||||
// Delete a record from the ElasticSearch backend.
|
||||
//
|
||||
// @param {Object} id id of object to delete
|
||||
// @return deferred supporting promise API
|
||||
this.remove = function(id) {
|
||||
url = this.endpoint;
|
||||
url += '/' + id;
|
||||
return makeRequest({
|
||||
url: url,
|
||||
type: 'DELETE',
|
||||
dataType: 'json'
|
||||
});
|
||||
};
|
||||
|
||||
this._normalizeQuery = function(queryObj) {
|
||||
var self = this;
|
||||
var queryInfo = (queryObj && queryObj.toJSON) ? queryObj.toJSON() : _.extend({}, queryObj);
|
||||
var out = {
|
||||
constant_score: {
|
||||
query: {}
|
||||
}
|
||||
};
|
||||
if (!queryInfo.q) {
|
||||
out.constant_score.query = {
|
||||
match_all: {}
|
||||
};
|
||||
} else {
|
||||
out.constant_score.query = {
|
||||
query_string: {
|
||||
query: queryInfo.q
|
||||
}
|
||||
};
|
||||
}
|
||||
if (queryInfo.filters && queryInfo.filters.length) {
|
||||
out.constant_score.filter = {
|
||||
and: []
|
||||
};
|
||||
_.each(queryInfo.filters, function(filter) {
|
||||
out.constant_score.filter.and.push(self._convertFilter(filter));
|
||||
});
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
// convert from Recline sort structure to ES form
|
||||
// http://www.elasticsearch.org/guide/reference/api/search/sort.html
|
||||
this._normalizeSort = function(sort) {
|
||||
var out = _.map(sort, function(sortObj) {
|
||||
var _tmp = {};
|
||||
var _tmp2 = _.clone(sortObj);
|
||||
delete _tmp2['field'];
|
||||
_tmp[sortObj.field] = _tmp2;
|
||||
return _tmp;
|
||||
});
|
||||
return out;
|
||||
},
|
||||
|
||||
this._convertFilter = function(filter) {
|
||||
var out = {};
|
||||
out[filter.type] = {}
|
||||
if (filter.type === 'term') {
|
||||
out.term[filter.field] = filter.term.toLowerCase();
|
||||
} else if (filter.type === 'geo_distance') {
|
||||
out.geo_distance[filter.field] = filter.point;
|
||||
out.geo_distance.distance = filter.distance;
|
||||
out.geo_distance.unit = filter.unit;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
// ### query
|
||||
//
|
||||
// @return deferred supporting promise API
|
||||
this.query = function(queryObj) {
|
||||
var esQuery = (queryObj && queryObj.toJSON) ? queryObj.toJSON() : _.extend({}, queryObj);
|
||||
esQuery.query = this._normalizeQuery(queryObj);
|
||||
delete esQuery.q;
|
||||
delete esQuery.filters;
|
||||
if (esQuery.sort && esQuery.sort.length > 0) {
|
||||
esQuery.sort = this._normalizeSort(esQuery.sort);
|
||||
}
|
||||
var data = {source: JSON.stringify(esQuery)};
|
||||
var url = this.endpoint + '/_search';
|
||||
var jqxhr = makeRequest({
|
||||
url: url,
|
||||
data: data,
|
||||
dataType: this.options.dataType
|
||||
});
|
||||
return jqxhr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ## Recline Connectors
|
||||
//
|
||||
// Requires URL of ElasticSearch endpoint to be specified on the dataset
|
||||
// via the url attribute.
|
||||
|
||||
// ES options which are passed through to `options` on Wrapper (see Wrapper for details)
|
||||
my.esOptions = {};
|
||||
|
||||
// ### fetch
|
||||
my.fetch = function(dataset) {
|
||||
var es = new my.Wrapper(dataset.url, my.esOptions);
|
||||
var dfd = new Deferred();
|
||||
es.mapping().done(function(schema) {
|
||||
|
||||
if (!schema){
|
||||
dfd.reject({'message':'Elastic Search did not return a mapping'});
|
||||
return;
|
||||
}
|
||||
|
||||
// only one top level key in ES = the type so we can ignore it
|
||||
var key = _.keys(schema)[0];
|
||||
var fieldData = _.map(schema[key].properties, function(dict, fieldName) {
|
||||
dict.id = fieldName;
|
||||
return dict;
|
||||
});
|
||||
dfd.resolve({
|
||||
fields: fieldData
|
||||
});
|
||||
})
|
||||
.fail(function(arguments) {
|
||||
dfd.reject(arguments);
|
||||
});
|
||||
return dfd.promise();
|
||||
};
|
||||
|
||||
// ### save
|
||||
my.save = function(changes, dataset) {
|
||||
var es = new my.Wrapper(dataset.url, my.esOptions);
|
||||
if (changes.creates.length + changes.updates.length + changes.deletes.length > 1) {
|
||||
var dfd = new Deferred();
|
||||
msg = 'Saving more than one item at a time not yet supported';
|
||||
alert(msg);
|
||||
dfd.reject(msg);
|
||||
return dfd.promise();
|
||||
}
|
||||
if (changes.creates.length > 0) {
|
||||
return es.upsert(changes.creates[0]);
|
||||
}
|
||||
else if (changes.updates.length >0) {
|
||||
return es.upsert(changes.updates[0]);
|
||||
} else if (changes.deletes.length > 0) {
|
||||
return es.remove(changes.deletes[0].id);
|
||||
}
|
||||
};
|
||||
|
||||
// ### query
|
||||
my.query = function(queryObj, dataset) {
|
||||
var dfd = new Deferred();
|
||||
var es = new my.Wrapper(dataset.url, my.esOptions);
|
||||
var jqxhr = es.query(queryObj);
|
||||
jqxhr.done(function(results) {
|
||||
var out = {
|
||||
total: results.hits.total
|
||||
};
|
||||
out.hits = _.map(results.hits.hits, function(hit) {
|
||||
if (!('id' in hit._source) && hit._id) {
|
||||
hit._source.id = hit._id;
|
||||
}
|
||||
return hit._source;
|
||||
});
|
||||
if (results.facets) {
|
||||
out.facets = results.facets;
|
||||
}
|
||||
dfd.resolve(out);
|
||||
}).fail(function(errorObj) {
|
||||
var out = {
|
||||
title: 'Failed: ' + errorObj.status + ' code',
|
||||
message: errorObj.responseText
|
||||
};
|
||||
dfd.reject(out);
|
||||
});
|
||||
return dfd.promise();
|
||||
};
|
||||
|
||||
|
||||
// ### makeRequest
|
||||
//
|
||||
// Just $.ajax but in any headers in the 'headers' attribute of this
|
||||
// Backend instance. Example:
|
||||
//
|
||||
// <pre>
|
||||
// var jqxhr = this._makeRequest({
|
||||
// url: the-url
|
||||
// });
|
||||
// </pre>
|
||||
var makeRequest = function(data, headers) {
|
||||
var extras = {};
|
||||
if (headers) {
|
||||
extras = {
|
||||
beforeSend: function(req) {
|
||||
_.each(headers, function(value, key) {
|
||||
req.setRequestHeader(key, value);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
var data = _.extend(extras, data);
|
||||
return $.ajax(data);
|
||||
};
|
||||
|
||||
}(jQuery, this.recline.Backend.ElasticSearch));
|
||||
|
||||
@ -1,167 +0,0 @@
|
||||
this.recline = this.recline || {};
|
||||
this.recline.Backend = this.recline.Backend || {};
|
||||
this.recline.Backend.GDocs = this.recline.Backend.GDocs || {};
|
||||
|
||||
(function(my) {
|
||||
my.__type__ = 'gdocs';
|
||||
|
||||
// use either jQuery or Underscore Deferred depending on what is available
|
||||
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
|
||||
|
||||
// ## Google spreadsheet backend
|
||||
//
|
||||
// Fetch data from a Google Docs spreadsheet.
|
||||
//
|
||||
// Dataset must have a url attribute pointing to the Gdocs or its JSON feed e.g.
|
||||
// <pre>
|
||||
// var dataset = new recline.Model.Dataset({
|
||||
// url: 'https://docs.google.com/spreadsheet/ccc?key=0Aon3JiuouxLUdGlQVDJnbjZRSU1tUUJWOUZXRG53VkE#gid=0'
|
||||
// },
|
||||
// 'gdocs'
|
||||
// );
|
||||
//
|
||||
// var dataset = new recline.Model.Dataset({
|
||||
// url: 'https://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values?alt=json'
|
||||
// },
|
||||
// 'gdocs'
|
||||
// );
|
||||
// </pre>
|
||||
//
|
||||
// @return object with two attributes
|
||||
//
|
||||
// * fields: array of Field objects
|
||||
// * records: array of objects for each row
|
||||
my.fetch = function(dataset) {
|
||||
var dfd = new Deferred();
|
||||
var urls = my.getGDocsAPIUrls(dataset.url);
|
||||
|
||||
// TODO cover it with tests
|
||||
// get the spreadsheet title
|
||||
(function () {
|
||||
var titleDfd = new Deferred();
|
||||
|
||||
jQuery.getJSON(urls.spreadsheet, function (d) {
|
||||
titleDfd.resolve({
|
||||
spreadsheetTitle: d.feed.title.$t
|
||||
});
|
||||
});
|
||||
|
||||
return titleDfd.promise();
|
||||
}()).then(function (response) {
|
||||
|
||||
// get the actual worksheet data
|
||||
jQuery.getJSON(urls.worksheet, function(d) {
|
||||
var result = my.parseData(d);
|
||||
var fields = _.map(result.fields, function(fieldId) {
|
||||
return {id: fieldId};
|
||||
});
|
||||
|
||||
dfd.resolve({
|
||||
metadata: {
|
||||
title: response.spreadsheetTitle +" :: "+ result.worksheetTitle,
|
||||
spreadsheetTitle: response.spreadsheetTitle,
|
||||
worksheetTitle : result.worksheetTitle
|
||||
},
|
||||
records : result.records,
|
||||
fields : fields,
|
||||
useMemoryStore: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return dfd.promise();
|
||||
};
|
||||
|
||||
// ## parseData
|
||||
//
|
||||
// Parse data from Google Docs API into a reasonable form
|
||||
//
|
||||
// :options: (optional) optional argument dictionary:
|
||||
// columnsToUse: list of columns to use (specified by field names)
|
||||
// colTypes: dictionary (with column names as keys) specifying types (e.g. range, percent for use in conversion).
|
||||
// :return: tabular data object (hash with keys: field and data).
|
||||
//
|
||||
// Issues: seems google docs return columns in rows in random order and not even sure whether consistent across rows.
|
||||
my.parseData = function(gdocsSpreadsheet, options) {
|
||||
var options = options || {};
|
||||
var colTypes = options.colTypes || {};
|
||||
var results = {
|
||||
fields : [],
|
||||
records: []
|
||||
};
|
||||
var entries = gdocsSpreadsheet.feed.entry || [];
|
||||
var key;
|
||||
var colName;
|
||||
// percentage values (e.g. 23.3%)
|
||||
var rep = /^([\d\.\-]+)\%$/;
|
||||
|
||||
for(key in entries[0]) {
|
||||
// it's barely possible it has inherited keys starting with 'gsx$'
|
||||
if(/^gsx/.test(key)) {
|
||||
colName = key.substr(4);
|
||||
results.fields.push(colName);
|
||||
}
|
||||
}
|
||||
|
||||
// converts non numberical values that should be numerical (22.3%[string] -> 0.223[float])
|
||||
results.records = _.map(entries, function(entry) {
|
||||
var row = {};
|
||||
|
||||
_.each(results.fields, function(col) {
|
||||
var _keyname = 'gsx$' + col;
|
||||
var value = entry[_keyname].$t;
|
||||
var num;
|
||||
|
||||
// TODO cover this part of code with test
|
||||
// TODO use the regexp only once
|
||||
// if labelled as % and value contains %, convert
|
||||
if(colTypes[col] === 'percent' && rep.test(value)) {
|
||||
num = rep.exec(value)[1];
|
||||
value = parseFloat(num) / 100;
|
||||
}
|
||||
|
||||
row[col] = value;
|
||||
});
|
||||
|
||||
return row;
|
||||
});
|
||||
|
||||
results.worksheetTitle = gdocsSpreadsheet.feed.title.$t;
|
||||
return results;
|
||||
};
|
||||
|
||||
// Convenience function to get GDocs JSON API Url from standard URL
|
||||
my.getGDocsAPIUrls = function(url) {
|
||||
// https://docs.google.com/spreadsheet/ccc?key=XXXX#gid=YYY
|
||||
var regex = /.*spreadsheet\/ccc?.*key=([^#?&+]+)[^#]*(#gid=([\d]+).*)?/;
|
||||
var matches = url.match(regex);
|
||||
var key;
|
||||
var worksheet;
|
||||
var urls;
|
||||
|
||||
if(!!matches) {
|
||||
key = matches[1];
|
||||
// the gid in url is 0-based and feed url is 1-based
|
||||
worksheet = parseInt(matches[3]) + 1;
|
||||
if (isNaN(worksheet)) {
|
||||
worksheet = 1;
|
||||
}
|
||||
urls = {
|
||||
worksheet : 'https://spreadsheets.google.com/feeds/list/'+ key +'/'+ worksheet +'/public/values?alt=json',
|
||||
spreadsheet: 'https://spreadsheets.google.com/feeds/worksheets/'+ key +'/public/basic?alt=json'
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we assume that it's one of the feeds urls
|
||||
key = url.split('/')[5];
|
||||
// by default then, take first worksheet
|
||||
worksheet = 1;
|
||||
urls = {
|
||||
worksheet : 'https://spreadsheets.google.com/feeds/list/'+ key +'/'+ worksheet +'/public/values?alt=json',
|
||||
spreadsheet: 'https://spreadsheets.google.com/feeds/worksheets/'+ key +'/public/basic?alt=json'
|
||||
}
|
||||
}
|
||||
|
||||
return urls;
|
||||
};
|
||||
}(this.recline.Backend.GDocs));
|
||||
@ -3,10 +3,11 @@ this.recline.Backend = this.recline.Backend || {};
|
||||
this.recline.Backend.Memory = this.recline.Backend.Memory || {};
|
||||
|
||||
(function(my) {
|
||||
"use strict";
|
||||
my.__type__ = 'memory';
|
||||
|
||||
// private data - use either jQuery or Underscore Deferred depending on what is available
|
||||
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
|
||||
var Deferred = (typeof jQuery !== "undefined" && jQuery.Deferred) || _.Deferred;
|
||||
|
||||
// ## Data Wrapper
|
||||
//
|
||||
@ -107,9 +108,9 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
|
||||
integer: function (e) { return parseFloat(e, 10); },
|
||||
'float': function (e) { return parseFloat(e, 10); },
|
||||
number: function (e) { return parseFloat(e, 10); },
|
||||
string : function (e) { return e.toString() },
|
||||
date : function (e) { return new Date(e).valueOf() },
|
||||
datetime : function (e) { return new Date(e).valueOf() }
|
||||
string : function (e) { return e.toString(); },
|
||||
date : function (e) { return moment(e).valueOf(); },
|
||||
datetime : function (e) { return new Date(e).valueOf(); }
|
||||
};
|
||||
var keyedFields = {};
|
||||
_.each(self.fields, function(field) {
|
||||
@ -140,19 +141,19 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
|
||||
}
|
||||
|
||||
function range(record, filter) {
|
||||
var startnull = (filter.start == null || filter.start === '');
|
||||
var stopnull = (filter.stop == null || filter.stop === '');
|
||||
var fromnull = (_.isUndefined(filter.from) || filter.from === null || filter.from === '');
|
||||
var tonull = (_.isUndefined(filter.to) || filter.to === null || filter.to === '');
|
||||
var parse = getDataParser(filter);
|
||||
var value = parse(record[filter.field]);
|
||||
var start = parse(filter.start);
|
||||
var stop = parse(filter.stop);
|
||||
var from = parse(fromnull ? '' : filter.from);
|
||||
var to = parse(tonull ? '' : filter.to);
|
||||
|
||||
// if at least one end of range is set do not allow '' to get through
|
||||
// note that for strings '' <= {any-character} e.g. '' <= 'a'
|
||||
if ((!startnull || !stopnull) && value === '') {
|
||||
if ((!fromnull || !tonull) && value === '') {
|
||||
return false;
|
||||
}
|
||||
return ((startnull || value >= start) && (stopnull || value <= stop));
|
||||
return ((fromnull || value >= from) && (tonull || value <= to));
|
||||
}
|
||||
|
||||
function geo_distance() {
|
||||
@ -165,8 +166,8 @@ this.recline.Backend.Memory = this.recline.Backend.Memory || {};
|
||||
if (queryObj.q) {
|
||||
var terms = queryObj.q.split(' ');
|
||||
var patterns=_.map(terms, function(term) {
|
||||
return new RegExp(term.toLowerCase());;
|
||||
});
|
||||
return new RegExp(term.toLowerCase());
|
||||
});
|
||||
results = _.filter(results, function(rawdoc) {
|
||||
var matches = true;
|
||||
_.each(patterns, function(pattern) {
|
||||
|
||||
88
src/model.js
88
src/model.js
@ -3,9 +3,10 @@ this.recline = this.recline || {};
|
||||
this.recline.Model = this.recline.Model || {};
|
||||
|
||||
(function(my) {
|
||||
"use strict";
|
||||
|
||||
// use either jQuery or Underscore Deferred depending on what is available
|
||||
var Deferred = _.isUndefined(this.jQuery) ? _.Deferred : jQuery.Deferred;
|
||||
var Deferred = (typeof jQuery !== "undefined" && jQuery.Deferred) || _.Deferred;
|
||||
|
||||
// ## <a id="dataset">Dataset</a>
|
||||
my.Dataset = Backbone.Model.extend({
|
||||
@ -15,6 +16,7 @@ my.Dataset = Backbone.Model.extend({
|
||||
|
||||
// ### initialize
|
||||
initialize: function() {
|
||||
var self = this;
|
||||
_.bindAll(this, 'query');
|
||||
this.backend = null;
|
||||
if (this.get('backend')) {
|
||||
@ -34,17 +36,26 @@ my.Dataset = Backbone.Model.extend({
|
||||
this.facets = new my.FacetList();
|
||||
this.recordCount = null;
|
||||
this.queryState = new my.Query();
|
||||
this.queryState.bind('change', this.query);
|
||||
this.queryState.bind('facet:add', this.query);
|
||||
this.queryState.bind('change facet:add', function () {
|
||||
self.query(); // We want to call query() without any arguments.
|
||||
});
|
||||
// store is what we query and save against
|
||||
// store will either be the backend or be a memory store if Backend fetch
|
||||
// tells us to use memory store
|
||||
this._store = this.backend;
|
||||
|
||||
// if backend has a handleQueryResultFunction, use that
|
||||
this._handleResult = (this.backend != null && _.has(this.backend, 'handleQueryResult')) ?
|
||||
this.backend.handleQueryResult : this._handleQueryResult;
|
||||
if (this.backend == recline.Backend.Memory) {
|
||||
this.fetch();
|
||||
}
|
||||
},
|
||||
|
||||
sync: function(method, model, options) {
|
||||
return this.backend.sync(method, model, options);
|
||||
},
|
||||
|
||||
// ### fetch
|
||||
//
|
||||
// Retrieve dataset and (some) records from the backend.
|
||||
@ -68,7 +79,13 @@ my.Dataset = Backbone.Model.extend({
|
||||
}
|
||||
|
||||
function handleResults(results) {
|
||||
var out = self._normalizeRecordsAndFields(results.records, results.fields);
|
||||
// if explicitly given the fields
|
||||
// (e.g. var dataset = new Dataset({fields: fields, ...})
|
||||
// use that field info over anything we get back by parsing the data
|
||||
// (results.fields)
|
||||
var fields = self.get('fields') || results.fields;
|
||||
|
||||
var out = self._normalizeRecordsAndFields(results.records, fields);
|
||||
if (results.useMemoryStore) {
|
||||
self._store = new recline.Backend.Memory.Store(out.records, out.fields);
|
||||
}
|
||||
@ -180,7 +197,7 @@ my.Dataset = Backbone.Model.extend({
|
||||
|
||||
this._store.query(actualQuery, this.toJSON())
|
||||
.done(function(queryResult) {
|
||||
self._handleQueryResult(queryResult);
|
||||
self._handleResult(queryResult);
|
||||
self.trigger('query:done');
|
||||
dfd.resolve(self.records);
|
||||
})
|
||||
@ -298,7 +315,7 @@ my.Record = Backbone.Model.extend({
|
||||
//
|
||||
// NB: if field is undefined a default '' value will be returned
|
||||
getFieldValue: function(field) {
|
||||
val = this.getFieldValueUnrendered(field);
|
||||
var val = this.getFieldValueUnrendered(field);
|
||||
if (field && !_.isUndefined(field.renderer)) {
|
||||
val = field.renderer(val, field, this.toJSON());
|
||||
}
|
||||
@ -472,8 +489,8 @@ my.Query = Backbone.Model.extend({
|
||||
},
|
||||
range: {
|
||||
type: 'range',
|
||||
start: '',
|
||||
stop: ''
|
||||
from: '',
|
||||
to: ''
|
||||
},
|
||||
geo_distance: {
|
||||
type: 'geo_distance',
|
||||
@ -501,6 +518,23 @@ my.Query = Backbone.Model.extend({
|
||||
filters.push(ourfilter);
|
||||
this.trigger('change:filters:new-blank');
|
||||
},
|
||||
replaceFilter: function(filter) {
|
||||
// delete filter on the same field, then add
|
||||
var filters = this.get('filters');
|
||||
var idx = -1;
|
||||
_.each(this.get('filters'), function(f, key, list) {
|
||||
if (filter.field == f.field) {
|
||||
idx = key;
|
||||
}
|
||||
});
|
||||
// trigger just one event (change:filters:new-blank) instead of one for remove and
|
||||
// one for add
|
||||
if (idx >= 0) {
|
||||
filters.splice(idx, 1);
|
||||
this.set({filters: filters});
|
||||
}
|
||||
this.addFilter(filter);
|
||||
},
|
||||
updateFilter: function(index, value) {
|
||||
},
|
||||
// ### removeFilter
|
||||
@ -517,7 +551,7 @@ my.Query = Backbone.Model.extend({
|
||||
// Add a Facet to this query
|
||||
//
|
||||
// See <http://www.elasticsearch.org/guide/reference/api/search/facets/>
|
||||
addFacet: function(fieldId) {
|
||||
addFacet: function(fieldId, size, silent) {
|
||||
var facets = this.get('facets');
|
||||
// Assume id and fieldId should be the same (TODO: this need not be true if we want to add two different type of facets on same field)
|
||||
if (_.contains(_.keys(facets), fieldId)) {
|
||||
@ -526,8 +560,13 @@ my.Query = Backbone.Model.extend({
|
||||
facets[fieldId] = {
|
||||
terms: { field: fieldId }
|
||||
};
|
||||
if (!_.isUndefined(size)) {
|
||||
facets[fieldId].terms.size = size;
|
||||
}
|
||||
this.set({facets: facets}, {silent: true});
|
||||
this.trigger('facet:add', this);
|
||||
if (!silent) {
|
||||
this.trigger('facet:add', this);
|
||||
}
|
||||
},
|
||||
addHistogramFacet: function(fieldId) {
|
||||
var facets = this.get('facets');
|
||||
@ -539,7 +578,30 @@ my.Query = Backbone.Model.extend({
|
||||
};
|
||||
this.set({facets: facets}, {silent: true});
|
||||
this.trigger('facet:add', this);
|
||||
},
|
||||
removeFacet: function(fieldId) {
|
||||
var facets = this.get('facets');
|
||||
// Assume id and fieldId should be the same (TODO: this need not be true if we want to add two different type of facets on same field)
|
||||
if (!_.contains(_.keys(facets), fieldId)) {
|
||||
return;
|
||||
}
|
||||
delete facets[fieldId];
|
||||
this.set({facets: facets}, {silent: true});
|
||||
this.trigger('facet:remove', this);
|
||||
},
|
||||
clearFacets: function() {
|
||||
var facets = this.get('facets');
|
||||
_.each(_.keys(facets), function(fieldId) {
|
||||
delete facets[fieldId];
|
||||
});
|
||||
this.trigger('facet:remove', this);
|
||||
},
|
||||
// trigger a facet add; use this to trigger a single event after adding
|
||||
// multiple facets
|
||||
refreshFacets: function() {
|
||||
this.trigger('facet:add', this);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -577,9 +639,9 @@ my.ObjectState = Backbone.Model.extend({
|
||||
// ## Backbone.sync
|
||||
//
|
||||
// Override Backbone.sync to hand off to sync function in relevant backend
|
||||
Backbone.sync = function(method, model, options) {
|
||||
return model.backend.sync(method, model, options);
|
||||
};
|
||||
// Backbone.sync = function(method, model, options) {
|
||||
// return model.backend.sync(method, model, options);
|
||||
// };
|
||||
|
||||
}(this.recline.Model));
|
||||
|
||||
|
||||
160
src/view.flot.js
160
src/view.flot.js
@ -4,7 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
|
||||
"use strict";
|
||||
// ## Graph view for a Dataset using Flot graphing library.
|
||||
//
|
||||
// Initialization arguments (in a hash in first parameter):
|
||||
@ -15,7 +15,8 @@ this.recline.View = this.recline.View || {};
|
||||
// {
|
||||
// group: {column name for x-axis},
|
||||
// series: [{column name for series A}, {column name series B}, ... ],
|
||||
// graphType: 'line',
|
||||
// // options are: lines, points, lines-and-points, bars, columns
|
||||
// graphType: 'lines',
|
||||
// graphOptions: {custom [flot options]}
|
||||
// }
|
||||
//
|
||||
@ -38,14 +39,11 @@ my.Flot = Backbone.View.extend({
|
||||
var self = this;
|
||||
this.graphColors = ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"];
|
||||
|
||||
this.el = $(this.el);
|
||||
_.bindAll(this, 'render', 'redraw', '_toolTip', '_xaxisLabel');
|
||||
this.needToRedraw = false;
|
||||
this.model.bind('change', this.render);
|
||||
this.model.fields.bind('reset', this.render);
|
||||
this.model.fields.bind('add', this.render);
|
||||
this.model.records.bind('add', this.redraw);
|
||||
this.model.records.bind('reset', this.redraw);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.listenTo(this.model.fields, 'reset add', this.render);
|
||||
this.listenTo(this.model.records, 'reset add', this.redraw);
|
||||
var stateData = _.extend({
|
||||
group: null,
|
||||
// so that at least one series chooser box shows up
|
||||
@ -60,29 +58,34 @@ my.Flot = Backbone.View.extend({
|
||||
model: this.model,
|
||||
state: this.state.toJSON()
|
||||
});
|
||||
this.editor.state.bind('change', function() {
|
||||
this.listenTo(this.editor.state, 'change', function() {
|
||||
self.state.set(self.editor.state.toJSON());
|
||||
self.redraw();
|
||||
});
|
||||
this.elSidebar = this.editor.el;
|
||||
this.elSidebar = this.editor.$el;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
var tmplData = this.model.toTemplateJSON();
|
||||
var htmls = Mustache.render(this.template, tmplData);
|
||||
$(this.el).html(htmls);
|
||||
this.$graph = this.el.find('.panel.graph');
|
||||
this.$el.html(htmls);
|
||||
this.$graph = this.$el.find('.panel.graph');
|
||||
this.$graph.on("plothover", this._toolTip);
|
||||
return this;
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
this.editor.remove();
|
||||
Backbone.View.prototype.remove.apply(this, arguments);
|
||||
},
|
||||
|
||||
redraw: function() {
|
||||
// There are issues generating a Flot graph if either:
|
||||
// * The relevant div that graph attaches to his hidden at the moment of creating the plot -- Flot will complain with
|
||||
// Uncaught Invalid dimensions for plot, width = 0, height = 0
|
||||
// * There is no data for the plot -- either same error or may have issues later with errors like 'non-existent node-value'
|
||||
var areWeVisible = !jQuery.expr.filters.hidden(this.el[0]);
|
||||
var areWeVisible = !jQuery.expr.filters.hidden(this.el);
|
||||
if ((!areWeVisible || this.model.records.length === 0)) {
|
||||
this.needToRedraw = true;
|
||||
return;
|
||||
@ -153,25 +156,17 @@ my.Flot = Backbone.View.extend({
|
||||
},
|
||||
|
||||
_xaxisLabel: function (x) {
|
||||
var xfield = this.model.fields.get(this.state.attributes.group);
|
||||
|
||||
// time series
|
||||
var xtype = xfield.get('type');
|
||||
var isDateTime = (xtype === 'date' || xtype === 'date-time' || xtype === 'time');
|
||||
|
||||
if (this.xvaluesAreIndex) {
|
||||
if (this._groupFieldIsDateTime()) {
|
||||
// oddly x comes through as milliseconds *string* (rather than int
|
||||
// or float) so we have to reparse
|
||||
x = new Date(parseFloat(x)).toLocaleDateString();
|
||||
} else if (this.xvaluesAreIndex) {
|
||||
x = parseInt(x, 10);
|
||||
// HACK: deal with bar graph style cases where x-axis items were strings
|
||||
// In this case x at this point is the index of the item in the list of
|
||||
// records not its actual x-axis value
|
||||
x = this.model.records.models[x].get(this.state.attributes.group);
|
||||
}
|
||||
if (isDateTime) {
|
||||
x = new Date(x).toLocaleDateString();
|
||||
}
|
||||
// } else if (isDateTime) {
|
||||
// x = new Date(parseInt(x, 10)).toLocaleDateString();
|
||||
// }
|
||||
|
||||
return x;
|
||||
},
|
||||
@ -186,25 +181,26 @@ my.Flot = Backbone.View.extend({
|
||||
// @param numPoints the number of points that will be plotted
|
||||
getGraphOptions: function(typeId, numPoints) {
|
||||
var self = this;
|
||||
|
||||
var tickFormatter = function (x) {
|
||||
// convert x to a string and make sure that it is not too long or the
|
||||
// tick labels will overlap
|
||||
// TODO: find a more accurate way of calculating the size of tick labels
|
||||
var label = self._xaxisLabel(x) || "";
|
||||
|
||||
if (typeof label !== 'string') {
|
||||
label = label.toString();
|
||||
}
|
||||
if (self.state.attributes.graphType !== 'bars' && label.length > 10) {
|
||||
label = label.slice(0, 10) + "...";
|
||||
}
|
||||
|
||||
return label;
|
||||
};
|
||||
|
||||
var groupFieldIsDateTime = self._groupFieldIsDateTime();
|
||||
var xaxis = {};
|
||||
xaxis.tickFormatter = tickFormatter;
|
||||
|
||||
if (!groupFieldIsDateTime) {
|
||||
xaxis.tickFormatter = function (x) {
|
||||
// convert x to a string and make sure that it is not too long or the
|
||||
// tick labels will overlap
|
||||
// TODO: find a more accurate way of calculating the size of tick labels
|
||||
var label = self._xaxisLabel(x) || "";
|
||||
|
||||
if (typeof label !== 'string') {
|
||||
label = label.toString();
|
||||
}
|
||||
if (self.state.attributes.graphType !== 'bars' && label.length > 10) {
|
||||
label = label.slice(0, 10) + "...";
|
||||
}
|
||||
|
||||
return label;
|
||||
};
|
||||
}
|
||||
|
||||
// for labels case we only want ticks at the label intervals
|
||||
// HACK: however we also get this case with Date fields. In that case we
|
||||
@ -213,10 +209,12 @@ my.Flot = Backbone.View.extend({
|
||||
var numTicks = Math.min(this.model.records.length, 15);
|
||||
var increment = this.model.records.length / numTicks;
|
||||
var ticks = [];
|
||||
for (i=0; i<numTicks; i++) {
|
||||
for (var i=0; i<numTicks; i++) {
|
||||
ticks.push(parseInt(i*increment, 10));
|
||||
}
|
||||
xaxis.ticks = ticks;
|
||||
} else if (groupFieldIsDateTime) {
|
||||
xaxis.mode = 'time';
|
||||
}
|
||||
|
||||
var yaxis = {};
|
||||
@ -298,34 +296,54 @@ my.Flot = Backbone.View.extend({
|
||||
}
|
||||
},
|
||||
|
||||
_groupFieldIsDateTime: function() {
|
||||
var xfield = this.model.fields.get(this.state.attributes.group);
|
||||
var xtype = xfield.get('type');
|
||||
var isDateTime = (xtype === 'date' || xtype === 'date-time' || xtype === 'time');
|
||||
return isDateTime;
|
||||
},
|
||||
|
||||
createSeries: function() {
|
||||
var self = this;
|
||||
self.xvaluesAreIndex = false;
|
||||
var series = [];
|
||||
var xfield = self.model.fields.get(self.state.attributes.group);
|
||||
var isDateTime = self._groupFieldIsDateTime();
|
||||
|
||||
_.each(this.state.attributes.series, function(field) {
|
||||
var points = [];
|
||||
var fieldLabel = self.model.fields.get(field).get('label');
|
||||
|
||||
if (isDateTime){
|
||||
var cast = function(x){
|
||||
var _date = moment(String(x));
|
||||
if (_date.isValid()) {
|
||||
x = _date.toDate().getTime();
|
||||
}
|
||||
return x
|
||||
}
|
||||
} else {
|
||||
var raw = _.map(self.model.records.models,
|
||||
function(doc, index){
|
||||
return doc.getFieldValueUnrendered(xfield)
|
||||
});
|
||||
|
||||
if (_.all(raw, function(x){ return !isNaN(parseFloat(x)) })){
|
||||
var cast = function(x){ return parseFloat(x) }
|
||||
} else {
|
||||
self.xvaluesAreIndex = true
|
||||
}
|
||||
}
|
||||
|
||||
_.each(self.model.records.models, function(doc, index) {
|
||||
var xfield = self.model.fields.get(self.state.attributes.group);
|
||||
var x = doc.getFieldValue(xfield);
|
||||
|
||||
// time series
|
||||
var xtype = xfield.get('type');
|
||||
var isDateTime = (xtype === 'date' || xtype === 'date-time' || xtype === 'time');
|
||||
|
||||
if (isDateTime) {
|
||||
self.xvaluesAreIndex = true;
|
||||
x = index;
|
||||
} else if (typeof x === 'string') {
|
||||
x = parseFloat(x);
|
||||
if (isNaN(x)) { // assume this is a string label
|
||||
x = index;
|
||||
self.xvaluesAreIndex = true;
|
||||
}
|
||||
if(self.xvaluesAreIndex){
|
||||
var x = index;
|
||||
}else{
|
||||
var x = cast(doc.getFieldValueUnrendered(xfield));
|
||||
}
|
||||
|
||||
var yfield = self.model.fields.get(field);
|
||||
var y = doc.getFieldValue(yfield);
|
||||
var y = doc.getFieldValueUnrendered(yfield);
|
||||
|
||||
if (self.state.attributes.graphType == 'bars') {
|
||||
points.push([y, x]);
|
||||
@ -403,10 +421,8 @@ my.FlotControls = Backbone.View.extend({
|
||||
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
_.bindAll(this, 'render');
|
||||
this.model.fields.bind('reset', this.render);
|
||||
this.model.fields.bind('add', this.render);
|
||||
this.listenTo(this.model.fields, 'reset add', this.render);
|
||||
this.state = new recline.Model.ObjectState(options.state);
|
||||
this.render();
|
||||
},
|
||||
@ -415,7 +431,7 @@ my.FlotControls = Backbone.View.extend({
|
||||
var self = this;
|
||||
var tmplData = this.model.toTemplateJSON();
|
||||
var htmls = Mustache.render(this.template, tmplData);
|
||||
this.el.html(htmls);
|
||||
this.$el.html(htmls);
|
||||
|
||||
// set up editor from state
|
||||
if (this.state.get('graphType')) {
|
||||
@ -439,7 +455,7 @@ my.FlotControls = Backbone.View.extend({
|
||||
// Private: Helper function to select an option from a select list
|
||||
//
|
||||
_selectOption: function(id,value){
|
||||
var options = this.el.find(id + ' select > option');
|
||||
var options = this.$el.find(id + ' select > option');
|
||||
if (options) {
|
||||
options.each(function(opt){
|
||||
if (this.value == value) {
|
||||
@ -451,16 +467,16 @@ my.FlotControls = Backbone.View.extend({
|
||||
},
|
||||
|
||||
onEditorSubmit: function(e) {
|
||||
var select = this.el.find('.editor-group select');
|
||||
var select = this.$el.find('.editor-group select');
|
||||
var $editor = this;
|
||||
var $series = this.el.find('.editor-series select');
|
||||
var $series = this.$el.find('.editor-series select');
|
||||
var series = $series.map(function () {
|
||||
return $(this).val();
|
||||
});
|
||||
var updatedState = {
|
||||
series: $.makeArray(series),
|
||||
group: this.el.find('.editor-group select').val(),
|
||||
graphType: this.el.find('.editor-type select').val()
|
||||
group: this.$el.find('.editor-group select').val(),
|
||||
graphType: this.$el.find('.editor-type select').val()
|
||||
};
|
||||
this.state.set(updatedState);
|
||||
},
|
||||
@ -477,7 +493,7 @@ my.FlotControls = Backbone.View.extend({
|
||||
}, this.model.toTemplateJSON());
|
||||
|
||||
var htmls = Mustache.render(this.templateSeriesEditor, data);
|
||||
this.el.find('.editor-series-group').append(htmls);
|
||||
this.$el.find('.editor-series-group').append(htmls);
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
// ## (Data) Grid Dataset View
|
||||
//
|
||||
// Provides a tabular view on a Dataset.
|
||||
@ -15,11 +16,8 @@ my.Grid = Backbone.View.extend({
|
||||
|
||||
initialize: function(modelEtc) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
_.bindAll(this, 'render', 'onHorizontalScroll');
|
||||
this.model.records.bind('add', this.render);
|
||||
this.model.records.bind('reset', this.render);
|
||||
this.model.records.bind('remove', this.render);
|
||||
this.listenTo(this.model.records, 'add reset remove', this.render);
|
||||
this.tempState = {};
|
||||
var state = _.extend({
|
||||
hiddenFields: []
|
||||
@ -59,7 +57,7 @@ my.Grid = Backbone.View.extend({
|
||||
|
||||
onHorizontalScroll: function(e) {
|
||||
var currentScroll = $(e.target).scrollLeft();
|
||||
this.el.find('.recline-grid thead tr').scrollLeft(currentScroll);
|
||||
this.$el.find('.recline-grid thead tr').scrollLeft(currentScroll);
|
||||
},
|
||||
|
||||
// ======================================================
|
||||
@ -87,7 +85,7 @@ my.Grid = Backbone.View.extend({
|
||||
var modelData = this.model.toJSON();
|
||||
modelData.notEmpty = ( this.fields.length > 0 );
|
||||
// TODO: move this sort of thing into a toTemplateJSON method on Dataset?
|
||||
modelData.fields = _.map(this.fields, function(field) {
|
||||
modelData.fields = this.fields.map(function(field) {
|
||||
return field.toJSON();
|
||||
});
|
||||
// last header width = scroll bar - border (2px) */
|
||||
@ -96,17 +94,18 @@ my.Grid = Backbone.View.extend({
|
||||
},
|
||||
render: function() {
|
||||
var self = this;
|
||||
this.fields = this.model.fields.filter(function(field) {
|
||||
this.fields = new recline.Model.FieldList(this.model.fields.filter(function(field) {
|
||||
return _.indexOf(self.state.get('hiddenFields'), field.id) == -1;
|
||||
});
|
||||
}));
|
||||
|
||||
this.scrollbarDimensions = this.scrollbarDimensions || this._scrollbarSize(); // skip measurement if already have dimensions
|
||||
var numFields = this.fields.length;
|
||||
// compute field widths (-20 for first menu col + 10px for padding on each col and finally 16px for the scrollbar)
|
||||
var fullWidth = self.el.width() - 20 - 10 * numFields - this.scrollbarDimensions.width;
|
||||
var fullWidth = self.$el.width() - 20 - 10 * numFields - this.scrollbarDimensions.width;
|
||||
var width = parseInt(Math.max(50, fullWidth / numFields), 10);
|
||||
// if columns extend outside viewport then remainder is 0
|
||||
var remainder = Math.max(fullWidth - numFields * width,0);
|
||||
_.each(this.fields, function(field, idx) {
|
||||
this.fields.each(function(field, idx) {
|
||||
// add the remainder to the first field width so we make up full col
|
||||
if (idx === 0) {
|
||||
field.set({width: width+remainder});
|
||||
@ -115,10 +114,10 @@ my.Grid = Backbone.View.extend({
|
||||
}
|
||||
});
|
||||
var htmls = Mustache.render(this.template, this.toTemplateJSON());
|
||||
this.el.html(htmls);
|
||||
this.$el.html(htmls);
|
||||
this.model.records.forEach(function(doc) {
|
||||
var tr = $('<tr />');
|
||||
self.el.find('tbody').append(tr);
|
||||
self.$el.find('tbody').append(tr);
|
||||
var newView = new my.GridRow({
|
||||
model: doc,
|
||||
el: tr,
|
||||
@ -127,12 +126,12 @@ my.Grid = Backbone.View.extend({
|
||||
newView.render();
|
||||
});
|
||||
// hide extra header col if no scrollbar to avoid unsightly overhang
|
||||
var $tbody = this.el.find('tbody')[0];
|
||||
var $tbody = this.$el.find('tbody')[0];
|
||||
if ($tbody.scrollHeight <= $tbody.offsetHeight) {
|
||||
this.el.find('th.last-header').hide();
|
||||
this.$el.find('th.last-header').hide();
|
||||
}
|
||||
this.el.find('.recline-grid').toggleClass('no-hidden', (self.state.get('hiddenFields').length === 0));
|
||||
this.el.find('.recline-grid tbody').scroll(this.onHorizontalScroll);
|
||||
this.$el.find('.recline-grid').toggleClass('no-hidden', (self.state.get('hiddenFields').length === 0));
|
||||
this.$el.find('.recline-grid tbody').scroll(this.onHorizontalScroll);
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -168,8 +167,7 @@ my.GridRow = Backbone.View.extend({
|
||||
initialize: function(initData) {
|
||||
_.bindAll(this, 'render');
|
||||
this._fields = initData.fields;
|
||||
this.el = $(this.el);
|
||||
this.model.bind('change', this.render);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
},
|
||||
|
||||
template: ' \
|
||||
@ -202,9 +200,9 @@ my.GridRow = Backbone.View.extend({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.el.attr('data-id', this.model.id);
|
||||
this.$el.attr('data-id', this.model.id);
|
||||
var html = Mustache.render(this.template, this.toTemplateJSON());
|
||||
$(this.el).html(html);
|
||||
this.$el.html(html);
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -224,7 +222,7 @@ my.GridRow = Backbone.View.extend({
|
||||
',
|
||||
|
||||
onEditClick: function(e) {
|
||||
var editing = this.el.find('.data-table-cell-editor-editor');
|
||||
var editing = this.$el.find('.data-table-cell-editor-editor');
|
||||
if (editing.length > 0) {
|
||||
editing.parents('.data-table-cell-value').html(editing.text()).siblings('.data-table-cell-edit').removeClass("hidden");
|
||||
}
|
||||
|
||||
121
src/view.map.js
121
src/view.map.js
@ -4,13 +4,13 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
|
||||
"use strict";
|
||||
// ## Map view for a Dataset using Leaflet mapping library.
|
||||
//
|
||||
// This view allows to plot gereferenced records on a map. The location
|
||||
// information can be provided in 2 ways:
|
||||
//
|
||||
// 1. Via a single field. This field must be either a geo_point or
|
||||
// 1. Via a single field. This field must be either a geo_point or
|
||||
// [GeoJSON](http://geojson.org) object
|
||||
// 2. Via two fields with latitude and longitude coordinates.
|
||||
//
|
||||
@ -28,6 +28,8 @@ this.recline.View = this.recline.View || {};
|
||||
// latField: {id of field containing latitude in the dataset}
|
||||
// autoZoom: true,
|
||||
// // use cluster support
|
||||
// // cluster: true = always on
|
||||
// // cluster: false = always off
|
||||
// cluster: false
|
||||
// }
|
||||
// </pre>
|
||||
@ -51,7 +53,6 @@ my.Map = Backbone.View.extend({
|
||||
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
this.visible = true;
|
||||
this.mapReady = false;
|
||||
// this will be the Leaflet L.Map object (setup below)
|
||||
@ -78,32 +79,32 @@ my.Map = Backbone.View.extend({
|
||||
};
|
||||
|
||||
// Listen to changes in the fields
|
||||
this.model.fields.bind('change', function() {
|
||||
this.listenTo(this.model.fields, 'change', function() {
|
||||
self._setupGeometryField();
|
||||
self.render();
|
||||
});
|
||||
|
||||
// Listen to changes in the records
|
||||
this.model.records.bind('add', function(doc){self.redraw('add',doc);});
|
||||
this.model.records.bind('change', function(doc){
|
||||
this.listenTo(this.model.records, 'add', function(doc){self.redraw('add',doc);});
|
||||
this.listenTo(this.model.records, 'change', function(doc){
|
||||
self.redraw('remove',doc);
|
||||
self.redraw('add',doc);
|
||||
});
|
||||
this.model.records.bind('remove', function(doc){self.redraw('remove',doc);});
|
||||
this.model.records.bind('reset', function(){self.redraw('reset');});
|
||||
this.listenTo(this.model.records, 'remove', function(doc){self.redraw('remove',doc);});
|
||||
this.listenTo(this.model.records, 'reset', function(){self.redraw('reset');});
|
||||
|
||||
this.menu = new my.MapMenu({
|
||||
model: this.model,
|
||||
state: this.state.toJSON()
|
||||
});
|
||||
this.menu.state.bind('change', function() {
|
||||
this.listenTo(this.menu.state, 'change', function() {
|
||||
self.state.set(self.menu.state.toJSON());
|
||||
self.redraw();
|
||||
});
|
||||
this.state.bind('change', function() {
|
||||
this.listenTo(this.state, 'change', function() {
|
||||
self.redraw();
|
||||
});
|
||||
this.elSidebar = this.menu.el;
|
||||
this.elSidebar = this.menu.$el;
|
||||
},
|
||||
|
||||
// ## Customization Functions
|
||||
@ -123,7 +124,7 @@ my.Map = Backbone.View.extend({
|
||||
// }
|
||||
infobox: function(record) {
|
||||
var html = '';
|
||||
for (key in record.attributes){
|
||||
for (var key in record.attributes){
|
||||
if (!(this.state.get('geomField') && key == this.state.get('geomField'))){
|
||||
html += '<div><strong>' + key + '</strong>: '+ record.attributes[key] + '</div>';
|
||||
}
|
||||
@ -172,10 +173,9 @@ my.Map = Backbone.View.extend({
|
||||
// Also sets up the editor fields and the map if necessary.
|
||||
render: function() {
|
||||
var self = this;
|
||||
|
||||
htmls = Mustache.render(this.template, this.model.toTemplateJSON());
|
||||
$(this.el).html(htmls);
|
||||
this.$map = this.el.find('.panel.map');
|
||||
var htmls = Mustache.render(this.template, this.model.toTemplateJSON());
|
||||
this.$el.html(htmls);
|
||||
this.$map = this.$el.find('.panel.map');
|
||||
this.redraw();
|
||||
return this;
|
||||
},
|
||||
@ -219,15 +219,6 @@ my.Map = Backbone.View.extend({
|
||||
this._remove(doc);
|
||||
}
|
||||
|
||||
// enable clustering if there is a large number of markers
|
||||
var countAfter = 0;
|
||||
this.features.eachLayer(function(){countAfter++;});
|
||||
var sizeIncreased = countAfter - countBefore > 0;
|
||||
if (!this.state.get('cluster') && countAfter > 64 && sizeIncreased) {
|
||||
this.state.set({cluster: true});
|
||||
return;
|
||||
}
|
||||
|
||||
// this must come before zooming!
|
||||
// if not: errors when using e.g. circle markers like
|
||||
// "Cannot call method 'project' of undefined"
|
||||
@ -326,7 +317,7 @@ my.Map = Backbone.View.extend({
|
||||
if (!(docs instanceof Array)) docs = [docs];
|
||||
|
||||
_.each(docs,function(doc){
|
||||
for (key in self.features._layers){
|
||||
for (var key in self.features._layers){
|
||||
if (self.features._layers[key].feature.properties.cid == doc.cid){
|
||||
self.features.removeLayer(self.features._layers[key]);
|
||||
}
|
||||
@ -335,6 +326,31 @@ my.Map = Backbone.View.extend({
|
||||
|
||||
},
|
||||
|
||||
// Private: convert DMS coordinates to decimal
|
||||
//
|
||||
// north and east are positive, south and west are negative
|
||||
//
|
||||
_parseCoordinateString: function(coord){
|
||||
if (typeof(coord) != 'string') {
|
||||
return(parseFloat(coord));
|
||||
}
|
||||
var dms = coord.split(/[^\.\d\w]+/);
|
||||
var deg = 0; var m = 0;
|
||||
var toDeg = [1, 60, 3600]; // conversion factors for Deg, min, sec
|
||||
var i;
|
||||
for (i = 0; i < dms.length; ++i) {
|
||||
if (isNaN(parseFloat(dms[i]))) {
|
||||
continue;
|
||||
}
|
||||
deg += parseFloat(dms[i]) / toDeg[m];
|
||||
m += 1;
|
||||
}
|
||||
if (coord.match(/[SW]/)) {
|
||||
deg = -1*deg;
|
||||
}
|
||||
return(deg);
|
||||
},
|
||||
|
||||
// Private: Return a GeoJSON geomtry extracted from the record fields
|
||||
//
|
||||
_getGeometryFromRecord: function(doc){
|
||||
@ -346,12 +362,12 @@ my.Map = Backbone.View.extend({
|
||||
value = $.parseJSON(value);
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
if (typeof(value) === 'string') {
|
||||
value = value.replace('(', '').replace(')', '');
|
||||
var parts = value.split(',');
|
||||
var lat = parseFloat(parts[0]);
|
||||
var lon = parseFloat(parts[1]);
|
||||
var lat = this._parseCoordinateString(parts[0]);
|
||||
var lon = this._parseCoordinateString(parts[1]);
|
||||
|
||||
if (!isNaN(lon) && !isNaN(parseFloat(lat))) {
|
||||
return {
|
||||
"type": "Point",
|
||||
@ -379,6 +395,9 @@ my.Map = Backbone.View.extend({
|
||||
// We'll create a GeoJSON like point object from the two lat/lon fields
|
||||
var lon = doc.get(this.state.get('lonField'));
|
||||
var lat = doc.get(this.state.get('latField'));
|
||||
lon = this._parseCoordinateString(lon);
|
||||
lat = this._parseCoordinateString(lat);
|
||||
|
||||
if (!isNaN(parseFloat(lon)) && !isNaN(parseFloat(lat))) {
|
||||
return {
|
||||
type: 'Point',
|
||||
@ -442,8 +461,8 @@ my.Map = Backbone.View.extend({
|
||||
var self = this;
|
||||
this.map = new L.Map(this.$map.get(0));
|
||||
|
||||
var mapUrl = "http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png";
|
||||
var osmAttribution = 'Map data © 2011 OpenStreetMap contributors, Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">';
|
||||
var mapUrl = "//otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png";
|
||||
var osmAttribution = 'Map data © 2011 OpenStreetMap contributors, Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="//developer.mapquest.com/content/osm/mq_logo.png">';
|
||||
var bg = new L.TileLayer(mapUrl, {maxZoom: 18, attribution: osmAttribution ,subdomains: '1234'});
|
||||
this.map.addLayer(bg);
|
||||
|
||||
@ -533,7 +552,6 @@ my.MapMenu = Backbone.View.extend({
|
||||
Cluster markers</label> \
|
||||
</div> \
|
||||
<input type="hidden" class="editor-id" value="map-1" /> \
|
||||
</div> \
|
||||
</form> \
|
||||
',
|
||||
|
||||
@ -547,11 +565,10 @@ my.MapMenu = Backbone.View.extend({
|
||||
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
_.bindAll(this, 'render');
|
||||
this.model.fields.bind('change', this.render);
|
||||
this.listenTo(this.model.fields, 'change', this.render);
|
||||
this.state = new recline.Model.ObjectState(options.state);
|
||||
this.state.bind('change', this.render);
|
||||
this.listenTo(this.state, 'change', this.render);
|
||||
this.render();
|
||||
},
|
||||
|
||||
@ -560,28 +577,28 @@ my.MapMenu = Backbone.View.extend({
|
||||
// Also sets up the editor fields and the map if necessary.
|
||||
render: function() {
|
||||
var self = this;
|
||||
htmls = Mustache.render(this.template, this.model.toTemplateJSON());
|
||||
$(this.el).html(htmls);
|
||||
var htmls = Mustache.render(this.template, this.model.toTemplateJSON());
|
||||
this.$el.html(htmls);
|
||||
|
||||
if (this._geomReady() && this.model.fields.length){
|
||||
if (this.state.get('geomField')){
|
||||
this._selectOption('editor-geom-field',this.state.get('geomField'));
|
||||
this.el.find('#editor-field-type-geom').attr('checked','checked').change();
|
||||
this.$el.find('#editor-field-type-geom').attr('checked','checked').change();
|
||||
} else{
|
||||
this._selectOption('editor-lon-field',this.state.get('lonField'));
|
||||
this._selectOption('editor-lat-field',this.state.get('latField'));
|
||||
this.el.find('#editor-field-type-latlon').attr('checked','checked').change();
|
||||
this.$el.find('#editor-field-type-latlon').attr('checked','checked').change();
|
||||
}
|
||||
}
|
||||
if (this.state.get('autoZoom')) {
|
||||
this.el.find('#editor-auto-zoom').attr('checked', 'checked');
|
||||
this.$el.find('#editor-auto-zoom').attr('checked', 'checked');
|
||||
} else {
|
||||
this.el.find('#editor-auto-zoom').removeAttr('checked');
|
||||
this.$el.find('#editor-auto-zoom').removeAttr('checked');
|
||||
}
|
||||
if (this.state.get('cluster')) {
|
||||
this.el.find('#editor-cluster').attr('checked', 'checked');
|
||||
this.$el.find('#editor-cluster').attr('checked', 'checked');
|
||||
} else {
|
||||
this.el.find('#editor-cluster').removeAttr('checked');
|
||||
this.$el.find('#editor-cluster').removeAttr('checked');
|
||||
}
|
||||
return this;
|
||||
},
|
||||
@ -600,17 +617,17 @@ my.MapMenu = Backbone.View.extend({
|
||||
//
|
||||
onEditorSubmit: function(e){
|
||||
e.preventDefault();
|
||||
if (this.el.find('#editor-field-type-geom').attr('checked')){
|
||||
if (this.$el.find('#editor-field-type-geom').attr('checked')){
|
||||
this.state.set({
|
||||
geomField: this.el.find('.editor-geom-field > select > option:selected').val(),
|
||||
geomField: this.$el.find('.editor-geom-field > select > option:selected').val(),
|
||||
lonField: null,
|
||||
latField: null
|
||||
});
|
||||
} else {
|
||||
this.state.set({
|
||||
geomField: null,
|
||||
lonField: this.el.find('.editor-lon-field > select > option:selected').val(),
|
||||
latField: this.el.find('.editor-lat-field > select > option:selected').val()
|
||||
lonField: this.$el.find('.editor-lon-field > select > option:selected').val(),
|
||||
latField: this.$el.find('.editor-lat-field > select > option:selected').val()
|
||||
});
|
||||
}
|
||||
return false;
|
||||
@ -621,11 +638,11 @@ my.MapMenu = Backbone.View.extend({
|
||||
//
|
||||
onFieldTypeChange: function(e){
|
||||
if (e.target.value == 'geom'){
|
||||
this.el.find('.editor-field-type-geom').show();
|
||||
this.el.find('.editor-field-type-latlon').hide();
|
||||
this.$el.find('.editor-field-type-geom').show();
|
||||
this.$el.find('.editor-field-type-latlon').hide();
|
||||
} else {
|
||||
this.el.find('.editor-field-type-geom').hide();
|
||||
this.el.find('.editor-field-type-latlon').show();
|
||||
this.$el.find('.editor-field-type-geom').hide();
|
||||
this.$el.find('.editor-field-type-latlon').show();
|
||||
}
|
||||
},
|
||||
|
||||
@ -640,7 +657,7 @@ my.MapMenu = Backbone.View.extend({
|
||||
// Private: Helper function to select an option from a select list
|
||||
//
|
||||
_selectOption: function(id,value){
|
||||
var options = this.el.find('.' + id + ' > select > option');
|
||||
var options = this.$el.find('.' + id + ' > select > option');
|
||||
if (options){
|
||||
options.each(function(opt){
|
||||
if (this.value == value) {
|
||||
|
||||
@ -5,6 +5,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
// ## MultiView
|
||||
//
|
||||
// Manage multiple views together along with query editor etc. Usage:
|
||||
@ -129,7 +130,6 @@ my.MultiView = Backbone.View.extend({
|
||||
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
this._setupState(options.state);
|
||||
|
||||
// Hash of 'page' views (i.e. those for whole page) keyed by page name
|
||||
@ -199,43 +199,39 @@ my.MultiView = Backbone.View.extend({
|
||||
}
|
||||
this._showHideSidebar();
|
||||
|
||||
this.model.bind('query:start', function() {
|
||||
self.notify({loader: true, persist: true});
|
||||
});
|
||||
this.model.bind('query:done', function() {
|
||||
self.clearNotifications();
|
||||
self.el.find('.doc-count').text(self.model.recordCount || 'Unknown');
|
||||
});
|
||||
this.model.bind('query:fail', function(error) {
|
||||
self.clearNotifications();
|
||||
var msg = '';
|
||||
if (typeof(error) == 'string') {
|
||||
msg = error;
|
||||
} else if (typeof(error) == 'object') {
|
||||
if (error.title) {
|
||||
msg = error.title + ': ';
|
||||
}
|
||||
if (error.message) {
|
||||
msg += error.message;
|
||||
}
|
||||
} else {
|
||||
msg = 'There was an error querying the backend';
|
||||
this.listenTo(this.model, 'query:start', function() {
|
||||
self.notify({loader: true, persist: true});
|
||||
});
|
||||
this.listenTo(this.model, 'query:done', function() {
|
||||
self.clearNotifications();
|
||||
self.$el.find('.doc-count').text(self.model.recordCount || 'Unknown');
|
||||
});
|
||||
this.listenTo(this.model, 'query:fail', function(error) {
|
||||
self.clearNotifications();
|
||||
var msg = '';
|
||||
if (typeof(error) == 'string') {
|
||||
msg = error;
|
||||
} else if (typeof(error) == 'object') {
|
||||
if (error.title) {
|
||||
msg = error.title + ': ';
|
||||
}
|
||||
self.notify({message: msg, category: 'error', persist: true});
|
||||
});
|
||||
if (error.message) {
|
||||
msg += error.message;
|
||||
}
|
||||
} else {
|
||||
msg = 'There was an error querying the backend';
|
||||
}
|
||||
self.notify({message: msg, category: 'error', persist: true});
|
||||
});
|
||||
|
||||
// retrieve basic data like fields etc
|
||||
// note this.model and dataset returned are the same
|
||||
// TODO: set query state ...?
|
||||
this.model.queryState.set(self.state.get('query'), {silent: true});
|
||||
this.model.fetch()
|
||||
.fail(function(error) {
|
||||
self.notify({message: error.message, category: 'error', persist: true});
|
||||
});
|
||||
},
|
||||
|
||||
setReadOnly: function() {
|
||||
this.el.addClass('recline-read-only');
|
||||
this.$el.addClass('recline-read-only');
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@ -243,11 +239,11 @@ my.MultiView = Backbone.View.extend({
|
||||
tmplData.views = this.pageViews;
|
||||
tmplData.sidebarViews = this.sidebarViews;
|
||||
var template = Mustache.render(this.template, tmplData);
|
||||
$(this.el).html(template);
|
||||
this.$el.html(template);
|
||||
|
||||
// now create and append other views
|
||||
var $dataViewContainer = this.el.find('.data-view-container');
|
||||
var $dataSidebar = this.el.find('.data-view-sidebar');
|
||||
var $dataViewContainer = this.$el.find('.data-view-container');
|
||||
var $dataSidebar = this.$el.find('.data-view-sidebar');
|
||||
|
||||
// the main views
|
||||
_.each(this.pageViews, function(view, pageName) {
|
||||
@ -259,25 +255,37 @@ my.MultiView = Backbone.View.extend({
|
||||
});
|
||||
|
||||
_.each(this.sidebarViews, function(view) {
|
||||
this['$'+view.id] = view.view.el;
|
||||
this['$'+view.id] = view.view.$el;
|
||||
$dataSidebar.append(view.view.el);
|
||||
}, this);
|
||||
|
||||
var pager = new recline.View.Pager({
|
||||
this.pager = new recline.View.Pager({
|
||||
model: this.model.queryState
|
||||
});
|
||||
this.el.find('.recline-results-info').after(pager.el);
|
||||
this.$el.find('.recline-results-info').after(this.pager.el);
|
||||
|
||||
var queryEditor = new recline.View.QueryEditor({
|
||||
this.queryEditor = new recline.View.QueryEditor({
|
||||
model: this.model.queryState
|
||||
});
|
||||
this.el.find('.query-editor-here').append(queryEditor.el);
|
||||
this.$el.find('.query-editor-here').append(this.queryEditor.el);
|
||||
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
_.each(this.pageViews, function (view) {
|
||||
view.view.remove();
|
||||
});
|
||||
_.each(this.sidebarViews, function (view) {
|
||||
view.view.remove();
|
||||
});
|
||||
this.pager.remove();
|
||||
this.queryEditor.remove();
|
||||
Backbone.View.prototype.remove.apply(this, arguments);
|
||||
},
|
||||
|
||||
// hide the sidebar if empty
|
||||
_showHideSidebar: function() {
|
||||
var $dataSidebar = this.el.find('.data-view-sidebar');
|
||||
var $dataSidebar = this.$el.find('.data-view-sidebar');
|
||||
var visibleChildren = $dataSidebar.children().filter(function() {
|
||||
return $(this).css("display") != "none";
|
||||
}).length;
|
||||
@ -290,19 +298,19 @@ my.MultiView = Backbone.View.extend({
|
||||
},
|
||||
|
||||
updateNav: function(pageName) {
|
||||
this.el.find('.navigation a').removeClass('active');
|
||||
var $el = this.el.find('.navigation a[data-view="' + pageName + '"]');
|
||||
this.$el.find('.navigation a').removeClass('active');
|
||||
var $el = this.$el.find('.navigation a[data-view="' + pageName + '"]');
|
||||
$el.addClass('active');
|
||||
|
||||
// add/remove sidebars and hide inactive views
|
||||
_.each(this.pageViews, function(view, idx) {
|
||||
if (view.id === pageName) {
|
||||
view.view.el.show();
|
||||
view.view.$el.show();
|
||||
if (view.view.elSidebar) {
|
||||
view.view.elSidebar.show();
|
||||
}
|
||||
} else {
|
||||
view.view.el.hide();
|
||||
view.view.$el.hide();
|
||||
if (view.view.elSidebar) {
|
||||
view.view.elSidebar.hide();
|
||||
}
|
||||
@ -371,7 +379,7 @@ my.MultiView = Backbone.View.extend({
|
||||
_bindStateChanges: function() {
|
||||
var self = this;
|
||||
// finally ensure we update our state object when state of sub-object changes so that state is always up to date
|
||||
this.model.queryState.bind('change', function() {
|
||||
this.listenTo(this.model.queryState, 'change', function() {
|
||||
self.state.set({query: self.model.queryState.toJSON()});
|
||||
});
|
||||
_.each(this.pageViews, function(pageView) {
|
||||
@ -379,7 +387,7 @@ my.MultiView = Backbone.View.extend({
|
||||
var update = {};
|
||||
update['view-' + pageView.id] = pageView.view.state.toJSON();
|
||||
self.state.set(update);
|
||||
pageView.view.state.bind('change', function() {
|
||||
self.listenTo(pageView.view.state, 'change', function() {
|
||||
var update = {};
|
||||
update['view-' + pageView.id] = pageView.view.state.toJSON();
|
||||
// had problems where change not being triggered for e.g. grid view so let's do it explicitly
|
||||
@ -393,7 +401,7 @@ my.MultiView = Backbone.View.extend({
|
||||
_bindFlashNotifications: function() {
|
||||
var self = this;
|
||||
_.each(this.pageViews, function(pageView) {
|
||||
pageView.view.bind('recline:flash', function(flash) {
|
||||
self.listenTo(pageView.view, 'recline:flash', function(flash) {
|
||||
self.notify(flash);
|
||||
});
|
||||
});
|
||||
@ -519,7 +527,7 @@ my.parseQueryString = function(q) {
|
||||
|
||||
// Parse the query string out of the URL hash
|
||||
my.parseHashQueryString = function() {
|
||||
q = my.parseHashUrl(window.location.hash).query;
|
||||
var q = my.parseHashUrl(window.location.hash).query;
|
||||
return my.parseQueryString(q);
|
||||
};
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
// ## SlickGrid Dataset View
|
||||
//
|
||||
// Provides a tabular view on a Dataset, based on SlickGrid.
|
||||
@ -22,7 +23,11 @@ this.recline.View = this.recline.View || {};
|
||||
// model: dataset,
|
||||
// el: $el,
|
||||
// state: {
|
||||
// gridOptions: {editable: true},
|
||||
// gridOptions: {
|
||||
// editable: true,
|
||||
// enableAddRows: true
|
||||
// ...
|
||||
// },
|
||||
// columnsEditor: [
|
||||
// {column: 'date', editor: Slick.Editors.Date },
|
||||
// {column: 'title', editor: Slick.Editors.Text}
|
||||
@ -33,13 +38,10 @@ this.recline.View = this.recline.View || {};
|
||||
my.SlickGrid = Backbone.View.extend({
|
||||
initialize: function(modelEtc) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
this.el.addClass('recline-slickgrid');
|
||||
_.bindAll(this, 'render');
|
||||
this.model.records.bind('add', this.render);
|
||||
this.model.records.bind('reset', this.render);
|
||||
this.model.records.bind('remove', this.render);
|
||||
this.model.records.bind('change', this.onRecordChanged, this);
|
||||
this.$el.addClass('recline-slickgrid');
|
||||
_.bindAll(this, 'render', 'onRecordChanged');
|
||||
this.listenTo(this.model.records, 'add remove reset', this.render);
|
||||
this.listenTo(this.model.records, 'change', this.onRecordChanged);
|
||||
|
||||
var state = _.extend({
|
||||
hiddenColumns: [],
|
||||
@ -53,6 +55,8 @@ my.SlickGrid = Backbone.View.extend({
|
||||
|
||||
);
|
||||
this.state = new recline.Model.ObjectState(state);
|
||||
|
||||
this._slickHandler = new Slick.EventHandler();
|
||||
},
|
||||
|
||||
events: {
|
||||
@ -113,12 +117,30 @@ my.SlickGrid = Backbone.View.extend({
|
||||
var editInfo = _.find(self.state.get('columnsEditor'),function(c){return c.column === field.id;});
|
||||
if (editInfo){
|
||||
column.editor = editInfo.editor;
|
||||
} else {
|
||||
// guess editor type
|
||||
var typeToEditorMap = {
|
||||
'string': Slick.Editors.LongText,
|
||||
'integer': Slick.Editors.IntegerEditor,
|
||||
'number': Slick.Editors.Text,
|
||||
// TODO: need a way to ensure we format date in the right way
|
||||
// Plus what if dates are in distant past or future ... (?)
|
||||
// 'date': Slick.Editors.DateEditor,
|
||||
'date': Slick.Editors.Text,
|
||||
'boolean': Slick.Editors.YesNoSelectEditor
|
||||
// TODO: (?) percent ...
|
||||
};
|
||||
if (field.type in typeToEditorMap) {
|
||||
column.editor = typeToEditorMap[field.type]
|
||||
} else {
|
||||
column.editor = Slick.Editors.LongText;
|
||||
}
|
||||
}
|
||||
columns.push(column);
|
||||
});
|
||||
|
||||
// Restrict the visible columns
|
||||
var visibleColumns = columns.filter(function(column) {
|
||||
var visibleColumns = _.filter(columns, function(column) {
|
||||
return _.indexOf(self.state.get('hiddenColumns'), column.id) === -1;
|
||||
});
|
||||
|
||||
@ -164,7 +186,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
this.getItem = function(index) {return rows[index];};
|
||||
this.getItemMetadata = function(index) {return {};};
|
||||
this.getModel = function(index) {return models[index];};
|
||||
this.getModelRow = function(m) {return models.indexOf(m);};
|
||||
this.getModelRow = function(m) {return _.indexOf(models, m);};
|
||||
this.updateItem = function(m,i) {
|
||||
rows[i] = toRow(m);
|
||||
models[i] = m;
|
||||
@ -187,7 +209,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
this.grid.setSortColumn(column, sortAsc);
|
||||
}
|
||||
|
||||
this.grid.onSort.subscribe(function(e, args){
|
||||
this._slickHandler.subscribe(this.grid.onSort, function(e, args){
|
||||
var order = (args.sortAsc) ? 'asc':'desc';
|
||||
var sort = [{
|
||||
field: args.sortCol.field,
|
||||
@ -196,7 +218,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
self.model.query({sort: sort});
|
||||
});
|
||||
|
||||
this.grid.onColumnsReordered.subscribe(function(e, args){
|
||||
this._slickHandler.subscribe(this.grid.onColumnsReordered, function(e, args){
|
||||
self.state.set({columnsOrder: _.pluck(self.grid.getColumns(),'id')});
|
||||
});
|
||||
|
||||
@ -212,7 +234,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
self.state.set({columnsWidth:columnsWidth});
|
||||
});
|
||||
|
||||
this.grid.onCellChange.subscribe(function (e, args) {
|
||||
this._slickHandler.subscribe(this.grid.onCellChange, function (e, args) {
|
||||
// We need to change the model associated value
|
||||
//
|
||||
var grid = args.grid;
|
||||
@ -235,7 +257,12 @@ my.SlickGrid = Backbone.View.extend({
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
this._slickHandler.unsubscribeAll();
|
||||
Backbone.View.prototype.remove.apply(this, arguments);
|
||||
},
|
||||
|
||||
show: function() {
|
||||
// If the div is hidden, SlickGrid will calculate wrongly some
|
||||
|
||||
@ -4,6 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
// turn off unnecessary logging from VMM Timeline
|
||||
if (typeof VMM !== 'undefined') {
|
||||
VMM.debug = false;
|
||||
@ -27,18 +28,20 @@ my.Timeline = Backbone.View.extend({
|
||||
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
this.timeline = new VMM.Timeline();
|
||||
this.timeline = new VMM.Timeline(this.elementId);
|
||||
this._timelineIsInitialized = false;
|
||||
this.model.fields.bind('reset', function() {
|
||||
this.listenTo(this.model.fields, 'reset', function() {
|
||||
self._setupTemporalField();
|
||||
});
|
||||
this.model.records.bind('all', function() {
|
||||
this.listenTo(this.model.records, 'all', function() {
|
||||
self.reloadData();
|
||||
});
|
||||
var stateData = _.extend({
|
||||
startField: null,
|
||||
endField: null,
|
||||
// by default timelinejs (and browsers) will parse ambiguous dates in US format (mm/dd/yyyy)
|
||||
// set to true to interpret dd/dd/dddd as dd/mm/yyyy
|
||||
nonUSDates: false,
|
||||
timelineJSOptions: {}
|
||||
},
|
||||
options.state
|
||||
@ -50,7 +53,7 @@ my.Timeline = Backbone.View.extend({
|
||||
render: function() {
|
||||
var tmplData = {};
|
||||
var htmls = Mustache.render(this.template, tmplData);
|
||||
this.el.html(htmls);
|
||||
this.$el.html(htmls);
|
||||
// can only call _initTimeline once view in DOM as Timeline uses $
|
||||
// internally to look up element
|
||||
if ($(this.elementId).length > 0) {
|
||||
@ -66,9 +69,10 @@ my.Timeline = Backbone.View.extend({
|
||||
},
|
||||
|
||||
_initTimeline: function() {
|
||||
var $timeline = this.el.find(this.elementId);
|
||||
var data = this._timelineJSON();
|
||||
this.timeline.init(data, this.elementId, this.state.get("timelineJSOptions"));
|
||||
var config = this.state.get("timelineJSOptions");
|
||||
config.id = this.elementId;
|
||||
this.timeline.init(config, data);
|
||||
this._timelineIsInitialized = true
|
||||
},
|
||||
|
||||
@ -130,19 +134,33 @@ my.Timeline = Backbone.View.extend({
|
||||
return out;
|
||||
},
|
||||
|
||||
// convert dates into a format TimelineJS will handle
|
||||
// TimelineJS does not document this at all so combo of read the code +
|
||||
// trial and error
|
||||
// Summary (AFAICt):
|
||||
// Preferred: [-]yyyy[,mm,dd,hh,mm,ss]
|
||||
// Supported: mm/dd/yyyy
|
||||
_parseDate: function(date) {
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
var out = date.trim();
|
||||
var out = $.trim(date);
|
||||
out = out.replace(/(\d)th/g, '$1');
|
||||
out = out.replace(/(\d)st/g, '$1');
|
||||
out = out.trim() ? moment(out) : null;
|
||||
if (out.toDate() == 'Invalid Date') {
|
||||
return null;
|
||||
} else {
|
||||
return out.toDate();
|
||||
out = $.trim(out);
|
||||
if (out.match(/\d\d\d\d-\d\d-\d\d(T.*)?/)) {
|
||||
out = out.replace(/-/g, ',').replace('T', ',').replace(':',',');
|
||||
}
|
||||
if (out.match(/\d\d-\d\d-\d\d.*/)) {
|
||||
out = out.replace(/-/g, '/');
|
||||
}
|
||||
if (this.state.get('nonUSDates')) {
|
||||
var parts = out.match(/(\d\d)\/(\d\d)\/(\d\d.*)/);
|
||||
if (parts) {
|
||||
out = [parts[2], parts[1], parts[3]].join('/');
|
||||
}
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
_setupTemporalField: function() {
|
||||
|
||||
@ -4,6 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
|
||||
// ## FacetViewer
|
||||
//
|
||||
@ -41,9 +42,8 @@ my.FacetViewer = Backbone.View.extend({
|
||||
},
|
||||
initialize: function(model) {
|
||||
_.bindAll(this, 'render');
|
||||
this.el = $(this.el);
|
||||
this.model.facets.bind('all', this.render);
|
||||
this.model.fields.bind('all', this.render);
|
||||
this.listenTo(this.model.facets, 'all', this.render);
|
||||
this.listenTo(this.model.fields, 'all', this.render);
|
||||
this.render();
|
||||
},
|
||||
render: function() {
|
||||
@ -60,17 +60,17 @@ my.FacetViewer = Backbone.View.extend({
|
||||
return facet;
|
||||
});
|
||||
var templated = Mustache.render(this.template, tmplData);
|
||||
this.el.html(templated);
|
||||
this.$el.html(templated);
|
||||
// are there actually any facets to show?
|
||||
if (this.model.facets.length > 0) {
|
||||
this.el.show();
|
||||
this.$el.show();
|
||||
} else {
|
||||
this.el.hide();
|
||||
this.$el.hide();
|
||||
}
|
||||
},
|
||||
onHide: function(e) {
|
||||
e.preventDefault();
|
||||
this.el.hide();
|
||||
this.$el.hide();
|
||||
},
|
||||
onFacetFilter: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
@ -20,7 +20,8 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
|
||||
"use strict";
|
||||
|
||||
my.Fields = Backbone.View.extend({
|
||||
className: 'recline-fields-view',
|
||||
template: ' \
|
||||
@ -59,13 +60,12 @@ my.Fields = Backbone.View.extend({
|
||||
|
||||
initialize: function(model) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
_.bindAll(this, 'render');
|
||||
|
||||
// TODO: this is quite restrictive in terms of when it is re-run
|
||||
// e.g. a change in type will not trigger a re-run atm.
|
||||
// being more liberal (e.g. binding to all) can lead to being called a lot (e.g. for change:width)
|
||||
this.model.fields.bind('reset', function(action) {
|
||||
this.listenTo(this.model.fields, 'reset', function(action) {
|
||||
self.model.fields.each(function(field) {
|
||||
field.facets.unbind('all', self.render);
|
||||
field.facets.bind('all', self.render);
|
||||
@ -74,7 +74,7 @@ my.Fields = Backbone.View.extend({
|
||||
self.model.getFieldsSummary();
|
||||
self.render();
|
||||
});
|
||||
this.el.find('.collapse').collapse();
|
||||
this.$el.find('.collapse').collapse();
|
||||
this.render();
|
||||
},
|
||||
render: function() {
|
||||
@ -88,7 +88,7 @@ my.Fields = Backbone.View.extend({
|
||||
tmplData.fields.push(out);
|
||||
});
|
||||
var templated = Mustache.render(this.template, tmplData);
|
||||
this.el.html(templated);
|
||||
this.$el.html(templated);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
|
||||
my.FilterEditor = Backbone.View.extend({
|
||||
className: 'recline-filter-editor well',
|
||||
@ -58,9 +59,9 @@ my.FilterEditor = Backbone.View.extend({
|
||||
<a class="js-remove-filter" href="#" title="Remove this filter" data-filter-id="{{id}}">×</a> \
|
||||
</legend> \
|
||||
<label class="control-label" for="">From</label> \
|
||||
<input type="text" value="{{start}}" name="start" data-filter-field="{{field}}" data-filter-id="{{id}}" data-filter-type="{{type}}" /> \
|
||||
<input type="text" value="{{from}}" name="from" data-filter-field="{{field}}" data-filter-id="{{id}}" data-filter-type="{{type}}" /> \
|
||||
<label class="control-label" for="">To</label> \
|
||||
<input type="text" value="{{stop}}" name="stop" data-filter-field="{{field}}" data-filter-id="{{id}}" data-filter-type="{{type}}" /> \
|
||||
<input type="text" value="{{to}}" name="to" data-filter-field="{{field}}" data-filter-id="{{id}}" data-filter-type="{{type}}" /> \
|
||||
</fieldset> \
|
||||
</div> \
|
||||
',
|
||||
@ -88,11 +89,9 @@ my.FilterEditor = Backbone.View.extend({
|
||||
'submit form.js-add': 'onAddFilter'
|
||||
},
|
||||
initialize: function() {
|
||||
this.el = $(this.el);
|
||||
_.bindAll(this, 'render');
|
||||
this.model.fields.bind('all', this.render);
|
||||
this.model.queryState.bind('change', this.render);
|
||||
this.model.queryState.bind('change:filters:new-blank', this.render);
|
||||
this.listenTo(this.model.fields, 'all', this.render);
|
||||
this.listenTo(this.model.queryState, 'change change:filters:new-blank', this.render);
|
||||
this.render();
|
||||
},
|
||||
render: function() {
|
||||
@ -108,13 +107,13 @@ my.FilterEditor = Backbone.View.extend({
|
||||
return Mustache.render(self.filterTemplates[this.type], this);
|
||||
};
|
||||
var out = Mustache.render(this.template, tmplData);
|
||||
this.el.html(out);
|
||||
this.$el.html(out);
|
||||
},
|
||||
onAddFilterShow: function(e) {
|
||||
e.preventDefault();
|
||||
var $target = $(e.target);
|
||||
$target.hide();
|
||||
this.el.find('form.js-add').show();
|
||||
this.$el.find('form.js-add').show();
|
||||
},
|
||||
onAddFilter: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
@ -4,6 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
|
||||
my.Pager = Backbone.View.extend({
|
||||
className: 'recline-pager',
|
||||
@ -24,14 +25,13 @@ my.Pager = Backbone.View.extend({
|
||||
|
||||
initialize: function() {
|
||||
_.bindAll(this, 'render');
|
||||
this.el = $(this.el);
|
||||
this.model.bind('change', this.render);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.render();
|
||||
},
|
||||
onFormSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var newFrom = parseInt(this.el.find('input[name="from"]').val());
|
||||
var newSize = parseInt(this.el.find('input[name="to"]').val()) - newFrom;
|
||||
var newFrom = parseInt(this.$el.find('input[name="from"]').val());
|
||||
var newSize = parseInt(this.$el.find('input[name="to"]').val()) - newFrom;
|
||||
newFrom = Math.max(newFrom, 0);
|
||||
newSize = Math.max(newSize, 1);
|
||||
this.model.set({size: newSize, from: newFrom});
|
||||
@ -52,7 +52,7 @@ my.Pager = Backbone.View.extend({
|
||||
var tmplData = this.model.toJSON();
|
||||
tmplData.to = this.model.get('from') + this.model.get('size');
|
||||
var templated = Mustache.render(this.template, tmplData);
|
||||
this.el.html(templated);
|
||||
this.$el.html(templated);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
|
||||
my.QueryEditor = Backbone.View.extend({
|
||||
className: 'recline-query-editor',
|
||||
@ -23,19 +24,18 @@ my.QueryEditor = Backbone.View.extend({
|
||||
|
||||
initialize: function() {
|
||||
_.bindAll(this, 'render');
|
||||
this.el = $(this.el);
|
||||
this.model.bind('change', this.render);
|
||||
this.listenTo(this.model, 'change', this.render);
|
||||
this.render();
|
||||
},
|
||||
onFormSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
var query = this.el.find('.text-query input').val();
|
||||
var query = this.$el.find('.text-query input').val();
|
||||
this.model.set({q: query});
|
||||
},
|
||||
render: function() {
|
||||
var tmplData = this.model.toJSON();
|
||||
var templated = Mustache.render(this.template, tmplData);
|
||||
this.el.html(templated);
|
||||
this.$el.html(templated);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ this.recline = this.recline || {};
|
||||
this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
|
||||
my.ValueFilter = Backbone.View.extend({
|
||||
className: 'recline-filter-editor well',
|
||||
@ -50,11 +51,9 @@ my.ValueFilter = Backbone.View.extend({
|
||||
'submit form.js-add': 'onAddFilter'
|
||||
},
|
||||
initialize: function() {
|
||||
this.el = $(this.el);
|
||||
_.bindAll(this, 'render');
|
||||
this.model.fields.bind('all', this.render);
|
||||
this.model.queryState.bind('change', this.render);
|
||||
this.model.queryState.bind('change:filters:new-blank', this.render);
|
||||
this.listenTo(this.model.fields, 'all', this.render);
|
||||
this.listenTo(this.model.queryState, 'change change:filters:new-blank', this.render);
|
||||
this.render();
|
||||
},
|
||||
render: function() {
|
||||
@ -70,7 +69,7 @@ my.ValueFilter = Backbone.View.extend({
|
||||
return Mustache.render(self.filterTemplates.term, this);
|
||||
};
|
||||
var out = Mustache.render(this.template, tmplData);
|
||||
this.el.html(out);
|
||||
this.$el.html(out);
|
||||
},
|
||||
updateFilter: function(input) {
|
||||
var self = this;
|
||||
@ -84,7 +83,7 @@ my.ValueFilter = Backbone.View.extend({
|
||||
e.preventDefault();
|
||||
var $target = $(e.target);
|
||||
$target.hide();
|
||||
this.el.find('form.js-add').show();
|
||||
this.$el.find('form.js-add').show();
|
||||
},
|
||||
onAddFilter: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
@ -64,6 +64,19 @@ test("parseCSV - quotechar", function() {
|
||||
|
||||
});
|
||||
|
||||
test("parseCSV skipInitialRows", function() {
|
||||
var csv = '"Jones, Jay",10\n' +
|
||||
'"Xyz ""ABC"" O\'Brien",11:35\n' +
|
||||
'"Other, AN",12:35\n';
|
||||
|
||||
var array = recline.Backend.CSV.parseCSV(csv, {skipInitialRows: 1});
|
||||
var exp = [
|
||||
['Xyz "ABC" O\'Brien', '11:35' ],
|
||||
['Other, AN', '12:35' ]
|
||||
];
|
||||
deepEqual(exp, array);
|
||||
});
|
||||
|
||||
test("serializeCSV - Array", function() {
|
||||
var csv = [
|
||||
['Jones, Jay', 10],
|
||||
|
||||
@ -1,353 +0,0 @@
|
||||
(function ($) {
|
||||
module("Backend ElasticSearch - Wrapper");
|
||||
|
||||
test("queryNormalize", function() {
|
||||
var backend = new recline.Backend.ElasticSearch.Wrapper();
|
||||
|
||||
var in_ = new recline.Model.Query();
|
||||
var out = backend._normalizeQuery(in_);
|
||||
var exp = {
|
||||
constant_score: {
|
||||
query: {
|
||||
match_all: {}
|
||||
}
|
||||
}
|
||||
};
|
||||
deepEqual(out, exp);
|
||||
|
||||
var in_ = new recline.Model.Query();
|
||||
in_.set({q: ''});
|
||||
var out = backend._normalizeQuery(in_);
|
||||
deepEqual(out, exp);
|
||||
|
||||
var in_ = new recline.Model.Query();
|
||||
in_.attributes.q = 'abc';
|
||||
var out = backend._normalizeQuery(in_);
|
||||
equal(out.constant_score.query.query_string.query, 'abc');
|
||||
|
||||
var in_ = new recline.Model.Query();
|
||||
in_.addFilter({
|
||||
type: 'term',
|
||||
field: 'xyz',
|
||||
term: 'XXX'
|
||||
});
|
||||
var out = backend._normalizeQuery(in_);
|
||||
var exp = {
|
||||
constant_score: {
|
||||
query: {
|
||||
match_all: {}
|
||||
},
|
||||
filter: {
|
||||
and: [
|
||||
{
|
||||
term: {
|
||||
xyz: 'xxx'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
deepEqual(out, exp);
|
||||
|
||||
var in_ = new recline.Model.Query();
|
||||
in_.addFilter({
|
||||
type: 'geo_distance',
|
||||
field: 'xyz'
|
||||
});
|
||||
var out = backend._normalizeQuery(in_);
|
||||
var exp = {
|
||||
constant_score: {
|
||||
query: {
|
||||
match_all: {}
|
||||
},
|
||||
filter: {
|
||||
and: [
|
||||
{
|
||||
geo_distance: {
|
||||
distance: 10,
|
||||
unit: 'km',
|
||||
'xyz': { lon: 0, lat: 0 }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
deepEqual(out, exp);
|
||||
});
|
||||
|
||||
var mapping_data = {
|
||||
"note": {
|
||||
"properties": {
|
||||
"_created": {
|
||||
"format": "dateOptionalTime",
|
||||
"type": "date"
|
||||
},
|
||||
"_last_modified": {
|
||||
"format": "dateOptionalTime",
|
||||
"type": "date"
|
||||
},
|
||||
"end": {
|
||||
"type": "string"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"start": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var sample_data = {
|
||||
"_shards": {
|
||||
"failed": 0,
|
||||
"successful": 5,
|
||||
"total": 5
|
||||
},
|
||||
"hits": {
|
||||
"hits": [
|
||||
{
|
||||
"_id": "u3rpLyuFS3yLNXrtxWkMwg",
|
||||
"_index": "hypernotes",
|
||||
"_score": 1.0,
|
||||
"_source": {
|
||||
"_created": "2012-02-24T17:53:57.286Z",
|
||||
"_last_modified": "2012-02-24T17:53:57.286Z",
|
||||
"owner": "tester",
|
||||
"title": "Note 1"
|
||||
},
|
||||
"_type": "note"
|
||||
},
|
||||
{
|
||||
"_id": "n7JMkFOHSASJCVTXgcpqkA",
|
||||
"_index": "hypernotes",
|
||||
"_score": 1.0,
|
||||
"_source": {
|
||||
"_created": "2012-02-24T17:53:57.290Z",
|
||||
"_last_modified": "2012-02-24T17:53:57.290Z",
|
||||
"owner": "tester",
|
||||
"title": "Note 3"
|
||||
},
|
||||
"_type": "note"
|
||||
},
|
||||
{
|
||||
"_id": "g7UMA55gTJijvsB3dFitzw",
|
||||
"_index": "hypernotes",
|
||||
"_score": 1.0,
|
||||
"_source": {
|
||||
"_created": "2012-02-24T17:53:57.289Z",
|
||||
"_last_modified": "2012-02-24T17:53:57.289Z",
|
||||
"owner": "tester",
|
||||
"title": "Note 2"
|
||||
},
|
||||
"_type": "note"
|
||||
}
|
||||
],
|
||||
"max_score": 1.0,
|
||||
"total": 3
|
||||
},
|
||||
"timed_out": false,
|
||||
"took": 2
|
||||
};
|
||||
|
||||
test("query", function() {
|
||||
var backend = new recline.Backend.ElasticSearch.Wrapper('https://localhost:9200/my-es-db/my-es-type');
|
||||
|
||||
var stub = sinon.stub($, 'ajax', function(options) {
|
||||
if (options.url.indexOf('_mapping') != -1) {
|
||||
return {
|
||||
done: function(callback) {
|
||||
callback(mapping_data);
|
||||
return this;
|
||||
},
|
||||
fail: function() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
done: function(callback) {
|
||||
callback(sample_data);
|
||||
return this;
|
||||
},
|
||||
fail: function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
backend.mapping().done(function(data) {
|
||||
var fields = _.keys(data.note.properties);
|
||||
deepEqual(['_created', '_last_modified', 'end', 'owner', 'start', 'title'], fields);
|
||||
});
|
||||
|
||||
backend.query().done(function(queryResult) {
|
||||
equal(3, queryResult.hits.total);
|
||||
equal(3, queryResult.hits.hits.length);
|
||||
equal('Note 1', queryResult.hits.hits[0]._source['title']);
|
||||
start();
|
||||
});
|
||||
$.ajax.restore();
|
||||
});
|
||||
|
||||
// DISABLED - this test requires ElasticSearch to be running locally
|
||||
// test("write", function() {
|
||||
// var url = 'http://localhost:9200/recline-test/es-write';
|
||||
// var backend = new recline.Backend.ElasticSearch.Wrapper(url);
|
||||
// stop();
|
||||
//
|
||||
// var id = parseInt(Math.random()*100000000).toString();
|
||||
// var rec = {
|
||||
// id: id,
|
||||
// title: 'my title'
|
||||
// };
|
||||
// var jqxhr = backend.upsert(rec);
|
||||
// jqxhr.done(function(data) {
|
||||
// ok(data.ok);
|
||||
// equal(data._id, id);
|
||||
// equal(data._type, 'es-write');
|
||||
// equal(data._version, 1);
|
||||
//
|
||||
// // update
|
||||
// rec.title = 'new title';
|
||||
// var jqxhr = backend.upsert(rec);
|
||||
// jqxhr.done(function(data) {
|
||||
// equal(data._version, 2);
|
||||
//
|
||||
// // delete
|
||||
// var jqxhr = backend.remove(rec.id);
|
||||
// jqxhr.done(function(data) {
|
||||
// ok(data.ok);
|
||||
// rec = null;
|
||||
//
|
||||
// // try to get ...
|
||||
// var jqxhr = backend.get(id);
|
||||
// jqxhr.done(function(data) {
|
||||
// // should not be here
|
||||
// ok(false, 'Should have got 404');
|
||||
// }).error(function(error) {
|
||||
// equal(error.status, 404);
|
||||
// start();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// }).fail(function(error) {
|
||||
// console.log(error);
|
||||
// ok(false, 'Basic request failed - is ElasticSearch running locally on port 9200 (required for this test!)');
|
||||
// start();
|
||||
// });
|
||||
// });
|
||||
|
||||
|
||||
// ==================================================
|
||||
|
||||
module("Backend ElasticSearch - Recline");
|
||||
|
||||
test("query", function() {
|
||||
var dataset = new recline.Model.Dataset({
|
||||
url: 'https://localhost:9200/my-es-db/my-es-type',
|
||||
backend: 'elasticsearch'
|
||||
});
|
||||
|
||||
var stub = sinon.stub($, 'ajax', function(options) {
|
||||
if (options.url.indexOf('_mapping') != -1) {
|
||||
return {
|
||||
done: function(callback) {
|
||||
callback(mapping_data);
|
||||
return this;
|
||||
},
|
||||
fail: function() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
done: function(callback) {
|
||||
callback(sample_data);
|
||||
return this;
|
||||
},
|
||||
fail: function() {
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
dataset.fetch().done(function(dataset) {
|
||||
deepEqual(['_created', '_last_modified', 'end', 'owner', 'start', 'title'], _.pluck(dataset.fields.toJSON(), 'id'));
|
||||
dataset.query().then(function(recList) {
|
||||
equal(3, dataset.recordCount);
|
||||
equal(3, recList.length);
|
||||
equal('Note 1', recList.models[0].get('title'));
|
||||
start();
|
||||
});
|
||||
});
|
||||
$.ajax.restore();
|
||||
});
|
||||
|
||||
// DISABLED - this test requires ElasticSearch to be running locally
|
||||
// test("write", function() {
|
||||
// var dataset = new recline.Model.Dataset({
|
||||
// url: 'http://localhost:9200/recline-test/es-write',
|
||||
// backend: 'elasticsearch'
|
||||
// });
|
||||
//
|
||||
// stop();
|
||||
//
|
||||
// var id = parseInt(Math.random()*100000000).toString();
|
||||
// var rec = new recline.Model.Record({
|
||||
// id: id,
|
||||
// title: 'my title'
|
||||
// });
|
||||
// dataset.records.add(rec);
|
||||
// // have to do this explicitly as we not really supporting adding new items atm
|
||||
// dataset._changes.creates.push(rec.toJSON());
|
||||
// var jqxhr = dataset.save();
|
||||
// jqxhr.done(function(data) {
|
||||
// ok(data.ok);
|
||||
// equal(data._id, id);
|
||||
// equal(data._type, 'es-write');
|
||||
// equal(data._version, 1);
|
||||
//
|
||||
// // update
|
||||
// rec.set({title: 'new title'});
|
||||
// // again set up by hand ...
|
||||
// dataset._changes.creates = [];
|
||||
// dataset._changes.updates.push(rec.toJSON());
|
||||
// var jqxhr = dataset.save();
|
||||
// jqxhr.done(function(data) {
|
||||
// equal(data._version, 2);
|
||||
//
|
||||
// // delete
|
||||
// dataset._changes.updates = 0;
|
||||
// dataset._changes.deletes.push(rec.toJSON());
|
||||
// var jqxhr = dataset.save();
|
||||
// jqxhr.done(function(data) {
|
||||
// ok(data.ok);
|
||||
// rec = null;
|
||||
//
|
||||
// // try to get ...
|
||||
// var es = new recline.Backend.ElasticSearch.Wrapper(dataset.get('url'));
|
||||
// var jqxhr = es.get(id);
|
||||
// jqxhr.done(function(data) {
|
||||
// // should not be here
|
||||
// ok(false, 'Should have got 404');
|
||||
// }).error(function(error) {
|
||||
// equal(error.status, 404);
|
||||
// start();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// }).fail(function(error) {
|
||||
// console.log(error);
|
||||
// ok(false, 'Basic request failed - is ElasticSearch running locally on port 9200 (required for this test!)');
|
||||
// start();
|
||||
// });
|
||||
// });
|
||||
|
||||
})(this.jQuery);
|
||||
@ -1,320 +0,0 @@
|
||||
(function ($) {
|
||||
module("Backend GDocs");
|
||||
|
||||
var sampleGDocsSpreadsheetMetadata = {
|
||||
feed: {
|
||||
category: [
|
||||
{
|
||||
term: "http://schemas.google.com/spreadsheets/2006#worksheet",
|
||||
scheme: "http://schemas.google.com/spreadsheets/2006"
|
||||
}
|
||||
],
|
||||
updated: {
|
||||
$t: "2010-07-13T09:57:28.408Z"
|
||||
},
|
||||
xmlns: "http://www.w3.org/2005/Atom",
|
||||
title: {
|
||||
$t: "javascript-test",
|
||||
type: "text"
|
||||
},
|
||||
author: [
|
||||
{
|
||||
name: {
|
||||
$t: "okfn.rufus.pollock"
|
||||
},
|
||||
email: {
|
||||
$t: "okfn.rufus.pollock@gmail.com"
|
||||
}
|
||||
}
|
||||
],
|
||||
openSearch$startIndex: {
|
||||
$t: "1"
|
||||
},
|
||||
xmlns$gs: "http://schemas.google.com/spreadsheets/2006",
|
||||
xmlns$openSearch: "http://a9.com/-/spec/opensearchrss/1.0/",
|
||||
entry: [
|
||||
{
|
||||
category: [
|
||||
{
|
||||
term: "http://schemas.google.com/spreadsheets/2006#worksheet",
|
||||
scheme: "http://schemas.google.com/spreadsheets/2006"
|
||||
}
|
||||
],
|
||||
updated: {
|
||||
$t: "2010-07-13T09:57:28.408Z"
|
||||
},
|
||||
title: {
|
||||
$t: "Sheet1",
|
||||
type: "text"
|
||||
},
|
||||
content: {
|
||||
$t: "Sheet1",
|
||||
type: "text"
|
||||
},
|
||||
link: [
|
||||
{
|
||||
href: "https://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/basic",
|
||||
type: "application/atom+xml",
|
||||
rel: "http://schemas.google.com/spreadsheets/2006#listfeed"
|
||||
},
|
||||
{
|
||||
href: "https://spreadsheets.google.com/feeds/cells/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/basic",
|
||||
type: "application/atom+xml",
|
||||
rel: "http://schemas.google.com/spreadsheets/2006#cellsfeed"
|
||||
},
|
||||
{
|
||||
href: "https://spreadsheets.google.com/tq?key=0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc&sheet=od6&pub=1",
|
||||
type: "application/atom+xml",
|
||||
rel: "http://schemas.google.com/visualization/2008#visualizationApi"
|
||||
},
|
||||
{
|
||||
href: "https://spreadsheets.google.com/feeds/worksheets/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/public/basic/od6",
|
||||
type: "application/atom+xml",
|
||||
rel: "self"
|
||||
}
|
||||
],
|
||||
id: {
|
||||
$t: "https://spreadsheets.google.com/feeds/worksheets/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/public/basic/od6"
|
||||
}
|
||||
}
|
||||
],
|
||||
link: [
|
||||
{
|
||||
href: "https://spreadsheets.google.com/pub?key=0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc",
|
||||
type: "text/html",
|
||||
rel: "alternate"
|
||||
},
|
||||
{
|
||||
href: "https://spreadsheets.google.com/feeds/worksheets/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/public/basic",
|
||||
type: "application/atom+xml",
|
||||
rel: "http://schemas.google.com/g/2005#feed"
|
||||
},
|
||||
{
|
||||
href: "https://spreadsheets.google.com/feeds/worksheets/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/public/basic?alt=json",
|
||||
type: "application/atom+xml",
|
||||
rel: "self"
|
||||
}
|
||||
],
|
||||
openSearch$totalResults: {
|
||||
$t: "1"
|
||||
},
|
||||
id: {
|
||||
$t: "https://spreadsheets.google.com/feeds/worksheets/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/public/basic"
|
||||
}
|
||||
},
|
||||
version: "1.0",
|
||||
encoding: "UTF-8"
|
||||
}
|
||||
|
||||
var sampleGDocsSpreadsheetData = {
|
||||
feed: {
|
||||
category: [
|
||||
{
|
||||
term: "http://schemas.google.com/spreadsheets/2006#list",
|
||||
scheme: "http://schemas.google.com/spreadsheets/2006"
|
||||
}
|
||||
],
|
||||
updated: {
|
||||
$t: "2010-07-12T18:32:16.200Z"
|
||||
},
|
||||
xmlns: "http://www.w3.org/2005/Atom",
|
||||
xmlns$gsx: "http://schemas.google.com/spreadsheets/2006/extended",
|
||||
title: {
|
||||
$t: "Sheet1",
|
||||
type: "text"
|
||||
},
|
||||
author: [
|
||||
{
|
||||
name: {
|
||||
$t: "okfn.rufus.pollock"
|
||||
},
|
||||
email: {
|
||||
$t: "okfn.rufus.pollock@gmail.com"
|
||||
}
|
||||
}
|
||||
],
|
||||
openSearch$startIndex: {
|
||||
$t: "1"
|
||||
},
|
||||
link: [
|
||||
{
|
||||
href: "http://spreadsheets.google.com/pub?key=0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc",
|
||||
type: "text/html",
|
||||
rel: "alternate"
|
||||
},
|
||||
{
|
||||
href: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values",
|
||||
type: "application/atom+xml",
|
||||
rel: "http://schemas.google.com/g/2005#feed"
|
||||
},
|
||||
{
|
||||
href: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values?alt=json-in-script",
|
||||
type: "application/atom+xml",
|
||||
rel: "self"
|
||||
}
|
||||
],
|
||||
xmlns$openSearch: "http://a9.com/-/spec/opensearchrss/1.0/",
|
||||
entry: [
|
||||
{
|
||||
category: [
|
||||
{
|
||||
term: "http://schemas.google.com/spreadsheets/2006#list",
|
||||
scheme: "http://schemas.google.com/spreadsheets/2006"
|
||||
}
|
||||
],
|
||||
updated: {
|
||||
$t: "2010-07-12T18:32:16.200Z"
|
||||
},
|
||||
'gsx$column-2': {
|
||||
$t: "1"
|
||||
},
|
||||
'gsx$column-1': {
|
||||
$t: "A"
|
||||
},
|
||||
title: {
|
||||
$t: "A",
|
||||
type: "text"
|
||||
},
|
||||
content: {
|
||||
$t: "column-2: 1",
|
||||
type: "text"
|
||||
},
|
||||
link: [
|
||||
{
|
||||
href: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values/cokwr",
|
||||
type: "application/atom+xml",
|
||||
rel: "self"
|
||||
}
|
||||
],
|
||||
id: {
|
||||
$t: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values/cokwr"
|
||||
}
|
||||
},
|
||||
{
|
||||
category: [
|
||||
{
|
||||
term: "http://schemas.google.com/spreadsheets/2006#list",
|
||||
scheme: "http://schemas.google.com/spreadsheets/2006"
|
||||
}
|
||||
],
|
||||
updated: {
|
||||
$t: "2010-07-12T18:32:16.200Z"
|
||||
},
|
||||
'gsx$column-2': {
|
||||
$t: "2"
|
||||
},
|
||||
'gsx$column-1': {
|
||||
$t: "b"
|
||||
},
|
||||
title: {
|
||||
$t: "b",
|
||||
type: "text"
|
||||
},
|
||||
content: {
|
||||
$t: "column-2: 2",
|
||||
type: "text"
|
||||
},
|
||||
link: [
|
||||
{
|
||||
href: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values/cpzh4",
|
||||
type: "application/atom+xml",
|
||||
rel: "self"
|
||||
}
|
||||
],
|
||||
id: {
|
||||
$t: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values/cpzh4"
|
||||
}
|
||||
},
|
||||
{
|
||||
category: [
|
||||
{
|
||||
term: "http://schemas.google.com/spreadsheets/2006#list",
|
||||
scheme: "http://schemas.google.com/spreadsheets/2006"
|
||||
}
|
||||
],
|
||||
updated: {
|
||||
$t: "2010-07-12T18:32:16.200Z"
|
||||
},
|
||||
'gsx$column-2': {
|
||||
$t: "3"
|
||||
},
|
||||
'gsx$column-1': {
|
||||
$t: "c"
|
||||
},
|
||||
title: {
|
||||
$t: "c",
|
||||
type: "text"
|
||||
},
|
||||
content: {
|
||||
$t: "column-2: 3",
|
||||
type: "text"
|
||||
},
|
||||
link: [
|
||||
{
|
||||
href: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values/cre1l",
|
||||
type: "application/atom+xml",
|
||||
rel: "self"
|
||||
}
|
||||
],
|
||||
id: {
|
||||
$t: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values/cre1l"
|
||||
}
|
||||
}
|
||||
],
|
||||
openSearch$totalResults: {
|
||||
$t: "3"
|
||||
},
|
||||
id: {
|
||||
$t: "http://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values"
|
||||
}
|
||||
},
|
||||
version: "1.0",
|
||||
encoding: "UTF-8"
|
||||
}
|
||||
|
||||
test("GDocs Backend", function() {
|
||||
var dataset = new recline.Model.Dataset({
|
||||
url: 'https://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values?alt=json',
|
||||
backend: 'gdocs'
|
||||
});
|
||||
|
||||
var stub = sinon.stub($, 'getJSON', function(options, cb) {
|
||||
var spreadsheetUrl = 'spreadsheets.google.com/feeds/worksheets/';
|
||||
var worksheetUrl = 'spreadsheets.google.com/feeds/list/';
|
||||
|
||||
if (options.indexOf(spreadsheetUrl) !== -1) {
|
||||
cb(sampleGDocsSpreadsheetMetadata)
|
||||
}
|
||||
else if(options.indexOf(worksheetUrl) !== -1) {
|
||||
cb(sampleGDocsSpreadsheetData)
|
||||
}
|
||||
});
|
||||
|
||||
dataset.fetch().then(function() {
|
||||
var docList = dataset.records;
|
||||
deepEqual(['column-2', 'column-1'], _.pluck(dataset.fields.toJSON(), 'id'));
|
||||
equal(3, docList.length);
|
||||
equal("A", docList.models[0].get('column-1'));
|
||||
equal('javascript-test :: Sheet1', dataset.get('title'));
|
||||
});
|
||||
$.getJSON.restore();
|
||||
});
|
||||
|
||||
test("GDocs Backend.getUrl", function() {
|
||||
var key = 'Abc_dajkdkjdafkj';
|
||||
var gid = 0;
|
||||
var worksheet = 1;
|
||||
var url = 'https://docs.google.com/spreadsheet/ccc?key=' + key + '#gid=' + gid
|
||||
var out = recline.Backend.GDocs.getGDocsAPIUrls(url);
|
||||
var exp1 = 'https://spreadsheets.google.com/feeds/list/' + key + '/' + worksheet + '/public/values?alt=json'
|
||||
var exp2 = 'https://spreadsheets.google.com/feeds/worksheets/' + key + '/public/basic?alt=json'
|
||||
equal(exp1, out.worksheet);
|
||||
equal(exp2, out.spreadsheet);
|
||||
|
||||
var url = 'https://docs.google.com/spreadsheet/ccc?key=' + key;
|
||||
var out = recline.Backend.GDocs.getGDocsAPIUrls(url);
|
||||
equal(out.worksheet, exp1);
|
||||
});
|
||||
|
||||
})(this.jQuery);
|
||||
|
||||
@ -100,18 +100,19 @@ test('filters', function () {
|
||||
});
|
||||
|
||||
query = new recline.Model.Query();
|
||||
query.addFilter({type: 'range', field: 'date', start: '2011-01-01', stop: '2011-05-01'});
|
||||
query.addFilter({type: 'range', field: 'date', from: '2011-01-01', to: '2011-05-01'});
|
||||
data.query(query.toJSON()).then(function(out) {
|
||||
equal(out.total, 3);
|
||||
deepEqual(_.pluck(out.hits, 'date'), ['2011-01-01','2011-02-03','2011-04-05']);
|
||||
});
|
||||
|
||||
query = new recline.Model.Query();
|
||||
query.addFilter({type: 'range', field: 'z', start: '0', stop: '10'});
|
||||
query.addFilter({type: 'range', field: 'z', from: '0', to: '10'});
|
||||
data.query(query.toJSON()).then(function(out) {
|
||||
equal(out.total, 3);
|
||||
deepEqual(_.pluck(out.hits, 'z'), [3,6,9]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -119,35 +120,37 @@ test('filters with nulls', function () {
|
||||
var data = _wrapData();
|
||||
|
||||
query = new recline.Model.Query();
|
||||
query.addFilter({type: 'range', field: 'z', start: '', stop: null});
|
||||
query.addFilter({type: 'range', field: 'z', from: '', to: null});
|
||||
data.query(query.toJSON()).then(function(out) {
|
||||
equal(out.total, 6);
|
||||
});
|
||||
|
||||
query = new recline.Model.Query();
|
||||
query.addFilter({type: 'range', field: 'x', start: '', stop: '3'});
|
||||
query.addFilter({type: 'range', field: 'x', from: '', to: '3'});
|
||||
data.query(query.toJSON()).then(function(out) {
|
||||
equal(out.total, 3);
|
||||
});
|
||||
|
||||
query = new recline.Model.Query();
|
||||
query.addFilter({type: 'range', field: 'x', start: '3', stop: ''});
|
||||
query.addFilter({type: 'range', field: 'x', from: '3', to: ''});
|
||||
data.query(query.toJSON()).then(function(out) {
|
||||
equal(out.total, 4);
|
||||
});
|
||||
|
||||
data.records[5].country = '';
|
||||
|
||||
query = new recline.Model.Query();
|
||||
query.addFilter({type: 'range', field: 'country', start: '', stop: 'Z'});
|
||||
query.addFilter({type: 'range', field: 'country', from: '', to: 'Z'});
|
||||
data.query(query.toJSON()).then(function(out) {
|
||||
equal(out.total, 5);
|
||||
});
|
||||
|
||||
query = new recline.Model.Query();
|
||||
query.addFilter({type: 'range', field: 'x', start: '', stop: ''});
|
||||
query.addFilter({type: 'range', field: 'x', from: '', to: ''});
|
||||
data.query(query.toJSON()).then(function(out) {
|
||||
equal(out.total, 6);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('facet', function () {
|
||||
@ -305,14 +308,14 @@ test('filters', function () {
|
||||
});
|
||||
|
||||
dataset = makeBackendDataset();
|
||||
dataset.queryState.addFilter({type: 'range', field: 'date', start: '2011-01-01', stop: '2011-05-01'});
|
||||
dataset.queryState.addFilter({type: 'range', field: 'date', from: '2011-01-01', to: '2011-05-01'});
|
||||
dataset.query().then(function() {
|
||||
equal(dataset.records.length, 3);
|
||||
deepEqual(dataset.records.pluck('date'), ['2011-01-01','2011-02-03','2011-04-05']);
|
||||
});
|
||||
|
||||
dataset = makeBackendDataset();
|
||||
dataset.queryState.addFilter({type: 'range', field: 'z', start: '0', stop: '10'});
|
||||
dataset.queryState.addFilter({type: 'range', field: 'z', from: '0', to: '10'});
|
||||
dataset.query().then(function() {
|
||||
equal(dataset.records.length, 3);
|
||||
deepEqual(dataset.records.pluck('z'), [3,6,9]);
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
<link rel="stylesheet" href="../css/flot.css" type="text/css" media="screen" />
|
||||
|
||||
<script type="text/javascript" src="../vendor/jquery/1.7.1/jquery.js"></script>
|
||||
<script type="text/javascript" src="../vendor/underscore/1.4.2/underscore.js"></script>
|
||||
<script type="text/javascript" src="../vendor/backbone/0.9.2/backbone.js"></script>
|
||||
<script type="text/javascript" src="../vendor/underscore/1.4.4/underscore.js"></script>
|
||||
<script type="text/javascript" src="../vendor/backbone/1.0.0/backbone.js"></script>
|
||||
<script type="text/javascript" src="../vendor/jquery-ui-1.8.14.custom.min.js"></script>
|
||||
<script type="text/javascript" src="../vendor/jquery.flot/0.7/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="../vendor/jquery.mustache.js"></script>
|
||||
@ -18,7 +18,8 @@
|
||||
<script type="text/javascript" src="../vendor/leaflet/0.3.1/leaflet.js"></script>
|
||||
|
||||
<script type="text/javascript" src="qunit/qunit.js"></script>
|
||||
<script src="sinon/1.1.1/sinon.js"></script>
|
||||
<script type="text/javascript" src="qunit/qunit-assert-html.js"></script>
|
||||
<script src="sinon/1.7.1/sinon.js"></script>
|
||||
<script src="sinon-qunit/1.0.0/sinon-qunit.js"></script>
|
||||
|
||||
<!-- Link to the built version of recline -->
|
||||
|
||||
@ -4,28 +4,36 @@
|
||||
<head>
|
||||
<title>Qunit Tests</title>
|
||||
<link rel="stylesheet" href="qunit/qunit.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="../vendor/timeline/20120520/css/timeline.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="../vendor/timeline/css/timeline.css" type="text/css" media="screen" />
|
||||
<link rel="stylesheet" href="../css/timeline.css" type="text/css" media="screen" />
|
||||
<style type="text/css">.recline-timeline { height: 400px; }</style>
|
||||
<link rel="stylesheet" href="../css/flot.css">
|
||||
<link rel="stylesheet" href="../vendor/leaflet/0.4.4/leaflet.css">
|
||||
<link rel="stylesheet" href="../vendor/leaflet.markercluster/MarkerCluster.css">
|
||||
<link rel="stylesheet" href="../vendor/leaflet.markercluster/MarkerCluster.Default.css">
|
||||
<link rel="stylesheet" href="../css/map.css">
|
||||
|
||||
<script type="text/javascript" src="../vendor/jquery/1.7.1/jquery.js"></script>
|
||||
<script type="text/javascript" src="../vendor/underscore/1.4.2/underscore.js"></script>
|
||||
<script type="text/javascript" src="../vendor/backbone/0.9.2/backbone.js"></script>
|
||||
<script type="text/javascript" src="../vendor/moment/1.6.2/moment.js"></script>
|
||||
<script type="text/javascript" src="../vendor/underscore/1.4.4/underscore.js"></script>
|
||||
<script type="text/javascript" src="../vendor/backbone/1.0.0/backbone.js"></script>
|
||||
<script type="text/javascript" src="../vendor/moment/2.0.0/moment.js"></script>
|
||||
<script type="text/javascript" src="../vendor/mustache/0.5.0-dev/mustache.js"></script>
|
||||
<script type="text/javascript" src="../vendor/bootstrap/2.0.2/bootstrap.js"></script>
|
||||
<script type="text/javascript" src="../vendor/flot/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="../vendor/flot/jquery.flot.time.js"></script>
|
||||
<script type="text/javascript" src="../vendor/leaflet/0.4.4/leaflet-src.js"></script>
|
||||
<script type="text/javascript" src="../vendor/leaflet.markercluster/leaflet.markercluster.js"></script>
|
||||
<script type="text/javascript" src="../vendor/slickgrid/2.0.1/jquery-ui-1.8.16.custom.min.js"></script>
|
||||
<script type="text/javascript" src="../vendor/slickgrid/2.0.1/jquery.event.drag-2.0.min.js"></script>
|
||||
<script type="text/javascript" src="../vendor/slickgrid/2.0.1/slick.grid.min.js"></script>
|
||||
<script type="text/javascript" src="../vendor/timeline/20120520/js/timeline.js"></script>
|
||||
<script type="text/javascript" src="../vendor/timeline/js/timeline.js"></script>
|
||||
<!--[if lte IE 7]>
|
||||
<script language="javascript" type="text/javascript" src="../vendor/json/json2.js"></script>
|
||||
<![endif]-->
|
||||
|
||||
<script type="text/javascript" src="qunit/qunit.js"></script>
|
||||
<script src="sinon/1.1.1/sinon.js"></script>
|
||||
<script type="text/javascript" src="qunit/qunit-assert-html.js"></script>
|
||||
<script src="sinon/1.7.1/sinon.js"></script>
|
||||
<script src="sinon-qunit/1.0.0/sinon-qunit.js"></script>
|
||||
|
||||
<script type="text/javascript" src="base.js"></script>
|
||||
@ -34,15 +42,11 @@
|
||||
<script type="text/javascript" src="../src/model.js"></script>
|
||||
<script type="text/javascript" src="../src/backend.memory.js"></script>
|
||||
<script type="text/javascript" src="../src/backend.dataproxy.js"></script>
|
||||
<script type="text/javascript" src="../src/backend.gdocs.js"></script>
|
||||
<script type="text/javascript" src="../src/backend.elasticsearch.js"></script>
|
||||
<script type="text/javascript" src="../src/backend.csv.js"></script>
|
||||
|
||||
<script type="text/javascript" src="model.test.js"></script>
|
||||
<script type="text/javascript" src="backend.memory.test.js"></script>
|
||||
<script type="text/javascript" src="backend.dataproxy.test.js"></script>
|
||||
<script type="text/javascript" src="backend.gdocs.test.js"></script>
|
||||
<script type="text/javascript" src="backend.elasticsearch.test.js"></script>
|
||||
<script type="text/javascript" src="backend.csv.test.js"></script>
|
||||
|
||||
<!-- views and view tests -->
|
||||
|
||||
@ -177,6 +177,26 @@ test('Dataset getFieldsSummary', function () {
|
||||
});
|
||||
});
|
||||
|
||||
test('fetch without and with explicit fields', function () {
|
||||
var dataset = new recline.Model.Dataset({
|
||||
backend: 'csv',
|
||||
data: 'A,B\n1,2\n3,4'
|
||||
});
|
||||
dataset.fetch();
|
||||
equal(dataset.fields.at(0).id, 'A');
|
||||
equal(dataset.fields.at(0).get('type'), 'string');
|
||||
|
||||
var dataset = new recline.Model.Dataset({
|
||||
fields: [{id: 'X', type: 'number'}, {id: 'Y'}],
|
||||
backend: 'csv',
|
||||
data: 'A,B\n1,2\n3,4'
|
||||
});
|
||||
dataset.fetch();
|
||||
equal(dataset.fields.at(0).id, 'X');
|
||||
equal(dataset.fields.at(0).get('type'), 'number');
|
||||
equal(dataset.records.at(0).get('X'), 1);
|
||||
});
|
||||
|
||||
test('_normalizeRecordsAndFields', function () {
|
||||
var data = [
|
||||
// fields but no records
|
||||
@ -279,7 +299,7 @@ test('_normalizeRecordsAndFields', function () {
|
||||
fields: [{id: 'col1'}, {id: 'col2'}],
|
||||
records: [
|
||||
{col1: 1, col2: 2},
|
||||
{col1: 3, col2: 4},
|
||||
{col1: 3, col2: 4}
|
||||
]
|
||||
},
|
||||
exp: {
|
||||
@ -327,6 +347,30 @@ test('Query', function () {
|
||||
deepEqual({terms: {field: 'xyz'}}, query.get('facets')['xyz']);
|
||||
});
|
||||
|
||||
test('Query.addFacet', function () {
|
||||
var query = new recline.Model.Query();
|
||||
query.addFacet('xyz', 25);
|
||||
deepEqual({terms: {field: 'xyz', "size": 25}}, query.get('facets')['xyz']);
|
||||
});
|
||||
|
||||
test('Query.removeFacet', function () {
|
||||
var query = new recline.Model.Query();
|
||||
query.addFacet('xyz');
|
||||
deepEqual({terms: {field: 'xyz'}}, query.get('facets')['xyz']);
|
||||
query.removeFacet('xyz');
|
||||
equal(undefined, query.get('facets')['xyz']);
|
||||
});
|
||||
|
||||
test('Query.clearFacets', function () {
|
||||
var query = new recline.Model.Query();
|
||||
query.addFacet('abc');
|
||||
query.addFacet('xyz');
|
||||
deepEqual({terms: {field: 'xyz'}}, query.get('facets')['xyz']);
|
||||
deepEqual({terms: {field: 'abc'}}, query.get('facets')['abc']);
|
||||
query.clearFacets();
|
||||
deepEqual({}, query.get('facets'));
|
||||
});
|
||||
|
||||
test('Query.addFilter', function () {
|
||||
var query = new recline.Model.Query();
|
||||
query.addFilter({type: 'term', field: 'xyz'});
|
||||
@ -354,4 +398,56 @@ test('Query.addFilter', function () {
|
||||
deepEqual(exp, query.get('filters')[2]);
|
||||
});
|
||||
|
||||
test('Query.replaceFilter', function () {
|
||||
var query = new recline.Model.Query();
|
||||
query.addFilter({type: 'term', field: 'xyz', term: 'one'});
|
||||
var exp = {
|
||||
field: 'xyz',
|
||||
type: 'term',
|
||||
term: 'one'
|
||||
};
|
||||
deepEqual(query.get('filters')[0], exp);
|
||||
|
||||
query.replaceFilter({type: 'term', field: 'xyz', term: 'two'});
|
||||
exp = {
|
||||
field: 'xyz',
|
||||
type: 'term',
|
||||
term: 'two'
|
||||
};
|
||||
deepEqual(query.get('filters')[0], exp);
|
||||
|
||||
});
|
||||
|
||||
test('Query.replaceFilter first filter', function () {
|
||||
// replaceFilter changes filter order
|
||||
var query = new recline.Model.Query();
|
||||
query.addFilter({type: 'term', field: 'abc', term: 'one'});
|
||||
query.addFilter({type: 'term', field: 'xyz', term: 'two'});
|
||||
var exp0 = {
|
||||
field: 'abc',
|
||||
type: 'term',
|
||||
term: 'one'
|
||||
};
|
||||
deepEqual(query.get('filters')[0], exp0);
|
||||
var exp1 = {
|
||||
field: 'xyz',
|
||||
type: 'term',
|
||||
term: 'two'
|
||||
};
|
||||
deepEqual(query.get('filters')[1], exp1);
|
||||
|
||||
var numFilters = query.get('filters').length;
|
||||
query.replaceFilter({type: 'term', field: 'abc', term: 'three'});
|
||||
equal(query.get('filters').length, numFilters);
|
||||
exp0 = {
|
||||
field: 'abc',
|
||||
type: 'term',
|
||||
term: 'three'
|
||||
};
|
||||
// deletes original filter and adds replacement to end
|
||||
deepEqual(query.get('filters')[1], exp0);
|
||||
deepEqual(query.get('filters')[0], exp1);
|
||||
|
||||
});
|
||||
|
||||
})(this.jQuery);
|
||||
|
||||
377
test/qunit/qunit-assert-html.js
Normal file
377
test/qunit/qunit-assert-html.js
Normal file
@ -0,0 +1,377 @@
|
||||
/*global QUnit:false */
|
||||
(function( QUnit, window, undefined ) {
|
||||
"use strict";
|
||||
|
||||
var trim = function( s ) {
|
||||
if ( !s ) {
|
||||
return "";
|
||||
}
|
||||
return typeof s.trim === "function" ? s.trim() : s.replace( /^\s+|\s+$/g, "" );
|
||||
};
|
||||
|
||||
var normalizeWhitespace = function( s ) {
|
||||
if ( !s ) {
|
||||
return "";
|
||||
}
|
||||
return trim( s.replace( /\s+/g, " " ) );
|
||||
};
|
||||
|
||||
var dedupeFlatDict = function( dictToDedupe, parentDict ) {
|
||||
var key, val;
|
||||
if ( parentDict ) {
|
||||
for ( key in dictToDedupe ) {
|
||||
val = dictToDedupe[key];
|
||||
if ( val && ( val === parentDict[key] ) ) {
|
||||
delete dictToDedupe[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return dictToDedupe;
|
||||
};
|
||||
|
||||
var objectKeys = Object.keys || (function() {
|
||||
var hasOwn = function( obj, propName ) {
|
||||
return Object.prototype.hasOwnProperty.call( obj, propName );
|
||||
};
|
||||
return function( obj ) {
|
||||
var keys = [],
|
||||
key;
|
||||
for ( key in obj ) {
|
||||
if ( hasOwn( obj, key ) ) {
|
||||
keys.push( key );
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Calculate based on `currentStyle`/`getComputedStyle` styles instead
|
||||
*/
|
||||
var getElementStyles = (function() {
|
||||
|
||||
// Memoized
|
||||
var camelCase = (function() {
|
||||
var camelCaseFn = (function() {
|
||||
// Matches dashed string for camelizing
|
||||
var rmsPrefix = /^-ms-/,
|
||||
msPrefixFix = "ms-",
|
||||
rdashAlpha = /-([\da-z])/gi,
|
||||
camelCaseReplacerFn = function( all, letter ) {
|
||||
return ( letter + "" ).toUpperCase();
|
||||
};
|
||||
|
||||
return function( s ) {
|
||||
return s.replace(rmsPrefix, msPrefixFix).replace(rdashAlpha, camelCaseReplacerFn);
|
||||
};
|
||||
})();
|
||||
|
||||
var camelCaseMemoizer = {};
|
||||
|
||||
return function( s ) {
|
||||
var temp = camelCaseMemoizer[s];
|
||||
if ( temp ) {
|
||||
return temp;
|
||||
}
|
||||
|
||||
temp = camelCaseFn( s );
|
||||
camelCaseMemoizer[s] = temp;
|
||||
return temp;
|
||||
};
|
||||
})();
|
||||
|
||||
var styleKeySortingFn = function( a, b ) {
|
||||
return camelCase( a ) < camelCase( b );
|
||||
};
|
||||
|
||||
return function( elem ) {
|
||||
var styleCount, i, key,
|
||||
styles = {},
|
||||
styleKeys = [],
|
||||
style = elem.ownerDocument.defaultView ?
|
||||
elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
|
||||
elem.currentStyle;
|
||||
|
||||
// `getComputedStyle`
|
||||
if ( style && style.length && style[0] && style[style[0]] ) {
|
||||
styleCount = style.length;
|
||||
while ( styleCount-- ) {
|
||||
styleKeys.push( style[styleCount] );
|
||||
}
|
||||
styleKeys.sort( styleKeySortingFn );
|
||||
|
||||
for ( i = 0, styleCount = styleKeys.length ; i < styleCount ; i++ ) {
|
||||
key = styleKeys[i];
|
||||
if ( key !== "cssText" && typeof style[key] === "string" && style[key] ) {
|
||||
styles[camelCase( key )] = style[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
// `currentStyle` support: IE < 9.0, Opera < 10.6
|
||||
else {
|
||||
for ( key in style ) {
|
||||
styleKeys.push( key );
|
||||
}
|
||||
styleKeys.sort();
|
||||
|
||||
for ( i = 0, styleCount = styleKeys.length ; i < styleCount ; i++ ) {
|
||||
key = styleKeys[i];
|
||||
if ( key !== "cssText" && typeof style[key] === "string" && style[key] ) {
|
||||
styles[key] = style[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return styles;
|
||||
|
||||
};
|
||||
})();
|
||||
|
||||
var serializeElementNode = function( elementNode, rootNodeStyles ) {
|
||||
var subNodes, i, len, styles, attrName,
|
||||
serializedNode = {
|
||||
NodeType: elementNode.nodeType,
|
||||
NodeName: elementNode.nodeName.toLowerCase(),
|
||||
Attributes: {},
|
||||
ChildNodes: []
|
||||
};
|
||||
|
||||
subNodes = elementNode.attributes;
|
||||
for ( i = 0, len = subNodes.length ; i < len ; i++ ) {
|
||||
attrName = subNodes[i].name.toLowerCase();
|
||||
if ( attrName === "class" ) {
|
||||
serializedNode.Attributes[attrName] = normalizeWhitespace( subNodes[i].value );
|
||||
}
|
||||
else if ( attrName !== "style" ) {
|
||||
serializedNode.Attributes[attrName] = subNodes[i].value;
|
||||
}
|
||||
// Ignore the "style" attribute completely
|
||||
}
|
||||
|
||||
// Only add the style attribute if there is 1+ pertinent rules
|
||||
styles = dedupeFlatDict( getElementStyles( elementNode ), rootNodeStyles );
|
||||
if ( styles && objectKeys( styles ).length ) {
|
||||
serializedNode.Attributes["style"] = styles;
|
||||
}
|
||||
|
||||
subNodes = elementNode.childNodes;
|
||||
for ( i = 0, len = subNodes.length; i < len; i++ ) {
|
||||
serializedNode.ChildNodes.push( serializeNode( subNodes[i], rootNodeStyles ) );
|
||||
}
|
||||
|
||||
return serializedNode;
|
||||
};
|
||||
|
||||
var serializeNode = function( node, rootNodeStyles ) {
|
||||
var serializedNode;
|
||||
|
||||
switch (node.nodeType) {
|
||||
case 1: // Node.ELEMENT_NODE
|
||||
serializedNode = serializeElementNode( node, rootNodeStyles );
|
||||
break;
|
||||
case 3: // Node.TEXT_NODE
|
||||
serializedNode = {
|
||||
NodeType: node.nodeType,
|
||||
NodeName: node.nodeName.toLowerCase(),
|
||||
NodeValue: node.nodeValue
|
||||
};
|
||||
break;
|
||||
case 4: // Node.CDATA_SECTION_NODE
|
||||
case 7: // Node.PROCESSING_INSTRUCTION_NODE
|
||||
case 8: // Node.COMMENT_NODE
|
||||
serializedNode = {
|
||||
NodeType: node.nodeType,
|
||||
NodeName: node.nodeName.toLowerCase(),
|
||||
NodeValue: trim( node.nodeValue )
|
||||
};
|
||||
break;
|
||||
case 5: // Node.ENTITY_REFERENCE_NODE
|
||||
case 6: // Node.ENTITY_NODE
|
||||
case 9: // Node.DOCUMENT_NODE
|
||||
case 10: // Node.DOCUMENT_TYPE_NODE
|
||||
case 11: // Node.DOCUMENT_FRAGMENT_NODE
|
||||
case 12: // Node.NOTATION_NODE
|
||||
serializedNode = {
|
||||
NodeType: node.nodeType,
|
||||
NodeName: node.nodeName
|
||||
};
|
||||
break;
|
||||
case 2: // Node.ATTRIBUTE_NODE
|
||||
throw new Error( "`node.nodeType` was `Node.ATTRIBUTE_NODE` (2), which is not supported by this method" );
|
||||
default:
|
||||
throw new Error( "`node.nodeType` was not recognized: " + node.nodeType );
|
||||
}
|
||||
|
||||
return serializedNode;
|
||||
};
|
||||
|
||||
var serializeHtml = function( html ) {
|
||||
var scratch = getCleanSlate(),
|
||||
rootNode = scratch.container(),
|
||||
rootNodeStyles = getElementStyles( rootNode ),
|
||||
serializedHtml = [],
|
||||
kids, i, len;
|
||||
rootNode.innerHTML = trim( html );
|
||||
|
||||
kids = rootNode.childNodes;
|
||||
for ( i = 0, len = kids.length; i < len; i++ ) {
|
||||
serializedHtml.push( serializeNode( kids[i], rootNodeStyles ) );
|
||||
}
|
||||
|
||||
scratch.reset();
|
||||
|
||||
return serializedHtml;
|
||||
};
|
||||
|
||||
var getCleanSlate = (function() {
|
||||
var containerElId = "qunit-html-addon-container",
|
||||
iframeReady = false,
|
||||
iframeLoaded = function() {
|
||||
iframeReady = true;
|
||||
},
|
||||
iframeReadied = function() {
|
||||
if (iframe.readyState === "complete" || iframe.readyState === 4) {
|
||||
iframeReady = true;
|
||||
}
|
||||
},
|
||||
iframeApi,
|
||||
iframe,
|
||||
iframeWin,
|
||||
iframeDoc;
|
||||
|
||||
if ( !iframeApi ) {
|
||||
|
||||
QUnit.begin(function() {
|
||||
// Initialize the background iframe!
|
||||
if ( !iframe || !iframeWin || !iframeDoc ) {
|
||||
iframe = window.document.createElement( "iframe" );
|
||||
QUnit.addEvent( iframe, "load", iframeLoaded );
|
||||
QUnit.addEvent( iframe, "readystatechange", iframeReadied );
|
||||
iframe.style.position = "absolute";
|
||||
iframe.style.top = iframe.style.left = "-1000px";
|
||||
iframe.height = iframe.width = 0;
|
||||
|
||||
// `getComputedStyle` behaves inconsistently cross-browser when not attached to a live DOM
|
||||
window.document.body.appendChild( iframe );
|
||||
|
||||
iframeWin = iframe.contentWindow ||
|
||||
iframe.window ||
|
||||
iframe.contentDocument && iframe.contentDocument.defaultView ||
|
||||
iframe.document && ( iframe.document.defaultView || iframe.document.window ) ||
|
||||
window.frames[( iframe.name || iframe.id )];
|
||||
|
||||
iframeDoc = iframeWin && iframeWin.document ||
|
||||
iframe.contentDocument ||
|
||||
iframe.document;
|
||||
|
||||
var iframeContents = [
|
||||
"<!DOCTYPE html>",
|
||||
"<html>",
|
||||
"<head>",
|
||||
" <title>QUnit HTML addon iframe</title>",
|
||||
"</head>",
|
||||
"<body>",
|
||||
" <div id=\"" + containerElId + "\"></div>",
|
||||
" <script type=\"text/javascript\">",
|
||||
" window.isReady = true;",
|
||||
" </script>",
|
||||
"</body>",
|
||||
"</html>"
|
||||
].join( "\n" );
|
||||
|
||||
iframeDoc.open();
|
||||
iframeDoc.write( iframeContents );
|
||||
iframeDoc.close();
|
||||
|
||||
// Is ready?
|
||||
iframeReady = iframeReady || iframeWin.isReady;
|
||||
}
|
||||
});
|
||||
|
||||
QUnit.done(function() {
|
||||
if ( iframe && iframe.ownerDocument ) {
|
||||
iframe.parentNode.removeChild( iframe );
|
||||
}
|
||||
iframe = iframeWin = iframeDoc = null;
|
||||
iframeReady = false;
|
||||
});
|
||||
|
||||
var waitForIframeReady = function( maxTimeout ) {
|
||||
if ( !iframeReady ) {
|
||||
if ( !maxTimeout ) {
|
||||
maxTimeout = 2000; // 2 seconds MAX
|
||||
}
|
||||
var startTime = new Date();
|
||||
while ( !iframeReady && ( ( new Date() - startTime ) < maxTimeout ) ) {
|
||||
iframeReady = iframeReady || iframeWin.isReady;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
iframeApi = {
|
||||
container: function() {
|
||||
waitForIframeReady();
|
||||
if ( iframeReady && iframeDoc ) {
|
||||
return iframeDoc.getElementById( containerElId );
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
reset: function() {
|
||||
var containerEl = iframeApi.container();
|
||||
if ( containerEl ) {
|
||||
containerEl.innerHTML = "";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Actual function signature for `getCleanState`
|
||||
return function() { return iframeApi; };
|
||||
})();
|
||||
|
||||
QUnit.extend( QUnit.assert, {
|
||||
|
||||
/**
|
||||
* Compare two snippets of HTML for equality after normalization.
|
||||
*
|
||||
* @example assert.htmlEqual("<B>Hello, QUnit!</B> ", "<b>Hello, QUnit!</b>", "HTML should be equal");
|
||||
* @param {String} actual The actual HTML before normalization.
|
||||
* @param {String} expected The excepted HTML before normalization.
|
||||
* @param {String} [message] Optional message to display in the results.
|
||||
*/
|
||||
htmlEqual: function( actual, expected, message ) {
|
||||
if ( !message ) {
|
||||
message = "HTML should be equal";
|
||||
}
|
||||
|
||||
this.deepEqual( serializeHtml( actual ), serializeHtml( expected ), message );
|
||||
},
|
||||
|
||||
/**
|
||||
* Compare two snippets of HTML for inequality after normalization.
|
||||
*
|
||||
* @example assert.notHtmlEqual("<b>Hello, <i>QUnit!</i></b>", "<b>Hello, QUnit!</b>", "HTML should not be equal");
|
||||
* @param {String} actual The actual HTML before normalization.
|
||||
* @param {String} expected The excepted HTML before normalization.
|
||||
* @param {String} [message] Optional message to display in the results.
|
||||
*/
|
||||
notHtmlEqual: function( actual, expected, message ) {
|
||||
if ( !message ) {
|
||||
message = "HTML should not be equal";
|
||||
}
|
||||
|
||||
this.notDeepEqual( serializeHtml( actual ), serializeHtml( expected ), message );
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Normalize and serialize an HTML snippet. Primarily only exposed for unit testing purposes.
|
||||
*
|
||||
* @example assert._serializeHtml('<b style="color:red;">Test</b>');
|
||||
* @param {String} html The HTML snippet to normalize and serialize.
|
||||
* @returns {Object[]} The normalized and serialized form of the HTML snippet.
|
||||
*/
|
||||
_serializeHtml: serializeHtml
|
||||
|
||||
});
|
||||
})( QUnit, this );
|
||||
@ -1,11 +1,11 @@
|
||||
/**
|
||||
* QUnit v1.6.0 - A JavaScript Unit Testing Framework
|
||||
* QUnit v1.11.0 - A JavaScript Unit Testing Framework
|
||||
*
|
||||
* http://docs.jquery.com/QUnit
|
||||
* http://qunitjs.com
|
||||
*
|
||||
* Copyright (c) 2012 John Resig, Jörn Zaefferer
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* or GPL (GPL-LICENSE.txt) licenses.
|
||||
* Copyright 2012 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
@ -38,10 +38,10 @@
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
|
||||
border-radius: 15px 15px 0 0;
|
||||
-moz-border-radius: 15px 15px 0 0;
|
||||
-webkit-border-top-right-radius: 15px;
|
||||
-webkit-border-top-left-radius: 15px;
|
||||
border-radius: 5px 5px 0 0;
|
||||
-moz-border-radius: 5px 5px 0 0;
|
||||
-webkit-border-top-right-radius: 5px;
|
||||
-webkit-border-top-left-radius: 5px;
|
||||
}
|
||||
|
||||
#qunit-header a {
|
||||
@ -54,9 +54,9 @@
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#qunit-header label {
|
||||
#qunit-testrunner-toolbar label {
|
||||
display: inline-block;
|
||||
padding-left: 0.5em;
|
||||
padding: 0 .5em 0 .1em;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
@ -67,6 +67,7 @@
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
color: #5E740B;
|
||||
background-color: #eee;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
@ -76,6 +77,9 @@
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-container {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/** Tests: Pass/Fail */
|
||||
|
||||
@ -107,19 +111,24 @@
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#qunit-tests ol {
|
||||
#qunit-tests li .runtime {
|
||||
float: right;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.qunit-assert-list {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
background-color: #fff;
|
||||
|
||||
border-radius: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
-webkit-border-radius: 15px;
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
}
|
||||
|
||||
box-shadow: inset 0px 2px 13px #999;
|
||||
-moz-box-shadow: inset 0px 2px 13px #999;
|
||||
-webkit-box-shadow: inset 0px 2px 13px #999;
|
||||
.qunit-collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests table {
|
||||
@ -162,8 +171,7 @@
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
margin: 0.5em;
|
||||
padding: 0.4em 0.5em 0.4em 0.5em;
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
@ -172,9 +180,9 @@
|
||||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #5E740B;
|
||||
color: #3c510c;
|
||||
background-color: #fff;
|
||||
border-left: 26px solid #C6E746;
|
||||
border-left: 10px solid #C6E746;
|
||||
}
|
||||
|
||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
@ -190,15 +198,15 @@
|
||||
#qunit-tests li li.fail {
|
||||
color: #710909;
|
||||
background-color: #fff;
|
||||
border-left: 26px solid #EE5757;
|
||||
border-left: 10px solid #EE5757;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#qunit-tests > li:last-child {
|
||||
border-radius: 0 0 15px 15px;
|
||||
-moz-border-radius: 0 0 15px 15px;
|
||||
-webkit-border-bottom-right-radius: 15px;
|
||||
-webkit-border-bottom-left-radius: 15px;
|
||||
border-radius: 0 0 5px 5px;
|
||||
-moz-border-radius: 0 0 5px 5px;
|
||||
-webkit-border-bottom-right-radius: 5px;
|
||||
-webkit-border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||
|
||||
1007
test/qunit/qunit.js
1007
test/qunit/qunit.js
File diff suppressed because it is too large
Load Diff
139
test/qunit/runner.js
Normal file
139
test/qunit/runner.js
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* QtWebKit-powered headless test runner using PhantomJS
|
||||
*
|
||||
* PhantomJS binaries: http://phantomjs.org/download.html
|
||||
* Requires PhantomJS 1.6+ (1.7+ recommended)
|
||||
*
|
||||
* Run with:
|
||||
* phantomjs runner.js [url-of-your-qunit-testsuite]
|
||||
*
|
||||
* e.g.
|
||||
* phantomjs runner.js http://localhost/qunit/test/index.html
|
||||
*/
|
||||
|
||||
/*global phantom:false, require:false, console:false, window:false, QUnit:false */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var url, page, timeout,
|
||||
args = require('system').args;
|
||||
|
||||
// arg[0]: scriptName, args[1...]: arguments
|
||||
if (args.length < 2 || args.length > 3) {
|
||||
console.error('Usage:\n phantomjs runner.js [url-of-your-qunit-testsuite] [timeout-in-seconds]');
|
||||
phantom.exit(1);
|
||||
}
|
||||
|
||||
url = args[1];
|
||||
page = require('webpage').create();
|
||||
if (args[2] !== undefined) {
|
||||
timeout = parseInt(args[2], 10);
|
||||
}
|
||||
|
||||
// Route `console.log()` calls from within the Page context to the main Phantom context (i.e. current `this`)
|
||||
page.onConsoleMessage = function(msg) {
|
||||
console.log(msg);
|
||||
};
|
||||
|
||||
page.onInitialized = function() {
|
||||
page.evaluate(addLogging);
|
||||
};
|
||||
|
||||
page.onCallback = function(message) {
|
||||
var result,
|
||||
failed;
|
||||
|
||||
if (message) {
|
||||
if (message.name === 'QUnit.done') {
|
||||
result = message.data;
|
||||
failed = !result || result.failed;
|
||||
|
||||
phantom.exit(failed ? 1 : 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
page.open(url, function(status) {
|
||||
if (status !== 'success') {
|
||||
console.error('Unable to access network: ' + status);
|
||||
phantom.exit(1);
|
||||
} else {
|
||||
// Cannot do this verification with the 'DOMContentLoaded' handler because it
|
||||
// will be too late to attach it if a page does not have any script tags.
|
||||
var qunitMissing = page.evaluate(function() { return (typeof QUnit === 'undefined' || !QUnit); });
|
||||
if (qunitMissing) {
|
||||
console.error('The `QUnit` object is not present on this page.');
|
||||
phantom.exit(1);
|
||||
}
|
||||
|
||||
// Set a timeout on the test running, otherwise tests with async problems will hang forever
|
||||
if (typeof timeout === 'number') {
|
||||
setTimeout(function() {
|
||||
console.error('The specified timeout of ' + timeout + ' seconds has expired. Aborting...');
|
||||
phantom.exit(1);
|
||||
}, timeout * 1000);
|
||||
}
|
||||
|
||||
// Do nothing... the callback mechanism will handle everything!
|
||||
}
|
||||
});
|
||||
|
||||
function addLogging() {
|
||||
window.document.addEventListener('DOMContentLoaded', function() {
|
||||
var currentTestAssertions = [];
|
||||
|
||||
QUnit.log(function(details) {
|
||||
var response;
|
||||
|
||||
// Ignore passing assertions
|
||||
if (details.result) {
|
||||
return;
|
||||
}
|
||||
|
||||
response = details.message || '';
|
||||
|
||||
if (typeof details.expected !== 'undefined') {
|
||||
if (response) {
|
||||
response += ', ';
|
||||
}
|
||||
|
||||
response += 'expected: ' + details.expected + ', but was: ' + details.actual;
|
||||
}
|
||||
|
||||
if (details.source) {
|
||||
response += "\n" + details.source;
|
||||
}
|
||||
|
||||
currentTestAssertions.push('Failed assertion: ' + response);
|
||||
});
|
||||
|
||||
QUnit.testDone(function(result) {
|
||||
var i,
|
||||
len,
|
||||
name = result.module + ': ' + result.name;
|
||||
|
||||
if (result.failed) {
|
||||
console.log('Test failed: ' + name);
|
||||
|
||||
for (i = 0, len = currentTestAssertions.length; i < len; i++) {
|
||||
console.log(' ' + currentTestAssertions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
currentTestAssertions.length = 0;
|
||||
});
|
||||
|
||||
QUnit.done(function(result) {
|
||||
console.log('Took ' + result.runtime + 'ms to run ' + result.total + ' tests. ' + result.passed + ' passed, ' + result.failed + ' failed.');
|
||||
|
||||
if (typeof window.callPhantom === 'function') {
|
||||
window.callPhantom({
|
||||
'name': 'QUnit.done',
|
||||
'data': result
|
||||
});
|
||||
}
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
})();
|
||||
File diff suppressed because it is too large
Load Diff
4299
test/sinon/1.7.1/sinon.js
Normal file
4299
test/sinon/1.7.1/sinon.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -29,8 +29,8 @@ test('initialize', function () {
|
||||
// check we have updated editor with state info
|
||||
equal(view.elSidebar.find('.editor-type select').val(), 'lines');
|
||||
equal(view.elSidebar.find('.editor-group select').val(), 'x');
|
||||
var out = _.map(view.elSidebar.find('.editor-series select'), function($el) {
|
||||
return $($el).val();
|
||||
var out = _.map(view.elSidebar.find('.editor-series select'), function(el) {
|
||||
return $(el).val();
|
||||
});
|
||||
deepEqual(out, ['y', 'z']);
|
||||
|
||||
@ -48,7 +48,9 @@ test('dates in graph view', function () {
|
||||
'series': ['y', 'z']
|
||||
}
|
||||
});
|
||||
view.render();
|
||||
$('.fixtures').append(view.el);
|
||||
view.redraw();
|
||||
|
||||
view.remove();
|
||||
});
|
||||
|
||||
@ -110,10 +110,14 @@ test('GeoJSON geom field', function () {
|
||||
test('_getGeometryFromRecord non-GeoJSON', function () {
|
||||
var test = [
|
||||
[{ lon: 47, lat: 53}, [47,53]],
|
||||
[{ lon: -47, lat: 53}, [-47,53]],
|
||||
["53.3,47.32", [47.32, 53.3]],
|
||||
["53.3, 47.32", [47.32, 53.3]],
|
||||
["(53.3,47.32)", [47.32, 53.3]],
|
||||
[[53.3,47.32], [53.3, 47.32]]
|
||||
[[53.3,47.32], [53.3, 47.32]],
|
||||
["53.3 N, 113.5 W", [-113.5, 53.3]],
|
||||
["53° 18' N, 113° 30' W", [-113.5, 53.3 ]],
|
||||
["22°45′90″S, 43°15′45″W", [-43.2625, -22.775]]
|
||||
];
|
||||
var view = new recline.View.Map({
|
||||
model: new recline.Model.Dataset({
|
||||
@ -130,7 +134,7 @@ test('_getGeometryFromRecord non-GeoJSON', function () {
|
||||
});
|
||||
});
|
||||
|
||||
test('many markers', function () {
|
||||
test('many markers and clustering', function () {
|
||||
var data = [];
|
||||
for (var i = 0; i<1000; i++) {
|
||||
data.push({ id: i, lon: 13+3*i, lat: 52+i/10});
|
||||
@ -150,7 +154,13 @@ test('many markers', function () {
|
||||
|
||||
dataset.query();
|
||||
|
||||
// this whole test looks a bit odd now
|
||||
// we used to turn on clustering automatically at a certain level but we do not any more
|
||||
equal(view.state.get('cluster'), false);
|
||||
|
||||
view.state.set({cluster: true});
|
||||
equal(view.state.get('cluster'), true);
|
||||
|
||||
view.remove();
|
||||
});
|
||||
|
||||
@ -162,13 +172,13 @@ test('Popup', function () {
|
||||
$('.fixtures').append(view.el);
|
||||
view.render();
|
||||
|
||||
var marker = view.el.find('.leaflet-marker-icon').first();
|
||||
var marker = view.$el.find('.leaflet-marker-icon').first();
|
||||
|
||||
assertPresent(marker);
|
||||
|
||||
_.values(view.features._layers)[0].fire('click');
|
||||
|
||||
var popup = view.el.find('.leaflet-popup-content');
|
||||
var popup = view.$el.find('.leaflet-popup-content');
|
||||
|
||||
assertPresent(popup);
|
||||
|
||||
@ -183,7 +193,7 @@ test('Popup', function () {
|
||||
view.remove();
|
||||
});
|
||||
|
||||
test('Popup - Custom', function () {
|
||||
test('Popup - Custom', function (assert) {
|
||||
var dataset = GeoJSONFixture.getDataset();
|
||||
var view = new recline.View.Map({
|
||||
model: dataset
|
||||
@ -195,14 +205,14 @@ test('Popup - Custom', function () {
|
||||
};
|
||||
view.render();
|
||||
|
||||
var marker = view.el.find('.leaflet-marker-icon').first();
|
||||
var marker = view.$el.find('.leaflet-marker-icon').first();
|
||||
_.values(view.features._layers)[0].fire('click');
|
||||
var popup = view.el.find('.leaflet-popup-content');
|
||||
var popup = view.$el.find('.leaflet-popup-content');
|
||||
|
||||
assertPresent(popup);
|
||||
|
||||
var text = popup.html();
|
||||
ok((text.indexOf('<h3>1</h3>y: 2') != -1))
|
||||
assert.htmlEqual(text, '<h3>1</h3>y: 2');
|
||||
|
||||
view.remove();
|
||||
});
|
||||
@ -213,7 +223,7 @@ test('geoJsonLayerOptions', function () {
|
||||
model: dataset
|
||||
});
|
||||
$('.fixtures').append(view.el);
|
||||
view.geoJsonLayerOptions.point
|
||||
view.geoJsonLayerOptions.point
|
||||
view.geoJsonLayerOptions.pointToLayer = function(feature, latlng) {
|
||||
var marker = new L.CircleMarker(latlng, { radius: 8 } );
|
||||
marker.bindPopup(feature.properties.popupContent);
|
||||
|
||||
@ -12,7 +12,7 @@ test('basic explorer functionality', function () {
|
||||
});
|
||||
var $explorer = $el.find('.recline-data-explorer');
|
||||
equal($explorer.length, 1);
|
||||
$el.remove();
|
||||
explorer.remove();
|
||||
});
|
||||
|
||||
test('get State', function () {
|
||||
@ -34,7 +34,7 @@ test('get State', function () {
|
||||
equal(state.get('backend'), 'memory');
|
||||
equal(state.get('dataset').url, 'xyz');
|
||||
ok(state.get('url') === url);
|
||||
$el.remove();
|
||||
explorer.remove();
|
||||
});
|
||||
|
||||
test('initialize state', function () {
|
||||
@ -60,16 +60,16 @@ test('initialize state', function () {
|
||||
ok(explorer.state.get('currentView'), 'graph');
|
||||
|
||||
// check the correct view is visible
|
||||
var css = explorer.el.find('.navigation a[data-view="graph"]').attr('class').split(' ');
|
||||
var css = explorer.$el.find('.navigation a[data-view="graph"]').attr('class').split(' ');
|
||||
ok(_.contains(css, 'active'), css);
|
||||
var css = explorer.el.find('.navigation a[data-view="grid"]').attr('class').split(' ');
|
||||
var css = explorer.$el.find('.navigation a[data-view="grid"]').attr('class').split(' ');
|
||||
ok(!(_.contains(css, 'active')), css);
|
||||
|
||||
// check pass through of view config
|
||||
deepEqual(explorer.state.get('view-grid')['hiddenFields'], ['x']);
|
||||
equal(explorer.state.get('view-map')['lonField'], 'lon1');
|
||||
|
||||
$el.remove();
|
||||
explorer.remove();
|
||||
});
|
||||
|
||||
test('restore (from serialized state)', function() {
|
||||
@ -83,6 +83,9 @@ test('restore (from serialized state)', function() {
|
||||
var out = explorerNew.state.toJSON();
|
||||
equal(out.backend, state.backend);
|
||||
|
||||
explorer.remove();
|
||||
explorerNew.remove();
|
||||
|
||||
var dataset = new recline.Model.Dataset({
|
||||
url: 'http://data.london.gov.uk/datafiles/transport/tfl_passengers.csv',
|
||||
format: 'csv',
|
||||
@ -95,6 +98,9 @@ test('restore (from serialized state)', function() {
|
||||
var explorerNew = recline.View.MultiView.restore(state);
|
||||
equal(explorerNew.model.get('backend'), 'dataproxy');
|
||||
equal(explorerNew.model.get('format'), 'csv');
|
||||
|
||||
explorer.remove();
|
||||
explorerNew.remove();
|
||||
});
|
||||
|
||||
})(this.jQuery);
|
||||
|
||||
@ -83,7 +83,7 @@ test('editable', function () {
|
||||
|
||||
$('.fixtures .test-datatable').append(view.el);
|
||||
view.render();
|
||||
view.grid.init();
|
||||
view.show();
|
||||
|
||||
var new_item = {lon: "foo", id: 1, z: 23, date: "12", y: 3, country: 'FR'};
|
||||
|
||||
@ -92,13 +92,15 @@ test('editable', function () {
|
||||
});
|
||||
|
||||
// Be sure a cell change triggers a change of the model
|
||||
e = new Slick.EventData();
|
||||
return view.grid.onCellChange.notify({
|
||||
row: 1,
|
||||
cell: 0,
|
||||
item: new_item,
|
||||
grid: view.grid
|
||||
}, e, view.grid);
|
||||
e = new Slick.EventData();
|
||||
view.grid.onCellChange.notify({
|
||||
row: 1,
|
||||
cell: 0,
|
||||
item: new_item,
|
||||
grid: view.grid
|
||||
}, e, view.grid);
|
||||
|
||||
view.remove();
|
||||
});
|
||||
|
||||
test('update', function() {
|
||||
@ -124,9 +126,11 @@ test('update', function() {
|
||||
// Change the model at row 1
|
||||
dataset.records.at(1).set('z', zbefore + 1);
|
||||
equal( zbefore + 1, view.grid.getData().getItem(1)['z']);
|
||||
|
||||
view.remove();
|
||||
});
|
||||
|
||||
test('renderers', function () {
|
||||
test('renderers', function (assert) {
|
||||
var dataset = Fixture.getDataset();
|
||||
|
||||
dataset.fields.get('country').renderer = function(val, field, doc){
|
||||
@ -148,7 +152,7 @@ test('renderers', function () {
|
||||
view.grid.init();
|
||||
|
||||
equal($(view.grid.getCellNode(0,view.grid.getColumnIndex('country'))).text(),'Country: DE');
|
||||
equal($(view.grid.getCellNode(0,view.grid.getColumnIndex('country'))).html(),'<a href="abc">Country: DE</a>');
|
||||
assert.htmlEqual($(view.grid.getCellNode(0,view.grid.getColumnIndex('country'))).html(),'<a href="abc">Country: DE</a>');
|
||||
equal($(view.grid.getCellNode(0,view.grid.getColumnIndex('computed'))).text(),'10');
|
||||
view.remove();
|
||||
});
|
||||
|
||||
@ -19,13 +19,13 @@ test('extract dates and timelineJSON', function () {
|
||||
'headline': '',
|
||||
'date': [
|
||||
{
|
||||
'startDate': new Date('2012-03-20'),
|
||||
'startDate': '2012,03,20',
|
||||
'endDate': null,
|
||||
'headline': '1',
|
||||
'text': '<div class="recline-record-summary"><div class="Date"><strong>Date</strong>: 2012-03-20</div><div class="title"><strong>title</strong>: 1</div></div>'
|
||||
},
|
||||
{
|
||||
'startDate': new Date('2012-03-25'),
|
||||
'startDate': '2012,03,25',
|
||||
'endDate': null,
|
||||
'headline': '2',
|
||||
'text': '<div class="recline-record-summary"><div class="Date"><strong>Date</strong>: 2012-03-25</div><div class="title"><strong>title</strong>: 2</div></div>'
|
||||
@ -37,17 +37,22 @@ test('extract dates and timelineJSON', function () {
|
||||
});
|
||||
|
||||
test('render etc', function () {
|
||||
var dataset = Fixture.getDataset();
|
||||
var dataset = new recline.Model.Dataset({
|
||||
records: [
|
||||
{'Date': '-10000', 'title': 'first'},
|
||||
{'Date': '2012-03-20', 'title': 'second'},
|
||||
{'Date': '2012-03-25', 'title': 'third'}
|
||||
]
|
||||
});
|
||||
var view = new recline.View.Timeline({
|
||||
model: dataset
|
||||
});
|
||||
view.render();
|
||||
$('.fixtures').append(view.el);
|
||||
view._initTimeline();
|
||||
assertPresent('.vmm-timeline', view.el);
|
||||
view.render();
|
||||
assertPresent('.vco-timeline', view.el);
|
||||
assertPresent('.timenav', view.el);
|
||||
assertPresent('.timenav', view.el);
|
||||
equal(view.el.find('.marker.active h4').text(), '2011');
|
||||
equal(view.$el.find('.marker.active h3').text(), 'first');
|
||||
view.remove();
|
||||
});
|
||||
|
||||
@ -57,18 +62,22 @@ test('_parseDate', function () {
|
||||
model: dataset
|
||||
});
|
||||
var testData = [
|
||||
[ '1st August 1914', '1914-08-01T00:00:00.000Z' ],
|
||||
[ '1 August 1914', '1914-08-01T00:00:00.000Z' ],
|
||||
[ 'August 1st 1914', '1914-08-01T00:00:00.000Z' ],
|
||||
[ '1914-08-01', '1914-08-01T00:00:00.000Z' ],
|
||||
[ '1914-08-01T08:00', '1914-08-01T08:00:00.000Z' ],
|
||||
[ 'afdaf afdaf', null ],
|
||||
// [ '1st August 1914', '1914-08-01T00:00:00.000Z' ],
|
||||
// [ '1 August 1914', '1914-08-01T00:00:00.000Z' ],
|
||||
// [ 'August 1st 1914', '1914-08-01T00:00:00.000Z' ],
|
||||
[ '1914-08-01', '1914,08,01' ],
|
||||
[ '1914-08-01T08:00', '1914,08,01,08,00' ],
|
||||
[ '03-20-1914', '03/20/1914' ],
|
||||
[ '20/03/1914', '20/03/1914' ],
|
||||
[ '-10000', '-10000' ],
|
||||
[ null, null ]
|
||||
];
|
||||
_.each(testData, function(item) {
|
||||
var out = view._parseDate(item[0]);
|
||||
if (out) out = out.toISOString();
|
||||
equal(out, item[1]);
|
||||
});
|
||||
view.state.set({'nonUSDates': true});
|
||||
var out = view._parseDate('20/03/1914');
|
||||
equal(out, '03/20/1914');
|
||||
});
|
||||
|
||||
|
||||
@ -7,10 +7,10 @@ test('basics', function () {
|
||||
});
|
||||
$('.fixtures').append(view.el);
|
||||
assertPresent('.js-add-filter', view.elSidebar);
|
||||
var $addForm = view.el.find('form.js-add');
|
||||
var $addForm = view.$el.find('form.js-add');
|
||||
ok(!$addForm.is(":visible"));
|
||||
view.el.find('.js-add-filter').click();
|
||||
ok(!view.el.find('.js-add-filter').is(":visible"));
|
||||
view.$el.find('.js-add-filter').click();
|
||||
ok(!view.$el.find('.js-add-filter').is(":visible"));
|
||||
ok($addForm.is(":visible"));
|
||||
|
||||
// submit the form
|
||||
@ -19,7 +19,7 @@ test('basics', function () {
|
||||
|
||||
// now check we have new filter
|
||||
ok(!$addForm.is(":visible"));
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
equal($editForm.find('.filter-term').length, 1)
|
||||
equal(dataset.queryState.attributes.filters[0].field, 'country');
|
||||
|
||||
@ -30,30 +30,30 @@ test('basics', function () {
|
||||
equal(dataset.records.length, 3);
|
||||
|
||||
// now set a second range filter ...
|
||||
view.el.find('.js-add-filter').click();
|
||||
var $addForm = view.el.find('form.js-add');
|
||||
view.$el.find('.js-add-filter').click();
|
||||
var $addForm = view.$el.find('form.js-add');
|
||||
$addForm.find('select.fields').val('x');
|
||||
$addForm.find('select.filterType').val('range');
|
||||
$addForm.submit();
|
||||
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
$editForm.find('.filter-range input').first().val('2');
|
||||
$editForm.find('.filter-range input').last().val('4');
|
||||
$editForm.submit();
|
||||
equal(dataset.queryState.attributes.filters[0].term, 'UK');
|
||||
equal(dataset.queryState.attributes.filters[1].start, 2);
|
||||
equal(dataset.queryState.attributes.filters[1].from, 2);
|
||||
equal(dataset.records.length, 2);
|
||||
|
||||
// now remove filter
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
$editForm.find('.js-remove-filter').last().click();
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
equal($editForm.find('.filter').length, 1)
|
||||
equal(dataset.records.length, 3);
|
||||
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
$editForm.find('.js-remove-filter').last().click();
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
equal($editForm.find('.filter').length, 0)
|
||||
equal(dataset.records.length, 6);
|
||||
|
||||
@ -68,18 +68,18 @@ test('add 2 filters of same type', function () {
|
||||
$('.fixtures').append(view.el);
|
||||
|
||||
// add 2 term filters
|
||||
var $addForm = view.el.find('form.js-add');
|
||||
view.el.find('.js-add-filter').click();
|
||||
var $addForm = view.$el.find('form.js-add');
|
||||
view.$el.find('.js-add-filter').click();
|
||||
$addForm.find('select.fields').val('country');
|
||||
$addForm.submit();
|
||||
|
||||
var $addForm = view.el.find('form.js-add');
|
||||
view.el.find('.js-add-filter').click();
|
||||
var $addForm = view.$el.find('form.js-add');
|
||||
view.$el.find('.js-add-filter').click();
|
||||
$addForm.find('select.fields').val('id');
|
||||
$addForm.submit();
|
||||
|
||||
var fields = [];
|
||||
view.el.find('form.js-edit .filter-term input').each(function(idx, item) {
|
||||
view.$el.find('form.js-edit .filter-term input').each(function(idx, item) {
|
||||
fields.push($(item).attr('data-filter-field'));
|
||||
});
|
||||
deepEqual(fields, ['country', 'id']);
|
||||
@ -94,14 +94,14 @@ test('geo_distance', function () {
|
||||
});
|
||||
$('.fixtures').append(view.el);
|
||||
|
||||
var $addForm = view.el.find('form.js-add');
|
||||
var $addForm = view.$el.find('form.js-add');
|
||||
// submit the form
|
||||
$addForm.find('select.filterType').val('geo_distance');
|
||||
$addForm.find('select.fields').val('lon');
|
||||
$addForm.submit();
|
||||
|
||||
// now check we have new filter
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
equal($editForm.find('.filter-geo_distance').length, 1)
|
||||
deepEqual(_.sortBy(_.keys(dataset.queryState.attributes.filters[0]),_.identity),
|
||||
["distance", "field", "point", "type", "unit"]);
|
||||
|
||||
@ -7,10 +7,10 @@ test('basics', function () {
|
||||
});
|
||||
$('.fixtures').append(view.el);
|
||||
assertPresent('.js-add-filter', view.elSidebar);
|
||||
var $addForm = view.el.find('form.js-add');
|
||||
var $addForm = view.$el.find('form.js-add');
|
||||
ok(!$addForm.is(":visible"));
|
||||
view.el.find('.js-add-filter').click();
|
||||
ok(!view.el.find('.js-add-filter').is(":visible"));
|
||||
view.$el.find('.js-add-filter').click();
|
||||
ok(!view.$el.find('.js-add-filter').is(":visible"));
|
||||
ok($addForm.is(":visible"));
|
||||
|
||||
// submit the form
|
||||
@ -19,7 +19,7 @@ test('basics', function () {
|
||||
|
||||
// now check we have new filter
|
||||
ok(!$addForm.is(":visible"));
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
equal($editForm.find('.filter-term').length, 1);
|
||||
equal(dataset.queryState.attributes.filters[0].field, 'country');
|
||||
|
||||
@ -30,9 +30,9 @@ test('basics', function () {
|
||||
equal(dataset.records.length, 3);
|
||||
|
||||
// now remove filter
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
$editForm.find('.js-remove-filter').last().click();
|
||||
$editForm = view.el.find('form.js-edit');
|
||||
$editForm = view.$el.find('form.js-edit');
|
||||
equal($editForm.find('.filter').length, 0);
|
||||
equal(dataset.records.length, 6);
|
||||
|
||||
@ -47,18 +47,19 @@ test('add 2 filters', function () {
|
||||
$('.fixtures').append(view.el);
|
||||
|
||||
// add 2 term filters
|
||||
var $addForm = view.el.find('form.js-add');
|
||||
view.el.find('.js-add-filter').click();
|
||||
var $addForm = view.$el.find('form.js-add');
|
||||
view.$el.find('.js-add-filter').click();
|
||||
|
||||
$addForm.find('select.fields').val('country');
|
||||
$addForm.submit();
|
||||
|
||||
$addForm = view.el.find('form.js-add');
|
||||
view.el.find('.js-add-filter').click();
|
||||
$addForm = view.$el.find('form.js-add');
|
||||
view.$el.find('.js-add-filter').click();
|
||||
$addForm.find('select.fields').val('id');
|
||||
$addForm.submit();
|
||||
|
||||
var fields = [];
|
||||
view.el.find('form.js-edit .filter-term input').each(function(idx, item) {
|
||||
view.$el.find('form.js-edit .filter-term input').each(function(idx, item) {
|
||||
fields.push($(item).attr('data-filter-field'));
|
||||
});
|
||||
deepEqual(fields, ['country', 'id']);
|
||||
|
||||
38
vendor/backbone/0.9.2/backbone-min.js
vendored
38
vendor/backbone/0.9.2/backbone-min.js
vendored
@ -1,38 +0,0 @@
|
||||
// Backbone.js 0.9.2
|
||||
|
||||
// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Backbone may be freely distributed under the MIT license.
|
||||
// For all details and documentation:
|
||||
// http://backbonejs.org
|
||||
(function(){var l=this,y=l.Backbone,z=Array.prototype.slice,A=Array.prototype.splice,g;g="undefined"!==typeof exports?exports:l.Backbone={};g.VERSION="0.9.2";var f=l._;!f&&"undefined"!==typeof require&&(f=require("underscore"));var i=l.jQuery||l.Zepto||l.ender;g.setDomLibrary=function(a){i=a};g.noConflict=function(){l.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var p=/\s+/,k=g.Events={on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(p);for(d=this._callbacks||(this._callbacks=
|
||||
{});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,h,g,j,q;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(p):f.keys(e);d=a.shift();)if(h=e[d],delete e[d],h&&(b||c))for(g=h.tail;(h=h.next)!==g;)if(j=h.callback,q=h.context,b&&j!==b||c&&q!==c)this.on(d,j,q);return this}},trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(p);for(g=
|
||||
z.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};k.bind=k.on;k.unbind=k.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent=
|
||||
{};this._pending={};this.set(a,{silent:!0});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,k,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(null==
|
||||
b?"":""+b)},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof o&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=c.changes={},h=this.attributes,g=this._escapedAttributes,j=this._previousAttributes||{};for(e in d){a=d[e];if(!f.isEqual(h[e],a)||c.unset&&f.has(h,e))delete g[e],(c.silent?this._silent:
|
||||
b)[e]=!0;c.unset?delete h[e]:h[e]=a;!f.isEqual(j[e],a)||f.has(h,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=!0)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)};
|
||||
a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return!1;e=f.clone(this.attributes)}a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var h=this,i=c.success;c.success=function(a,b,e){b=h.parse(a,e);if(c.wait){delete c.wait;b=f.extend(d||{},b)}if(!h.set(b,c))return false;i?i(h,a):h.trigger("sync",h,a,c)};c.error=g.wrapError(c.error,
|
||||
h,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),!1;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t();
|
||||
return this.isNew()?a:a+("/"==a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){a||(a={});var b=this._changing;this._changing=!0;for(var c in this._silent)this._pending[c]=!0;var d=f.extend({},a.changes,this._silent);this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending=
|
||||
{};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length||
|
||||
!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger("error",this,c,b);return!1}});var r=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);b.comparator&&(this.comparator=b.comparator);
|
||||
this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(r.prototype,k,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,i,j={},k={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];c=0;for(d=a.length;c<d;c++){if(!(e=a[c]=this._prepareModel(a[c],b)))throw Error("Can't add an invalid model to a collection");g=e.cid;i=e.id;j[g]||this._byCid[g]||null!=i&&(k[i]||this._byId[i])?
|
||||
l.push(c):j[g]=k[i]=e}for(c=l.length;c--;)a.splice(l[c],1);c=0;for(d=a.length;c<d;c++)(e=a[c]).on("all",this._onModelEvent,this),this._byCid[e.cid]=e,null!=e.id&&(this._byId[e.id]=e);this.length+=d;A.apply(this.models,[null!=b.at?b.at:this.models.length,0].concat(a));this.comparator&&this.sort({silent:!0});if(b.silent)return this;c=0;for(d=this.models.length;c<d;c++)if(j[(e=this.models[c]).cid])b.index=c,e.trigger("add",e,this,b);return this},remove:function(a,b){var c,d,e,g;b||(b={});a=f.isArray(a)?
|
||||
a.slice():[a];c=0;for(d=a.length;c<d;c++)if(g=this.getByCid(a[c])||this.get(a[c]))delete this._byId[g.id],delete this._byCid[g.cid],e=this.indexOf(g),this.models.splice(e,1),this.length--,b.silent||(b.index=e,g.trigger("remove",g,this,b)),this._removeReference(g);return this},push:function(a,b){a=this._prepareModel(a,b);this.add(a,b);return a},pop:function(a){var b=this.at(this.length-1);this.remove(b,a);return b},unshift:function(a,b){a=this._prepareModel(a,b);this.add(a,f.extend({at:0},b));return a},
|
||||
shift:function(a){var b=this.at(0);this.remove(b,a);return b},get:function(a){return null==a?void 0:this._byId[null!=a.id?a.id:a]},getByCid:function(a){return a&&this._byCid[a.cid||a]},at:function(a){return this.models[a]},where:function(a){return f.isEmpty(a)?[]:this.filter(function(b){for(var c in a)if(a[c]!==b.get(c))return!1;return!0})},sort:function(a){a||(a={});if(!this.comparator)throw Error("Cannot sort a set without a comparator");var b=f.bind(this.comparator,this);1==this.comparator.length?
|
||||
this.models=this.sortBy(b):this.models.sort(b);a.silent||this.trigger("reset",this,a);return this},pluck:function(a){return f.map(this.models,function(b){return b.get(a)})},reset:function(a,b){a||(a=[]);b||(b={});for(var c=0,d=this.models.length;c<d;c++)this._removeReference(this.models[c]);this._reset();this.add(a,f.extend({silent:!0},b));b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a=a?f.clone(a):{};void 0===a.parse&&(a.parse=!0);var b=this,c=a.success;a.success=function(d,
|
||||
e,f){b[a.add?"add":"reset"](b.parse(d,f),a);c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},create:function(a,b){var c=this,b=b?f.clone(b):{},a=this._prepareModel(a,b);if(!a)return!1;b.wait||c.add(a,b);var d=b.success;b.success=function(e,f){b.wait&&c.add(e,b);d?d(e,f):e.trigger("sync",a,f,b)};a.save(null,b);return a},parse:function(a){return a},chain:function(){return f(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId=
|
||||
{};this._byCid={}},_prepareModel:function(a,b){b||(b={});a instanceof o?a.collection||(a.collection=this):(b.collection=this,a=new this.model(a,b),a._validate(a.attributes,b)||(a=!1));return a},_removeReference:function(a){this==a.collection&&delete a.collection;a.off("all",this._onModelEvent,this)},_onModelEvent:function(a,b,c,d){("add"==a||"remove"==a)&&c!=this||("destroy"==a&&this.remove(b,d),b&&a==="change:"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],this._byId[b.id]=b),this.trigger.apply(this,
|
||||
arguments))}});f.each("forEach,each,map,reduce,reduceRight,find,detect,filter,select,reject,every,all,some,any,include,contains,invoke,max,min,sortBy,sortedIndex,toArray,size,first,initial,rest,last,without,indexOf,shuffle,lastIndexOf,isEmpty,groupBy".split(","),function(a){r.prototype[a]=function(){return f[a].apply(f,[this.models].concat(f.toArray(arguments)))}});var u=g.Router=function(a){a||(a={});a.routes&&(this.routes=a.routes);this._bindRoutes();this.initialize.apply(this,arguments)},B=/:\w+/g,
|
||||
C=/\*\w+/g,D=/[-[\]{}()+?.,\\^$|#\s]/g;f.extend(u.prototype,k,{initialize:function(){},route:function(a,b,c){g.history||(g.history=new m);f.isRegExp(a)||(a=this._routeToRegExp(a));c||(c=this[b]);g.history.route(a,f.bind(function(d){d=this._extractParameters(a,d);c&&c.apply(this,d);this.trigger.apply(this,["route:"+b].concat(d));g.history.trigger("route",this,b,d)},this));return this},navigate:function(a,b){g.history.navigate(a,b)},_bindRoutes:function(){if(this.routes){var a=[],b;for(b in this.routes)a.unshift([b,
|
||||
this.routes[b]]);b=0;for(var c=a.length;b<c;b++)this.route(a[b][0],a[b][1],this[a[b][1]])}},_routeToRegExp:function(a){a=a.replace(D,"\\$&").replace(B,"([^/]+)").replace(C,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});var m=g.History=function(){this.handlers=[];f.bindAll(this,"checkUrl")},s=/^[#\/]/,E=/msie [\w.]+/;m.started=!1;f.extend(m.prototype,k,{interval:50,getHash:function(a){return(a=(a?a.location:window.location).href.match(/#(.*)$/))?a[1]:
|
||||
""},getFragment:function(a,b){if(null==a)if(this._hasPushState||b){var a=window.location.pathname,c=window.location.search;c&&(a+=c)}else a=this.getHash();a.indexOf(this.options.root)||(a=a.substr(this.options.root.length));return a.replace(s,"")},start:function(a){if(m.started)throw Error("Backbone.history has already been started");m.started=!0;this.options=f.extend({},{root:"/"},this.options,a);this._wantsHashChange=!1!==this.options.hashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=
|
||||
!(!this.options.pushState||!window.history||!window.history.pushState);var a=this.getFragment(),b=document.documentMode;if(b=E.exec(navigator.userAgent.toLowerCase())&&(!b||7>=b))this.iframe=i('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a);this._hasPushState?i(window).bind("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!b?i(window).bind("hashchange",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,
|
||||
this.interval));this.fragment=a;a=window.location;b=a.pathname==this.options.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),window.location.replace(this.options.root+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&b&&a.hash&&(this.fragment=this.getHash().replace(s,""),window.history.replaceState({},document.title,a.protocol+"//"+a.host+this.options.root+this.fragment));if(!this.options.silent)return this.loadUrl()},
|
||||
stop:function(){i(window).unbind("popstate",this.checkUrl).unbind("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);m.started=!1},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.getHash(this.iframe)));if(a==this.fragment)return!1;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(a){var b=this.fragment=this.getFragment(a);return f.any(this.handlers,
|
||||
function(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){if(!m.started)return!1;if(!b||!0===b)b={trigger:b};var c=(a||"").replace(s,"");this.fragment!=c&&(this._hasPushState?(0!=c.indexOf(this.options.root)&&(c=this.options.root+c),this.fragment=c,window.history[b.replace?"replaceState":"pushState"]({},document.title,c)):this._wantsHashChange?(this.fragment=c,this._updateHash(window.location,c,b.replace),this.iframe&&c!=this.getFragment(this.getHash(this.iframe))&&(b.replace||
|
||||
this.iframe.document.open().close(),this._updateHash(this.iframe.location,c,b.replace))):window.location.assign(this.options.root+a),b.trigger&&this.loadUrl(a))},_updateHash:function(a,b,c){c?a.replace(a.toString().replace(/(javascript:|#).*$/,"")+"#"+b):a.hash=b}});var v=g.View=function(a){this.cid=f.uniqueId("view");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},F=/^(\S+)\s*(.*)$/,w="model,collection,el,id,attributes,className,tagName".split(",");
|
||||
f.extend(v.prototype,k,{tagName:"div",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();return this},make:function(a,b,c){a=document.createElement(a);b&&i(a).attr(b);c&&i(a).html(c);return a},setElement:function(a,b){this.$el&&this.undelegateEvents();this.$el=a instanceof i?a:i(a);this.el=this.$el[0];!1!==b&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=n(this,"events"))){this.undelegateEvents();
|
||||
for(var b in a){var c=a[b];f.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method "'+a[b]+'" does not exist');var d=b.match(F),e=d[1],d=d[2],c=f.bind(c,this),e=e+(".delegateEvents"+this.cid);""===d?this.$el.bind(e,c):this.$el.delegate(d,e,c)}}},undelegateEvents:function(){this.$el.unbind(".delegateEvents"+this.cid)},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=0,c=w.length;b<c;b++){var d=w[b];a[d]&&(this[d]=a[d])}this.options=a},_ensureElement:function(){if(this.el)this.setElement(this.el,
|
||||
!1);else{var a=n(this,"attributes")||{};this.id&&(a.id=this.id);this.className&&(a["class"]=this.className);this.setElement(this.make(this.tagName,a),!1)}}});o.extend=r.extend=u.extend=v.extend=function(a,b){var c=G(this,a,b);c.extend=this.extend;return c};var H={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};g.sync=function(a,b,c){var d=H[a];c||(c={});var e={type:d,dataType:"json"};c.url||(e.url=n(b,"url")||t());if(!c.data&&b&&("create"==a||"update"==a))e.contentType="application/json",
|
||||
e.data=JSON.stringify(b.toJSON());g.emulateJSON&&(e.contentType="application/x-www-form-urlencoded",e.data=e.data?{model:e.data}:{});if(g.emulateHTTP&&("PUT"===d||"DELETE"===d))g.emulateJSON&&(e.data._method=d),e.type="POST",e.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",d)};"GET"!==e.type&&!g.emulateJSON&&(e.processData=!1);return i.ajax(f.extend(e,c))};g.wrapError=function(a,b,c){return function(d,e){e=d===b?e:d;a?a(b,e,c):b.trigger("error",b,e,c)}};var x=function(){},G=function(a,
|
||||
b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){a.apply(this,arguments)};f.extend(d,a);x.prototype=a.prototype;d.prototype=new x;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},n=function(a,b){return!a||!a[b]?null:f.isFunction(a[b])?a[b]():a[b]},t=function(){throw Error('A "url" property or function must be specified');}}).call(this);
|
||||
1431
vendor/backbone/0.9.2/backbone.js
vendored
1431
vendor/backbone/0.9.2/backbone.js
vendored
File diff suppressed because it is too large
Load Diff
1571
vendor/backbone/1.0.0/backbone.js
vendored
Normal file
1571
vendor/backbone/1.0.0/backbone.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1111
vendor/flot/jquery.flot.js
vendored
1111
vendor/flot/jquery.flot.js
vendored
File diff suppressed because it is too large
Load Diff
431
vendor/flot/jquery.flot.time.js
vendored
Normal file
431
vendor/flot/jquery.flot.time.js
vendored
Normal file
@ -0,0 +1,431 @@
|
||||
/* Pretty handling of time axes.
|
||||
|
||||
Copyright (c) 2007-2013 IOLA and Ole Laursen.
|
||||
Licensed under the MIT license.
|
||||
|
||||
Set axis.mode to "time" to enable. See the section "Time series data" in
|
||||
API.txt for details.
|
||||
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var options = {
|
||||
xaxis: {
|
||||
timezone: null, // "browser" for local to the client or timezone for timezone-js
|
||||
timeformat: null, // format string to use
|
||||
twelveHourClock: false, // 12 or 24 time in time mode
|
||||
monthNames: null // list of names of months
|
||||
}
|
||||
};
|
||||
|
||||
// round to nearby lower multiple of base
|
||||
|
||||
function floorInBase(n, base) {
|
||||
return base * Math.floor(n / base);
|
||||
}
|
||||
|
||||
// Returns a string with the date d formatted according to fmt.
|
||||
// A subset of the Open Group's strftime format is supported.
|
||||
|
||||
function formatDate(d, fmt, monthNames, dayNames) {
|
||||
|
||||
if (typeof d.strftime == "function") {
|
||||
return d.strftime(fmt);
|
||||
}
|
||||
|
||||
var leftPad = function(n, pad) {
|
||||
n = "" + n;
|
||||
pad = "" + (pad == null ? "0" : pad);
|
||||
return n.length == 1 ? pad + n : n;
|
||||
};
|
||||
|
||||
var r = [];
|
||||
var escape = false;
|
||||
var hours = d.getHours();
|
||||
var isAM = hours < 12;
|
||||
|
||||
if (monthNames == null) {
|
||||
monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||
}
|
||||
|
||||
if (dayNames == null) {
|
||||
dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||
}
|
||||
|
||||
var hours12;
|
||||
|
||||
if (hours > 12) {
|
||||
hours12 = hours - 12;
|
||||
} else if (hours == 0) {
|
||||
hours12 = 12;
|
||||
} else {
|
||||
hours12 = hours;
|
||||
}
|
||||
|
||||
for (var i = 0; i < fmt.length; ++i) {
|
||||
|
||||
var c = fmt.charAt(i);
|
||||
|
||||
if (escape) {
|
||||
switch (c) {
|
||||
case 'a': c = "" + dayNames[d.getDay()]; break;
|
||||
case 'b': c = "" + monthNames[d.getMonth()]; break;
|
||||
case 'd': c = leftPad(d.getDate()); break;
|
||||
case 'e': c = leftPad(d.getDate(), " "); break;
|
||||
case 'h': // For back-compat with 0.7; remove in 1.0
|
||||
case 'H': c = leftPad(hours); break;
|
||||
case 'I': c = leftPad(hours12); break;
|
||||
case 'l': c = leftPad(hours12, " "); break;
|
||||
case 'm': c = leftPad(d.getMonth() + 1); break;
|
||||
case 'M': c = leftPad(d.getMinutes()); break;
|
||||
// quarters not in Open Group's strftime specification
|
||||
case 'q':
|
||||
c = "" + (Math.floor(d.getMonth() / 3) + 1); break;
|
||||
case 'S': c = leftPad(d.getSeconds()); break;
|
||||
case 'y': c = leftPad(d.getFullYear() % 100); break;
|
||||
case 'Y': c = "" + d.getFullYear(); break;
|
||||
case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
|
||||
case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
|
||||
case 'w': c = "" + d.getDay(); break;
|
||||
}
|
||||
r.push(c);
|
||||
escape = false;
|
||||
} else {
|
||||
if (c == "%") {
|
||||
escape = true;
|
||||
} else {
|
||||
r.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return r.join("");
|
||||
}
|
||||
|
||||
// To have a consistent view of time-based data independent of which time
|
||||
// zone the client happens to be in we need a date-like object independent
|
||||
// of time zones. This is done through a wrapper that only calls the UTC
|
||||
// versions of the accessor methods.
|
||||
|
||||
function makeUtcWrapper(d) {
|
||||
|
||||
function addProxyMethod(sourceObj, sourceMethod, targetObj, targetMethod) {
|
||||
sourceObj[sourceMethod] = function() {
|
||||
return targetObj[targetMethod].apply(targetObj, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
var utc = {
|
||||
date: d
|
||||
};
|
||||
|
||||
// support strftime, if found
|
||||
|
||||
if (d.strftime != undefined) {
|
||||
addProxyMethod(utc, "strftime", d, "strftime");
|
||||
}
|
||||
|
||||
addProxyMethod(utc, "getTime", d, "getTime");
|
||||
addProxyMethod(utc, "setTime", d, "setTime");
|
||||
|
||||
var props = ["Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds"];
|
||||
|
||||
for (var p = 0; p < props.length; p++) {
|
||||
addProxyMethod(utc, "get" + props[p], d, "getUTC" + props[p]);
|
||||
addProxyMethod(utc, "set" + props[p], d, "setUTC" + props[p]);
|
||||
}
|
||||
|
||||
return utc;
|
||||
};
|
||||
|
||||
// select time zone strategy. This returns a date-like object tied to the
|
||||
// desired timezone
|
||||
|
||||
function dateGenerator(ts, opts) {
|
||||
if (opts.timezone == "browser") {
|
||||
return new Date(ts);
|
||||
} else if (!opts.timezone || opts.timezone == "utc") {
|
||||
return makeUtcWrapper(new Date(ts));
|
||||
} else if (typeof timezoneJS != "undefined" && typeof timezoneJS.Date != "undefined") {
|
||||
var d = new timezoneJS.Date();
|
||||
// timezone-js is fickle, so be sure to set the time zone before
|
||||
// setting the time.
|
||||
d.setTimezone(opts.timezone);
|
||||
d.setTime(ts);
|
||||
return d;
|
||||
} else {
|
||||
return makeUtcWrapper(new Date(ts));
|
||||
}
|
||||
}
|
||||
|
||||
// map of app. size of time units in milliseconds
|
||||
|
||||
var timeUnitSize = {
|
||||
"second": 1000,
|
||||
"minute": 60 * 1000,
|
||||
"hour": 60 * 60 * 1000,
|
||||
"day": 24 * 60 * 60 * 1000,
|
||||
"month": 30 * 24 * 60 * 60 * 1000,
|
||||
"quarter": 3 * 30 * 24 * 60 * 60 * 1000,
|
||||
"year": 365.2425 * 24 * 60 * 60 * 1000
|
||||
};
|
||||
|
||||
// the allowed tick sizes, after 1 year we use
|
||||
// an integer algorithm
|
||||
|
||||
var baseSpec = [
|
||||
[1, "second"], [2, "second"], [5, "second"], [10, "second"],
|
||||
[30, "second"],
|
||||
[1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
|
||||
[30, "minute"],
|
||||
[1, "hour"], [2, "hour"], [4, "hour"],
|
||||
[8, "hour"], [12, "hour"],
|
||||
[1, "day"], [2, "day"], [3, "day"],
|
||||
[0.25, "month"], [0.5, "month"], [1, "month"],
|
||||
[2, "month"]
|
||||
];
|
||||
|
||||
// we don't know which variant(s) we'll need yet, but generating both is
|
||||
// cheap
|
||||
|
||||
var specMonths = baseSpec.concat([[3, "month"], [6, "month"],
|
||||
[1, "year"]]);
|
||||
var specQuarters = baseSpec.concat([[1, "quarter"], [2, "quarter"],
|
||||
[1, "year"]]);
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processOptions.push(function (plot, options) {
|
||||
$.each(plot.getAxes(), function(axisName, axis) {
|
||||
|
||||
var opts = axis.options;
|
||||
|
||||
if (opts.mode == "time") {
|
||||
axis.tickGenerator = function(axis) {
|
||||
|
||||
var ticks = [];
|
||||
var d = dateGenerator(axis.min, opts);
|
||||
var minSize = 0;
|
||||
|
||||
// make quarter use a possibility if quarters are
|
||||
// mentioned in either of these options
|
||||
|
||||
var spec = (opts.tickSize && opts.tickSize[1] ===
|
||||
"quarter") ||
|
||||
(opts.minTickSize && opts.minTickSize[1] ===
|
||||
"quarter") ? specQuarters : specMonths;
|
||||
|
||||
if (opts.minTickSize != null) {
|
||||
if (typeof opts.tickSize == "number") {
|
||||
minSize = opts.tickSize;
|
||||
} else {
|
||||
minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < spec.length - 1; ++i) {
|
||||
if (axis.delta < (spec[i][0] * timeUnitSize[spec[i][1]]
|
||||
+ spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
|
||||
&& spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var size = spec[i][0];
|
||||
var unit = spec[i][1];
|
||||
|
||||
// special-case the possibility of several years
|
||||
|
||||
if (unit == "year") {
|
||||
|
||||
// if given a minTickSize in years, just use it,
|
||||
// ensuring that it's an integer
|
||||
|
||||
if (opts.minTickSize != null && opts.minTickSize[1] == "year") {
|
||||
size = Math.floor(opts.minTickSize[0]);
|
||||
} else {
|
||||
|
||||
var magn = Math.pow(10, Math.floor(Math.log(axis.delta / timeUnitSize.year) / Math.LN10));
|
||||
var norm = (axis.delta / timeUnitSize.year) / magn;
|
||||
|
||||
if (norm < 1.5) {
|
||||
size = 1;
|
||||
} else if (norm < 3) {
|
||||
size = 2;
|
||||
} else if (norm < 7.5) {
|
||||
size = 5;
|
||||
} else {
|
||||
size = 10;
|
||||
}
|
||||
|
||||
size *= magn;
|
||||
}
|
||||
|
||||
// minimum size for years is 1
|
||||
|
||||
if (size < 1) {
|
||||
size = 1;
|
||||
}
|
||||
}
|
||||
|
||||
axis.tickSize = opts.tickSize || [size, unit];
|
||||
var tickSize = axis.tickSize[0];
|
||||
unit = axis.tickSize[1];
|
||||
|
||||
var step = tickSize * timeUnitSize[unit];
|
||||
|
||||
if (unit == "second") {
|
||||
d.setSeconds(floorInBase(d.getSeconds(), tickSize));
|
||||
} else if (unit == "minute") {
|
||||
d.setMinutes(floorInBase(d.getMinutes(), tickSize));
|
||||
} else if (unit == "hour") {
|
||||
d.setHours(floorInBase(d.getHours(), tickSize));
|
||||
} else if (unit == "month") {
|
||||
d.setMonth(floorInBase(d.getMonth(), tickSize));
|
||||
} else if (unit == "quarter") {
|
||||
d.setMonth(3 * floorInBase(d.getMonth() / 3,
|
||||
tickSize));
|
||||
} else if (unit == "year") {
|
||||
d.setFullYear(floorInBase(d.getFullYear(), tickSize));
|
||||
}
|
||||
|
||||
// reset smaller components
|
||||
|
||||
d.setMilliseconds(0);
|
||||
|
||||
if (step >= timeUnitSize.minute) {
|
||||
d.setSeconds(0);
|
||||
}
|
||||
if (step >= timeUnitSize.hour) {
|
||||
d.setMinutes(0);
|
||||
}
|
||||
if (step >= timeUnitSize.day) {
|
||||
d.setHours(0);
|
||||
}
|
||||
if (step >= timeUnitSize.day * 4) {
|
||||
d.setDate(1);
|
||||
}
|
||||
if (step >= timeUnitSize.month * 2) {
|
||||
d.setMonth(floorInBase(d.getMonth(), 3));
|
||||
}
|
||||
if (step >= timeUnitSize.quarter * 2) {
|
||||
d.setMonth(floorInBase(d.getMonth(), 6));
|
||||
}
|
||||
if (step >= timeUnitSize.year) {
|
||||
d.setMonth(0);
|
||||
}
|
||||
|
||||
var carry = 0;
|
||||
var v = Number.NaN;
|
||||
var prev;
|
||||
|
||||
do {
|
||||
|
||||
prev = v;
|
||||
v = d.getTime();
|
||||
ticks.push(v);
|
||||
|
||||
if (unit == "month" || unit == "quarter") {
|
||||
if (tickSize < 1) {
|
||||
|
||||
// a bit complicated - we'll divide the
|
||||
// month/quarter up but we need to take
|
||||
// care of fractions so we don't end up in
|
||||
// the middle of a day
|
||||
|
||||
d.setDate(1);
|
||||
var start = d.getTime();
|
||||
d.setMonth(d.getMonth() +
|
||||
(unit == "quarter" ? 3 : 1));
|
||||
var end = d.getTime();
|
||||
d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
|
||||
carry = d.getHours();
|
||||
d.setHours(0);
|
||||
} else {
|
||||
d.setMonth(d.getMonth() +
|
||||
tickSize * (unit == "quarter" ? 3 : 1));
|
||||
}
|
||||
} else if (unit == "year") {
|
||||
d.setFullYear(d.getFullYear() + tickSize);
|
||||
} else {
|
||||
d.setTime(v + step);
|
||||
}
|
||||
} while (v < axis.max && v != prev);
|
||||
|
||||
return ticks;
|
||||
};
|
||||
|
||||
axis.tickFormatter = function (v, axis) {
|
||||
|
||||
var d = dateGenerator(v, axis.options);
|
||||
|
||||
// first check global format
|
||||
|
||||
if (opts.timeformat != null) {
|
||||
return formatDate(d, opts.timeformat, opts.monthNames, opts.dayNames);
|
||||
}
|
||||
|
||||
// possibly use quarters if quarters are mentioned in
|
||||
// any of these places
|
||||
|
||||
var useQuarters = (axis.options.tickSize &&
|
||||
axis.options.tickSize[1] == "quarter") ||
|
||||
(axis.options.minTickSize &&
|
||||
axis.options.minTickSize[1] == "quarter");
|
||||
|
||||
var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
|
||||
var span = axis.max - axis.min;
|
||||
var suffix = (opts.twelveHourClock) ? " %p" : "";
|
||||
var hourCode = (opts.twelveHourClock) ? "%I" : "%H";
|
||||
var fmt;
|
||||
|
||||
if (t < timeUnitSize.minute) {
|
||||
fmt = hourCode + ":%M:%S" + suffix;
|
||||
} else if (t < timeUnitSize.day) {
|
||||
if (span < 2 * timeUnitSize.day) {
|
||||
fmt = hourCode + ":%M" + suffix;
|
||||
} else {
|
||||
fmt = "%b %d " + hourCode + ":%M" + suffix;
|
||||
}
|
||||
} else if (t < timeUnitSize.month) {
|
||||
fmt = "%b %d";
|
||||
} else if ((useQuarters && t < timeUnitSize.quarter) ||
|
||||
(!useQuarters && t < timeUnitSize.year)) {
|
||||
if (span < timeUnitSize.year) {
|
||||
fmt = "%b";
|
||||
} else {
|
||||
fmt = "%b %Y";
|
||||
}
|
||||
} else if (useQuarters && t < timeUnitSize.year) {
|
||||
if (span < timeUnitSize.year) {
|
||||
fmt = "Q%q";
|
||||
} else {
|
||||
fmt = "Q%q %Y";
|
||||
}
|
||||
} else {
|
||||
fmt = "%Y";
|
||||
}
|
||||
|
||||
var rt = formatDate(d, fmt, opts.monthNames, opts.dayNames);
|
||||
|
||||
return rt;
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'time',
|
||||
version: '1.0'
|
||||
});
|
||||
|
||||
// Time-axis support used to be in Flot core, which exposed the
|
||||
// formatDate function on the plot object. Various plugins depend
|
||||
// on the function, so we need to re-expose it here.
|
||||
|
||||
$.plot.formatDate = formatDate;
|
||||
|
||||
})(jQuery);
|
||||
918
vendor/moment/1.6.2/moment.js
vendored
918
vendor/moment/1.6.2/moment.js
vendored
@ -1,918 +0,0 @@
|
||||
// moment.js
|
||||
// version : 1.6.2
|
||||
// author : Tim Wood
|
||||
// license : MIT
|
||||
// momentjs.com
|
||||
|
||||
(function (Date, undefined) {
|
||||
|
||||
var moment,
|
||||
VERSION = "1.6.2",
|
||||
round = Math.round, i,
|
||||
// internal storage for language config files
|
||||
languages = {},
|
||||
currentLanguage = 'en',
|
||||
|
||||
// check for nodeJS
|
||||
hasModule = (typeof module !== 'undefined'),
|
||||
|
||||
// parameters to check for on the lang config
|
||||
langConfigProperties = 'months|monthsShort|monthsParse|weekdays|weekdaysShort|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'),
|
||||
|
||||
// ASP.NET json date format regex
|
||||
aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
|
||||
|
||||
// format tokens
|
||||
formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|LT|LL?L?L?)/g,
|
||||
|
||||
// parsing tokens
|
||||
parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
|
||||
|
||||
// parsing token regexes
|
||||
parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
|
||||
parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
|
||||
parseTokenThreeDigits = /\d{3}/, // 000 - 999
|
||||
parseTokenFourDigits = /\d{4}/, // 0000 - 9999
|
||||
parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i, // any word characters or numbers
|
||||
parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
|
||||
parseTokenT = /T/i, // T (ISO seperator)
|
||||
|
||||
// preliminary iso regex
|
||||
// 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
|
||||
isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
|
||||
isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
|
||||
|
||||
// iso time formats and regexes
|
||||
isoTimes = [
|
||||
['HH:mm:ss.S', /T\d\d:\d\d:\d\d\.\d{1,3}/],
|
||||
['HH:mm:ss', /T\d\d:\d\d:\d\d/],
|
||||
['HH:mm', /T\d\d:\d\d/],
|
||||
['HH', /T\d\d/]
|
||||
],
|
||||
|
||||
// timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
|
||||
parseTimezoneChunker = /([\+\-]|\d\d)/gi,
|
||||
|
||||
// getter and setter names
|
||||
proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
|
||||
unitMillisecondFactors = {
|
||||
'Milliseconds' : 1,
|
||||
'Seconds' : 1e3,
|
||||
'Minutes' : 6e4,
|
||||
'Hours' : 36e5,
|
||||
'Days' : 864e5,
|
||||
'Months' : 2592e6,
|
||||
'Years' : 31536e6
|
||||
};
|
||||
|
||||
// Moment prototype object
|
||||
function Moment(date, isUTC) {
|
||||
this._d = date;
|
||||
this._isUTC = !!isUTC;
|
||||
}
|
||||
|
||||
function absRound(number) {
|
||||
if (number < 0) {
|
||||
return Math.ceil(number);
|
||||
} else {
|
||||
return Math.floor(number);
|
||||
}
|
||||
}
|
||||
|
||||
// Duration Constructor
|
||||
function Duration(duration) {
|
||||
var data = this._data = {},
|
||||
years = duration.years || duration.y || 0,
|
||||
months = duration.months || duration.M || 0,
|
||||
weeks = duration.weeks || duration.w || 0,
|
||||
days = duration.days || duration.d || 0,
|
||||
hours = duration.hours || duration.h || 0,
|
||||
minutes = duration.minutes || duration.m || 0,
|
||||
seconds = duration.seconds || duration.s || 0,
|
||||
milliseconds = duration.milliseconds || duration.ms || 0;
|
||||
|
||||
// representation for dateAddRemove
|
||||
this._milliseconds = milliseconds +
|
||||
seconds * 1e3 + // 1000
|
||||
minutes * 6e4 + // 1000 * 60
|
||||
hours * 36e5; // 1000 * 60 * 60
|
||||
// Because of dateAddRemove treats 24 hours as different from a
|
||||
// day when working around DST, we need to store them separately
|
||||
this._days = days +
|
||||
weeks * 7;
|
||||
// It is impossible translate months into days without knowing
|
||||
// which months you are are talking about, so we have to store
|
||||
// it separately.
|
||||
this._months = months +
|
||||
years * 12;
|
||||
|
||||
// The following code bubbles up values, see the tests for
|
||||
// examples of what that means.
|
||||
data.milliseconds = milliseconds % 1000;
|
||||
seconds += absRound(milliseconds / 1000);
|
||||
|
||||
data.seconds = seconds % 60;
|
||||
minutes += absRound(seconds / 60);
|
||||
|
||||
data.minutes = minutes % 60;
|
||||
hours += absRound(minutes / 60);
|
||||
|
||||
data.hours = hours % 24;
|
||||
days += absRound(hours / 24);
|
||||
|
||||
days += weeks * 7;
|
||||
data.days = days % 30;
|
||||
|
||||
months += absRound(days / 30);
|
||||
|
||||
data.months = months % 12;
|
||||
years += absRound(months / 12);
|
||||
|
||||
data.years = years;
|
||||
}
|
||||
|
||||
// left zero fill a number
|
||||
// see http://jsperf.com/left-zero-filling for performance comparison
|
||||
function leftZeroFill(number, targetLength) {
|
||||
var output = number + '';
|
||||
while (output.length < targetLength) {
|
||||
output = '0' + output;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// helper function for _.addTime and _.subtractTime
|
||||
function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
|
||||
var ms = duration._milliseconds,
|
||||
d = duration._days,
|
||||
M = duration._months,
|
||||
currentDate;
|
||||
|
||||
if (ms) {
|
||||
mom._d.setTime(+mom + ms * isAdding);
|
||||
}
|
||||
if (d) {
|
||||
mom.date(mom.date() + d * isAdding);
|
||||
}
|
||||
if (M) {
|
||||
currentDate = mom.date();
|
||||
mom.date(1)
|
||||
.month(mom.month() + M * isAdding)
|
||||
.date(Math.min(currentDate, mom.daysInMonth()));
|
||||
}
|
||||
}
|
||||
|
||||
// check if is an array
|
||||
function isArray(input) {
|
||||
return Object.prototype.toString.call(input) === '[object Array]';
|
||||
}
|
||||
|
||||
// convert an array to a date.
|
||||
// the array should mirror the parameters below
|
||||
// note: all values past the year are optional and will default to the lowest possible value.
|
||||
// [year, month, day , hour, minute, second, millisecond]
|
||||
function dateFromArray(input) {
|
||||
return new Date(input[0], input[1] || 0, input[2] || 1, input[3] || 0, input[4] || 0, input[5] || 0, input[6] || 0);
|
||||
}
|
||||
|
||||
// format date using native date object
|
||||
function formatMoment(m, inputString) {
|
||||
var currentMonth = m.month(),
|
||||
currentDate = m.date(),
|
||||
currentYear = m.year(),
|
||||
currentDay = m.day(),
|
||||
currentHours = m.hours(),
|
||||
currentMinutes = m.minutes(),
|
||||
currentSeconds = m.seconds(),
|
||||
currentMilliseconds = m.milliseconds(),
|
||||
currentZone = -m.zone(),
|
||||
ordinal = moment.ordinal,
|
||||
meridiem = moment.meridiem;
|
||||
// check if the character is a format
|
||||
// return formatted string or non string.
|
||||
//
|
||||
// uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380)
|
||||
// for minification and performance
|
||||
// see http://jsperf.com/object-of-functions-vs-switch for performance comparison
|
||||
function replaceFunction(input) {
|
||||
// create a couple variables to be used later inside one of the cases.
|
||||
var a, b;
|
||||
switch (input) {
|
||||
// MONTH
|
||||
case 'M' :
|
||||
return currentMonth + 1;
|
||||
case 'Mo' :
|
||||
return (currentMonth + 1) + ordinal(currentMonth + 1);
|
||||
case 'MM' :
|
||||
return leftZeroFill(currentMonth + 1, 2);
|
||||
case 'MMM' :
|
||||
return moment.monthsShort[currentMonth];
|
||||
case 'MMMM' :
|
||||
return moment.months[currentMonth];
|
||||
// DAY OF MONTH
|
||||
case 'D' :
|
||||
return currentDate;
|
||||
case 'Do' :
|
||||
return currentDate + ordinal(currentDate);
|
||||
case 'DD' :
|
||||
return leftZeroFill(currentDate, 2);
|
||||
// DAY OF YEAR
|
||||
case 'DDD' :
|
||||
a = new Date(currentYear, currentMonth, currentDate);
|
||||
b = new Date(currentYear, 0, 1);
|
||||
return ~~ (((a - b) / 864e5) + 1.5);
|
||||
case 'DDDo' :
|
||||
a = replaceFunction('DDD');
|
||||
return a + ordinal(a);
|
||||
case 'DDDD' :
|
||||
return leftZeroFill(replaceFunction('DDD'), 3);
|
||||
// WEEKDAY
|
||||
case 'd' :
|
||||
return currentDay;
|
||||
case 'do' :
|
||||
return currentDay + ordinal(currentDay);
|
||||
case 'ddd' :
|
||||
return moment.weekdaysShort[currentDay];
|
||||
case 'dddd' :
|
||||
return moment.weekdays[currentDay];
|
||||
// WEEK OF YEAR
|
||||
case 'w' :
|
||||
a = new Date(currentYear, currentMonth, currentDate - currentDay + 5);
|
||||
b = new Date(a.getFullYear(), 0, 4);
|
||||
return ~~ ((a - b) / 864e5 / 7 + 1.5);
|
||||
case 'wo' :
|
||||
a = replaceFunction('w');
|
||||
return a + ordinal(a);
|
||||
case 'ww' :
|
||||
return leftZeroFill(replaceFunction('w'), 2);
|
||||
// YEAR
|
||||
case 'YY' :
|
||||
return leftZeroFill(currentYear % 100, 2);
|
||||
case 'YYYY' :
|
||||
return currentYear;
|
||||
// AM / PM
|
||||
case 'a' :
|
||||
return meridiem ? meridiem(currentHours, currentMinutes, false) : (currentHours > 11 ? 'pm' : 'am');
|
||||
case 'A' :
|
||||
return meridiem ? meridiem(currentHours, currentMinutes, true) : (currentHours > 11 ? 'PM' : 'AM');
|
||||
// 24 HOUR
|
||||
case 'H' :
|
||||
return currentHours;
|
||||
case 'HH' :
|
||||
return leftZeroFill(currentHours, 2);
|
||||
// 12 HOUR
|
||||
case 'h' :
|
||||
return currentHours % 12 || 12;
|
||||
case 'hh' :
|
||||
return leftZeroFill(currentHours % 12 || 12, 2);
|
||||
// MINUTE
|
||||
case 'm' :
|
||||
return currentMinutes;
|
||||
case 'mm' :
|
||||
return leftZeroFill(currentMinutes, 2);
|
||||
// SECOND
|
||||
case 's' :
|
||||
return currentSeconds;
|
||||
case 'ss' :
|
||||
return leftZeroFill(currentSeconds, 2);
|
||||
// MILLISECONDS
|
||||
case 'S' :
|
||||
return ~~ (currentMilliseconds / 100);
|
||||
case 'SS' :
|
||||
return leftZeroFill(~~(currentMilliseconds / 10), 2);
|
||||
case 'SSS' :
|
||||
return leftZeroFill(currentMilliseconds, 3);
|
||||
// TIMEZONE
|
||||
case 'Z' :
|
||||
return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(Math.abs(currentZone) / 60), 2) + ':' + leftZeroFill(~~(Math.abs(currentZone) % 60), 2);
|
||||
case 'ZZ' :
|
||||
return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(10 * Math.abs(currentZone) / 6), 4);
|
||||
// LONG DATES
|
||||
case 'L' :
|
||||
case 'LL' :
|
||||
case 'LLL' :
|
||||
case 'LLLL' :
|
||||
case 'LT' :
|
||||
return formatMoment(m, moment.longDateFormat[input]);
|
||||
// DEFAULT
|
||||
default :
|
||||
return input.replace(/(^\[)|(\\)|\]$/g, "");
|
||||
}
|
||||
}
|
||||
return inputString.replace(formattingTokens, replaceFunction);
|
||||
}
|
||||
|
||||
// get the regex to find the next token
|
||||
function getParseRegexForToken(token) {
|
||||
switch (token) {
|
||||
case 'DDDD':
|
||||
return parseTokenThreeDigits;
|
||||
case 'YYYY':
|
||||
return parseTokenFourDigits;
|
||||
case 'S':
|
||||
case 'SS':
|
||||
case 'SSS':
|
||||
case 'DDD':
|
||||
return parseTokenOneToThreeDigits;
|
||||
case 'MMM':
|
||||
case 'MMMM':
|
||||
case 'ddd':
|
||||
case 'dddd':
|
||||
case 'a':
|
||||
case 'A':
|
||||
return parseTokenWord;
|
||||
case 'Z':
|
||||
case 'ZZ':
|
||||
return parseTokenTimezone;
|
||||
case 'T':
|
||||
return parseTokenT;
|
||||
case 'MM':
|
||||
case 'DD':
|
||||
case 'dd':
|
||||
case 'YY':
|
||||
case 'HH':
|
||||
case 'hh':
|
||||
case 'mm':
|
||||
case 'ss':
|
||||
case 'M':
|
||||
case 'D':
|
||||
case 'd':
|
||||
case 'H':
|
||||
case 'h':
|
||||
case 'm':
|
||||
case 's':
|
||||
return parseTokenOneOrTwoDigits;
|
||||
default :
|
||||
return new RegExp(token.replace('\\', ''));
|
||||
}
|
||||
}
|
||||
|
||||
// function to convert string input to date
|
||||
function addTimeToArrayFromToken(token, input, datePartArray, config) {
|
||||
var a;
|
||||
//console.log('addTime', format, input);
|
||||
switch (token) {
|
||||
// MONTH
|
||||
case 'M' : // fall through to MM
|
||||
case 'MM' :
|
||||
datePartArray[1] = (input == null) ? 0 : ~~input - 1;
|
||||
break;
|
||||
case 'MMM' : // fall through to MMMM
|
||||
case 'MMMM' :
|
||||
for (a = 0; a < 12; a++) {
|
||||
if (moment.monthsParse[a].test(input)) {
|
||||
datePartArray[1] = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// DAY OF MONTH
|
||||
case 'D' : // fall through to DDDD
|
||||
case 'DD' : // fall through to DDDD
|
||||
case 'DDD' : // fall through to DDDD
|
||||
case 'DDDD' :
|
||||
datePartArray[2] = ~~input;
|
||||
break;
|
||||
// YEAR
|
||||
case 'YY' :
|
||||
input = ~~input;
|
||||
datePartArray[0] = input + (input > 70 ? 1900 : 2000);
|
||||
break;
|
||||
case 'YYYY' :
|
||||
datePartArray[0] = ~~Math.abs(input);
|
||||
break;
|
||||
// AM / PM
|
||||
case 'a' : // fall through to A
|
||||
case 'A' :
|
||||
config.isPm = ((input + '').toLowerCase() === 'pm');
|
||||
break;
|
||||
// 24 HOUR
|
||||
case 'H' : // fall through to hh
|
||||
case 'HH' : // fall through to hh
|
||||
case 'h' : // fall through to hh
|
||||
case 'hh' :
|
||||
datePartArray[3] = ~~input;
|
||||
break;
|
||||
// MINUTE
|
||||
case 'm' : // fall through to mm
|
||||
case 'mm' :
|
||||
datePartArray[4] = ~~input;
|
||||
break;
|
||||
// SECOND
|
||||
case 's' : // fall through to ss
|
||||
case 'ss' :
|
||||
datePartArray[5] = ~~input;
|
||||
break;
|
||||
// MILLISECOND
|
||||
case 'S' :
|
||||
case 'SS' :
|
||||
case 'SSS' :
|
||||
datePartArray[6] = ~~ (('0.' + input) * 1000);
|
||||
break;
|
||||
// TIMEZONE
|
||||
case 'Z' : // fall through to ZZ
|
||||
case 'ZZ' :
|
||||
config.isUTC = true;
|
||||
a = (input + '').match(parseTimezoneChunker);
|
||||
if (a && a[1]) {
|
||||
config.tzh = ~~a[1];
|
||||
}
|
||||
if (a && a[2]) {
|
||||
config.tzm = ~~a[2];
|
||||
}
|
||||
// reverse offsets
|
||||
if (a && a[0] === '+') {
|
||||
config.tzh = -config.tzh;
|
||||
config.tzm = -config.tzm;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// date from string and format string
|
||||
function makeDateFromStringAndFormat(string, format) {
|
||||
var datePartArray = [0, 0, 1, 0, 0, 0, 0],
|
||||
config = {
|
||||
tzh : 0, // timezone hour offset
|
||||
tzm : 0 // timezone minute offset
|
||||
},
|
||||
tokens = format.match(formattingTokens),
|
||||
i, parsedInput;
|
||||
|
||||
for (i = 0; i < tokens.length; i++) {
|
||||
parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
|
||||
string = string.replace(getParseRegexForToken(tokens[i]), '');
|
||||
addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config);
|
||||
}
|
||||
// handle am pm
|
||||
if (config.isPm && datePartArray[3] < 12) {
|
||||
datePartArray[3] += 12;
|
||||
}
|
||||
// if is 12 am, change hours to 0
|
||||
if (config.isPm === false && datePartArray[3] === 12) {
|
||||
datePartArray[3] = 0;
|
||||
}
|
||||
// handle timezone
|
||||
datePartArray[3] += config.tzh;
|
||||
datePartArray[4] += config.tzm;
|
||||
// return
|
||||
return config.isUTC ? new Date(Date.UTC.apply({}, datePartArray)) : dateFromArray(datePartArray);
|
||||
}
|
||||
|
||||
// compare two arrays, return the number of differences
|
||||
function compareArrays(array1, array2) {
|
||||
var len = Math.min(array1.length, array2.length),
|
||||
lengthDiff = Math.abs(array1.length - array2.length),
|
||||
diffs = 0,
|
||||
i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (~~array1[i] !== ~~array2[i]) {
|
||||
diffs++;
|
||||
}
|
||||
}
|
||||
return diffs + lengthDiff;
|
||||
}
|
||||
|
||||
// date from string and array of format strings
|
||||
function makeDateFromStringAndArray(string, formats) {
|
||||
var output,
|
||||
inputParts = string.match(parseMultipleFormatChunker) || [],
|
||||
formattedInputParts,
|
||||
scoreToBeat = 99,
|
||||
i,
|
||||
currentDate,
|
||||
currentScore;
|
||||
for (i = 0; i < formats.length; i++) {
|
||||
currentDate = makeDateFromStringAndFormat(string, formats[i]);
|
||||
formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || [];
|
||||
currentScore = compareArrays(inputParts, formattedInputParts);
|
||||
if (currentScore < scoreToBeat) {
|
||||
scoreToBeat = currentScore;
|
||||
output = currentDate;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// date from iso format
|
||||
function makeDateFromString(string) {
|
||||
var format = 'YYYY-MM-DDT',
|
||||
i;
|
||||
if (isoRegex.exec(string)) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (isoTimes[i][1].exec(string)) {
|
||||
format += isoTimes[i][0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return parseTokenTimezone.exec(string) ?
|
||||
makeDateFromStringAndFormat(string, format + ' Z') :
|
||||
makeDateFromStringAndFormat(string, format);
|
||||
}
|
||||
return new Date(string);
|
||||
}
|
||||
|
||||
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
|
||||
function substituteTimeAgo(string, number, withoutSuffix, isFuture) {
|
||||
var rt = moment.relativeTime[string];
|
||||
return (typeof rt === 'function') ?
|
||||
rt(number || 1, !!withoutSuffix, string, isFuture) :
|
||||
rt.replace(/%d/i, number || 1);
|
||||
}
|
||||
|
||||
function relativeTime(milliseconds, withoutSuffix) {
|
||||
var seconds = round(Math.abs(milliseconds) / 1000),
|
||||
minutes = round(seconds / 60),
|
||||
hours = round(minutes / 60),
|
||||
days = round(hours / 24),
|
||||
years = round(days / 365),
|
||||
args = seconds < 45 && ['s', seconds] ||
|
||||
minutes === 1 && ['m'] ||
|
||||
minutes < 45 && ['mm', minutes] ||
|
||||
hours === 1 && ['h'] ||
|
||||
hours < 22 && ['hh', hours] ||
|
||||
days === 1 && ['d'] ||
|
||||
days <= 25 && ['dd', days] ||
|
||||
days <= 45 && ['M'] ||
|
||||
days < 345 && ['MM', round(days / 30)] ||
|
||||
years === 1 && ['y'] || ['yy', years];
|
||||
args[2] = withoutSuffix;
|
||||
args[3] = milliseconds > 0;
|
||||
return substituteTimeAgo.apply({}, args);
|
||||
}
|
||||
|
||||
moment = function (input, format) {
|
||||
if (input === null || input === '') {
|
||||
return null;
|
||||
}
|
||||
var date,
|
||||
matched,
|
||||
isUTC;
|
||||
// parse Moment object
|
||||
if (moment.isMoment(input)) {
|
||||
date = new Date(+input._d);
|
||||
isUTC = input._isUTC;
|
||||
// parse string and format
|
||||
} else if (format) {
|
||||
if (isArray(format)) {
|
||||
date = makeDateFromStringAndArray(input, format);
|
||||
} else {
|
||||
date = makeDateFromStringAndFormat(input, format);
|
||||
}
|
||||
// evaluate it as a JSON-encoded date
|
||||
} else {
|
||||
matched = aspNetJsonRegex.exec(input);
|
||||
date = input === undefined ? new Date() :
|
||||
matched ? new Date(+matched[1]) :
|
||||
input instanceof Date ? input :
|
||||
isArray(input) ? dateFromArray(input) :
|
||||
typeof input === 'string' ? makeDateFromString(input) :
|
||||
new Date(input);
|
||||
}
|
||||
return new Moment(date, isUTC);
|
||||
};
|
||||
|
||||
// creating with utc
|
||||
moment.utc = function (input, format) {
|
||||
if (isArray(input)) {
|
||||
return new Moment(new Date(Date.UTC.apply({}, input)), true);
|
||||
}
|
||||
return (format && input) ?
|
||||
moment(input + ' +0000', format + ' Z').utc() :
|
||||
moment(input && !parseTokenTimezone.exec(input) ? input + '+0000' : input).utc();
|
||||
};
|
||||
|
||||
// creating with unix timestamp (in seconds)
|
||||
moment.unix = function (input) {
|
||||
return moment(input * 1000);
|
||||
};
|
||||
|
||||
// duration
|
||||
moment.duration = function (input, key) {
|
||||
var isDuration = moment.isDuration(input),
|
||||
isNumber = (typeof input === 'number'),
|
||||
duration = (isDuration ? input._data : (isNumber ? {} : input));
|
||||
|
||||
if (isNumber) {
|
||||
if (key) {
|
||||
duration[key] = input;
|
||||
} else {
|
||||
duration.milliseconds = input;
|
||||
}
|
||||
}
|
||||
|
||||
return new Duration(duration);
|
||||
};
|
||||
|
||||
// humanizeDuration
|
||||
// This method is deprecated in favor of the new Duration object. Please
|
||||
// see the moment.duration method.
|
||||
moment.humanizeDuration = function (num, type, withSuffix) {
|
||||
return moment.duration(num, type === true ? null : type).humanize(type === true ? true : withSuffix);
|
||||
};
|
||||
|
||||
// version number
|
||||
moment.version = VERSION;
|
||||
|
||||
// default format
|
||||
moment.defaultFormat = isoFormat;
|
||||
|
||||
// language switching and caching
|
||||
moment.lang = function (key, values) {
|
||||
var i, req,
|
||||
parse = [];
|
||||
if (!key) {
|
||||
return currentLanguage;
|
||||
}
|
||||
if (values) {
|
||||
for (i = 0; i < 12; i++) {
|
||||
parse[i] = new RegExp('^' + values.months[i] + '|^' + values.monthsShort[i].replace('.', ''), 'i');
|
||||
}
|
||||
values.monthsParse = values.monthsParse || parse;
|
||||
languages[key] = values;
|
||||
}
|
||||
if (languages[key]) {
|
||||
for (i = 0; i < langConfigProperties.length; i++) {
|
||||
moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]] ||
|
||||
languages.en[langConfigProperties[i]];
|
||||
}
|
||||
currentLanguage = key;
|
||||
} else {
|
||||
if (hasModule) {
|
||||
req = require('./lang/' + key);
|
||||
moment.lang(key, req);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// set default language
|
||||
moment.lang('en', {
|
||||
months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
|
||||
monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
|
||||
weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
|
||||
weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
|
||||
longDateFormat : {
|
||||
LT : "h:mm A",
|
||||
L : "MM/DD/YYYY",
|
||||
LL : "MMMM D YYYY",
|
||||
LLL : "MMMM D YYYY LT",
|
||||
LLLL : "dddd, MMMM D YYYY LT"
|
||||
},
|
||||
meridiem : false,
|
||||
calendar : {
|
||||
sameDay : '[Today at] LT',
|
||||
nextDay : '[Tomorrow at] LT',
|
||||
nextWeek : 'dddd [at] LT',
|
||||
lastDay : '[Yesterday at] LT',
|
||||
lastWeek : '[last] dddd [at] LT',
|
||||
sameElse : 'L'
|
||||
},
|
||||
relativeTime : {
|
||||
future : "in %s",
|
||||
past : "%s ago",
|
||||
s : "a few seconds",
|
||||
m : "a minute",
|
||||
mm : "%d minutes",
|
||||
h : "an hour",
|
||||
hh : "%d hours",
|
||||
d : "a day",
|
||||
dd : "%d days",
|
||||
M : "a month",
|
||||
MM : "%d months",
|
||||
y : "a year",
|
||||
yy : "%d years"
|
||||
},
|
||||
ordinal : function (number) {
|
||||
var b = number % 10;
|
||||
return (~~ (number % 100 / 10) === 1) ? 'th' :
|
||||
(b === 1) ? 'st' :
|
||||
(b === 2) ? 'nd' :
|
||||
(b === 3) ? 'rd' : 'th';
|
||||
}
|
||||
});
|
||||
|
||||
// compare moment object
|
||||
moment.isMoment = function (obj) {
|
||||
return obj instanceof Moment;
|
||||
};
|
||||
|
||||
// for typechecking Duration objects
|
||||
moment.isDuration = function (obj) {
|
||||
return obj instanceof Duration;
|
||||
};
|
||||
|
||||
// shortcut for prototype
|
||||
moment.fn = Moment.prototype = {
|
||||
|
||||
clone : function () {
|
||||
return moment(this);
|
||||
},
|
||||
|
||||
valueOf : function () {
|
||||
return +this._d;
|
||||
},
|
||||
|
||||
unix : function () {
|
||||
return Math.floor(+this._d / 1000);
|
||||
},
|
||||
|
||||
toString : function () {
|
||||
return this._d.toString();
|
||||
},
|
||||
|
||||
toDate : function () {
|
||||
return this._d;
|
||||
},
|
||||
|
||||
utc : function () {
|
||||
this._isUTC = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
local : function () {
|
||||
this._isUTC = false;
|
||||
return this;
|
||||
},
|
||||
|
||||
format : function (inputString) {
|
||||
return formatMoment(this, inputString ? inputString : moment.defaultFormat);
|
||||
},
|
||||
|
||||
add : function (input, val) {
|
||||
var dur = val ? moment.duration(+val, input) : moment.duration(input);
|
||||
addOrSubtractDurationFromMoment(this, dur, 1);
|
||||
return this;
|
||||
},
|
||||
|
||||
subtract : function (input, val) {
|
||||
var dur = val ? moment.duration(+val, input) : moment.duration(input);
|
||||
addOrSubtractDurationFromMoment(this, dur, -1);
|
||||
return this;
|
||||
},
|
||||
|
||||
diff : function (input, val, asFloat) {
|
||||
var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(),
|
||||
zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
|
||||
diff = this._d - inputMoment._d - zoneDiff,
|
||||
year = this.year() - inputMoment.year(),
|
||||
month = this.month() - inputMoment.month(),
|
||||
date = this.date() - inputMoment.date(),
|
||||
output;
|
||||
if (val === 'months') {
|
||||
output = year * 12 + month + date / 30;
|
||||
} else if (val === 'years') {
|
||||
output = year + (month + date / 30) / 12;
|
||||
} else {
|
||||
output = val === 'seconds' ? diff / 1e3 : // 1000
|
||||
val === 'minutes' ? diff / 6e4 : // 1000 * 60
|
||||
val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
|
||||
val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
|
||||
val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
|
||||
diff;
|
||||
}
|
||||
return asFloat ? output : round(output);
|
||||
},
|
||||
|
||||
from : function (time, withoutSuffix) {
|
||||
return moment.duration(this.diff(time)).humanize(!withoutSuffix);
|
||||
},
|
||||
|
||||
fromNow : function (withoutSuffix) {
|
||||
return this.from(moment(), withoutSuffix);
|
||||
},
|
||||
|
||||
calendar : function () {
|
||||
var diff = this.diff(moment().sod(), 'days', true),
|
||||
calendar = moment.calendar,
|
||||
allElse = calendar.sameElse,
|
||||
format = diff < -6 ? allElse :
|
||||
diff < -1 ? calendar.lastWeek :
|
||||
diff < 0 ? calendar.lastDay :
|
||||
diff < 1 ? calendar.sameDay :
|
||||
diff < 2 ? calendar.nextDay :
|
||||
diff < 7 ? calendar.nextWeek : allElse;
|
||||
return this.format(typeof format === 'function' ? format.apply(this) : format);
|
||||
},
|
||||
|
||||
isLeapYear : function () {
|
||||
var year = this.year();
|
||||
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
||||
},
|
||||
|
||||
isDST : function () {
|
||||
return (this.zone() < moment([this.year()]).zone() ||
|
||||
this.zone() < moment([this.year(), 5]).zone());
|
||||
},
|
||||
|
||||
day : function (input) {
|
||||
var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
|
||||
return input == null ? day :
|
||||
this.add({ d : input - day });
|
||||
},
|
||||
|
||||
sod: function () {
|
||||
return moment(this)
|
||||
.hours(0)
|
||||
.minutes(0)
|
||||
.seconds(0)
|
||||
.milliseconds(0);
|
||||
},
|
||||
|
||||
eod: function () {
|
||||
// end of day = start of day plus 1 day, minus 1 millisecond
|
||||
return this.sod().add({
|
||||
d : 1,
|
||||
ms : -1
|
||||
});
|
||||
},
|
||||
|
||||
zone : function () {
|
||||
return this._isUTC ? 0 : this._d.getTimezoneOffset();
|
||||
},
|
||||
|
||||
daysInMonth : function () {
|
||||
return moment(this).month(this.month() + 1).date(0).date();
|
||||
}
|
||||
};
|
||||
|
||||
// helper for adding shortcuts
|
||||
function makeGetterAndSetter(name, key) {
|
||||
moment.fn[name] = function (input) {
|
||||
var utc = this._isUTC ? 'UTC' : '';
|
||||
if (input != null) {
|
||||
this._d['set' + utc + key](input);
|
||||
return this;
|
||||
} else {
|
||||
return this._d['get' + utc + key]();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
|
||||
for (i = 0; i < proxyGettersAndSetters.length; i ++) {
|
||||
makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase(), proxyGettersAndSetters[i]);
|
||||
}
|
||||
|
||||
// add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
|
||||
makeGetterAndSetter('year', 'FullYear');
|
||||
|
||||
moment.duration.fn = Duration.prototype = {
|
||||
weeks : function () {
|
||||
return absRound(this.days() / 7);
|
||||
},
|
||||
|
||||
valueOf : function () {
|
||||
return this._milliseconds +
|
||||
this._days * 864e5 +
|
||||
this._months * 2592e6;
|
||||
},
|
||||
|
||||
humanize : function (withSuffix) {
|
||||
var difference = +this,
|
||||
rel = moment.relativeTime,
|
||||
output = relativeTime(difference, !withSuffix);
|
||||
|
||||
if (withSuffix) {
|
||||
output = (difference <= 0 ? rel.past : rel.future).replace(/%s/i, output);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
function makeDurationGetter(name) {
|
||||
moment.duration.fn[name] = function () {
|
||||
return this._data[name];
|
||||
};
|
||||
}
|
||||
|
||||
function makeDurationAsGetter(name, factor) {
|
||||
moment.duration.fn['as' + name] = function () {
|
||||
return +this / factor;
|
||||
};
|
||||
}
|
||||
|
||||
for (i in unitMillisecondFactors) {
|
||||
if (unitMillisecondFactors.hasOwnProperty(i)) {
|
||||
makeDurationAsGetter(i, unitMillisecondFactors[i]);
|
||||
makeDurationGetter(i.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
makeDurationAsGetter('Weeks', 6048e5);
|
||||
|
||||
// CommonJS module is defined
|
||||
if (hasModule) {
|
||||
module.exports = moment;
|
||||
}
|
||||
/*global ender:false */
|
||||
if (typeof window !== 'undefined' && typeof ender === 'undefined') {
|
||||
window.moment = moment;
|
||||
}
|
||||
/*global define:false */
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define("moment", [], function () {
|
||||
return moment;
|
||||
});
|
||||
}
|
||||
})(Date);
|
||||
1400
vendor/moment/2.0.0/moment.js
vendored
Normal file
1400
vendor/moment/2.0.0/moment.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
180
vendor/timeline/20120520/css/timeline.css
vendored
180
vendor/timeline/20120520/css/timeline.css
vendored
@ -1,180 +0,0 @@
|
||||
.vmm-timeline{}.vmm-timeline div *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
|
||||
.vmm-timeline h1,.vmm-timeline h2,.vmm-timeline h3,.vmm-timeline h4,.vmm-timeline h5,.vmm-timeline h6,.vmm-timeline p,.vmm-timeline blockquote,.vmm-timeline pre,.vmm-timeline a,.vmm-timeline abbr,.vmm-timeline acronym,.vmm-timeline address,.vmm-timeline cite,.vmm-timeline code,.vmm-timeline del,.vmm-timeline dfn,.vmm-timeline em,.vmm-timeline img,.vmm-timeline q,.vmm-timeline s,.vmm-timeline samp,.vmm-timeline small,.vmm-timeline strike,.vmm-timeline strong,.vmm-timeline sub,.vmm-timeline sup,.vmm-timeline tt,.vmm-timeline var,.vmm-timeline dd,.vmm-timeline dl,.vmm-timeline dt,.vmm-timeline li,.vmm-timeline ol,.vmm-timeline ul,.vmm-timeline fieldset,.vmm-timeline form,.vmm-timeline label,.vmm-timeline legend,.vmm-timeline button,.vmm-timeline table,.vmm-timeline caption,.vmm-timeline tbody,.vmm-timeline tfoot,.vmm-timeline thead,.vmm-timeline tr,.vmm-timeline th,.vmm-timeline td,.vmm-timeline .container,.vmm-timeline .content-container,.vmm-timeline .media,.vmm-timeline .text,.vmm-timeline .slider,.vmm-timeline .date,.vmm-timeline .title,.vmm-timeline .messege,.vmm-timeline .map,.vmm-timeline .credit,.vmm-timeline .caption,.vmm-timeline .feedback,.vmm-timeline .feature,.vmm-timeline .toolbar,.vmm-timeline .marker,.vmm-timeline .dot,.vmm-timeline .line,.vmm-timeline .flag,.vmm-timeline .time,.vmm-timeline .era,.vmm-timeline .major,.vmm-timeline .minor,.vmm-timeline .navigation,.vmm-timeline .start,.vmm-timeline .active{margin:0;padding:0;border:0;font-weight:normal;font-style:normal;font-size:100%;line-height:1;font-family:inherit;}
|
||||
.vmm-timeline table{border-collapse:collapse;border-spacing:0;}
|
||||
.vmm-timeline ol,.vmm-timeline ul{list-style:none;}
|
||||
.vmm-timeline q:before,.vmm-timeline q:after,.vmm-timeline blockquote:before,.vmm-timeline blockquote:after{content:"";}
|
||||
.vmm-timeline a:focus{outline:thin dotted;}
|
||||
.vmm-timeline a:hover,.vmm-timeline a:active{outline:0;}
|
||||
.vmm-timeline article,.vmm-timeline aside,.vmm-timeline details,.vmm-timeline figcaption,.vmm-timeline figure,.vmm-timeline footer,.vmm-timeline header,.vmm-timeline hgroup,.vmm-timeline nav,.vmm-timeline section{display:block;}
|
||||
.vmm-timeline audio,.vmm-timeline canvas,.vmm-timeline video{display:inline-block;*display:inline;*zoom:1;}
|
||||
.vmm-timeline audio:not([controls]){display:none;}
|
||||
.vmm-timeline div{max-width:none;}
|
||||
.vmm-timeline sub,.vmm-timeline sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}
|
||||
.vmm-timeline sup{top:-0.5em;}
|
||||
.vmm-timeline sub{bottom:-0.25em;}
|
||||
.vmm-timeline img{border:0;-ms-interpolation-mode:bicubic;}
|
||||
.vmm-timeline button,.vmm-timeline input,.vmm-timeline select,.vmm-timeline textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;}
|
||||
.vmm-timeline button,.vmm-timeline input{line-height:normal;*overflow:visible;}
|
||||
.vmm-timeline button::-moz-focus-inner,.vmm-timeline input::-moz-focus-inner{border:0;padding:0;}
|
||||
.vmm-timeline button,.vmm-timeline input[type="button"],.vmm-timeline input[type="reset"],.vmm-timeline input[type="submit"]{cursor:pointer;-webkit-appearance:button;}
|
||||
.vmm-timeline input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
|
||||
.vmm-timeline input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}
|
||||
.vmm-timeline textarea{overflow:auto;vertical-align:top;}
|
||||
.vmm-timeline{font-family:"Georgia",Times New Roman,Times,serif;}.vmm-timeline .twitter,.vmm-timeline .messege,.vmm-timeline .credit,.vmm-timeline .caption,.vmm-timeline .zoom-in,.vmm-timeline .zoom-out,.vmm-timeline .back-home,.vmm-timeline .time-interval div,.vmm-timeline .time-interval-major div,.vmm-timeline .nav-container{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;}
|
||||
.vmm-timeline h1.date,.vmm-timeline h2.date,.vmm-timeline h3.date,.vmm-timeline h4.date,.vmm-timeline h5.date,.vmm-timeline h6.date{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;}
|
||||
.vmm-timeline .timenav h1,.vmm-timeline .flag-content h1,.vmm-timeline .era h1,.vmm-timeline .timenav h2,.vmm-timeline .flag-content h2,.vmm-timeline .era h2,.vmm-timeline .timenav h3,.vmm-timeline .flag-content h3,.vmm-timeline .era h3,.vmm-timeline .timenav h4,.vmm-timeline .flag-content h4,.vmm-timeline .era h4,.vmm-timeline .timenav h5,.vmm-timeline .flag-content h5,.vmm-timeline .era h5,.vmm-timeline .timenav h6,.vmm-timeline .flag-content h6,.vmm-timeline .era h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;}
|
||||
.vmm-timeline p,.vmm-timeline blockquote,.vmm-timeline blockquote p,.vmm-timeline .twitter blockquote p{font-family:"Georgia",Times New Roman,Times,serif !important;}
|
||||
.vmm-timeline .feature h1,.vmm-timeline .feature h2,.vmm-timeline .feature h3,.vmm-timeline .feature h4,.vmm-timeline .feature h5,.vmm-timeline .feature h6{font-family:"Georgia",Times New Roman,Times,serif;}
|
||||
.tooltip{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;}
|
||||
#timeline-embed{background-color:#ffffff;margin-bottom:20px;border:1px solid #cccccc;padding-top:20px;padding-bottom:20px;clear:both;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;-webkit-box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);-moz-box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);}
|
||||
#timeline-embed.full-embed{overflow:hidden;border:0 !important;padding:0 !important;margin:0 !important;clear:both;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;-webkit-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;-moz-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;box-shadow:0px 0px 0px rgba(0, 0, 0, 0.25) !important;}
|
||||
#timeline-embed.sized-embed{overflow:hidden;border:1px solid #cccccc;padding-top:7px;padding-bottom:7px;margin:0 !important;clear:both;-webkit-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;-moz-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;box-shadow:0px 0px 0px rgba(0, 0, 0, 0.25) !important;}
|
||||
.vmm-timeline{width:100%;height:100%;padding:0px;margin:0px;background-color:#ffffff;position:absolute;z-index:100;clear:both;overflow:hidden;}.vmm-timeline .feature{width:100%;}.vmm-timeline .feature .slider{width:100%;float:left;position:relative;z-index:10;padding-top:15px;-webkit-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);}
|
||||
.vmm-timeline .feedback{position:absolute;display:table;overflow:hidden;top:0px;left:0px;z-index:205;width:100%;height:100%;background-color:#ffffff;}.vmm-timeline .feedback .messege{display:table-cell;vertical-align:middle;font-size:15px;font-weight:normal;line-height:20px;width:75%;margin-left:auto;margin-right:auto;margin-top:auto;margin-bottom:auto;text-align:center;}
|
||||
.vmm-timeline .container.main{position:absolute;top:0px: left:0px;padding-bottom:3px;width:auto;height:auto;margin:0px;clear:both;}
|
||||
.vmm-timeline img,.vmm-timeline embed,.vmm-timeline object,.vmm-timeline video,.vmm-timeline iframe{max-width:100%;}
|
||||
.vmm-timeline img{max-height:100%;border:1px solid #999999;}
|
||||
.vmm-timeline a{color:#0088cc;text-decoration:none;}
|
||||
.vmm-timeline a:hover{color:#005580;text-decoration:underline;}
|
||||
.vmm-timeline .thumbnail{width:24px;height:24px;overflow:hidden;float:left;margin-right:1px;margin-top:6px;}
|
||||
.vmm-timeline .thumbnail.thumb-plaintext{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-280px -48px;}
|
||||
.vmm-timeline .thumbnail.thumb-quote{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-232px -48px;}
|
||||
.vmm-timeline .thumbnail.thumb-document{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-256px -48px;}
|
||||
.vmm-timeline .thumbnail.thumb-photo{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-280px -24px;border:0;}.vmm-timeline .thumbnail.thumb-photo img{border:0px none #cccccc !important;}
|
||||
.vmm-timeline .thumbnail.thumb-twitter{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-256px -24px;}
|
||||
.vmm-timeline .thumbnail.thumb-vimeo{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-328px -48px;}
|
||||
.vmm-timeline .thumbnail.thumb-youtube{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-328px -72px;}
|
||||
.vmm-timeline .thumbnail.thumb-video{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-328px -24px;}
|
||||
.vmm-timeline .thumbnail.thumb-audio{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-304px -24px;}
|
||||
.vmm-timeline .thumbnail.thumb-map{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-208px -48px;}
|
||||
.vmm-timeline .thumbnail.thumb-website{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-232px -24px;}
|
||||
.vmm-timeline .thumbnail.thumb-wikipedia{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-184px -48px;}
|
||||
.vmm-timeline .zFront{z-index:204;}
|
||||
.slider{width:100%;height:100%;overflow:hidden;}.slider .slider-container-mask{text-align:center;width:100%;height:100%;overflow:hidden;}.slider .slider-container-mask .slider-container{position:absolute;top:0px;left:-2160px;width:100%;height:100%;text-align:center;display:block;background-color:#ffffff;}.slider .slider-container-mask .slider-container .slider-item-container{display:table-cell;vertical-align:middle;}
|
||||
.slider img,.slider embed,.slider object,.slider video,.slider iframe{max-width:100%;}
|
||||
.slider .nav-previous,.slider .nav-next{position:absolute;top:0px;width:100px;color:#DBDBDB;font-size:11px;}.slider .nav-previous .nav-container,.slider .nav-next .nav-container{height:100px;width:100px;position:absolute;}
|
||||
.slider .nav-previous .icon,.slider .nav-next .icon{margin-top:12px;margin-bottom:15px;}
|
||||
.slider .nav-previous .date,.slider .nav-next .date,.slider .nav-previous .title,.slider .nav-next .title{line-height:14px;}.slider .nav-previous .date a,.slider .nav-next .date a,.slider .nav-previous .title a,.slider .nav-next .title a{color:#999999;}
|
||||
.slider .nav-previous .date small,.slider .nav-next .date small,.slider .nav-previous .title small,.slider .nav-next .title small{display:none;}
|
||||
.slider .nav-previous .date,.slider .nav-next .date{font-size:13px;line-height:13px;font-weight:bold;text-transform:uppercase;margin-bottom:5px;}
|
||||
.slider .nav-previous .title,.slider .nav-next .title{font-size:11px;line-height:13px;}
|
||||
.slider .nav-previous:hover,.slider .nav-next:hover{color:#333333;cursor:pointer;}
|
||||
.slider .nav-previous{float:left;text-align:left;}.slider .nav-previous .icon{margin-left:15px;height:24px;background-image:url(timeline.png);background-repeat:no-repeat;background-position:-160px 0;width:24px;height:24px;overflow:hidden;}
|
||||
.slider .nav-previous .date,.slider .nav-previous .title{text-align:left;padding-left:15px;}
|
||||
.slider .nav-previous:hover .icon{margin-left:10px;}
|
||||
.slider .nav-next{float:right;text-align:right;}.slider .nav-next .icon{margin-left:61px;background-image:url(timeline.png);background-repeat:no-repeat;background-position:-184px 0;width:24px;height:24px;height:24px;overflow:hidden;}
|
||||
.slider .nav-next .date,.slider .nav-next .title{text-align:right;padding-right:15px;}
|
||||
.slider .nav-next:hover .icon{margin-left:66px;}
|
||||
.slider .slider-item{position:absolute;width:700px;height:100%;padding:0px;margin:0px;display:table;overflow-y:auto;}.slider .slider-item .content{display:table-cell;vertical-align:middle;}.slider .slider-item .content .pad-top .text .container{padding-top:15px;}
|
||||
.slider .slider-item .content .pad-right .text .container{padding-right:15px;}
|
||||
.slider .slider-item .content .pad-left .text .container{padding-left:30px;}
|
||||
.slider .slider-item .content .pad-left .media.text-media .media-wrapper .media-container{border:none;background-color:#ffffff;}
|
||||
.slider .slider-item .content .content-container{display:table;vertical-align:middle;}.slider .slider-item .content .content-container .text{width:40%;max-width:50%;min-width:120px;display:table-cell;vertical-align:middle;}.slider .slider-item .content .content-container .text .container{display:table-cell;vertical-align:middle;text-align:left;}.slider .slider-item .content .content-container .text .container p{-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;}
|
||||
.slider .slider-item .content .content-container .media{width:100%;min-width:50%;float:left;}.slider .slider-item .content .content-container .media .media-wrapper{margin-left:auto;margin-right:auto;}.slider .slider-item .content .content-container .media .media-wrapper .media-container{display:inline-block;line-height:0px;padding:0px;max-height:100%;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .media-frame,.slider .slider-item .content .content-container .media .media-wrapper .media-container .media-image img{border:1px solid;border-color:#cccccc #999999 #999999 #cccccc;background:#ffffff;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .soundcloud{border:0;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .media-image{display:inline-block;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow{position:relative;z-index:1;background:#ffffff;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow:before,.slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow:after{z-index:-1;position:absolute;content:"";bottom:15px;left:10px;width:50%;top:80%;max-width:300px;background:#999999;-webkit-box-shadow:0 15px 10px #999999;-moz-box-shadow:0 15px 10px #999999;box-shadow:0 15px 10px #999999;-webkit-transform:rotate(-2deg);-moz-transform:rotate(-2deg);-o-transform:rotate(-2deg);-ms-transform:rotate(-2deg);transform:rotate(-2deg);}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow::after{-webkit-transform:rotate(2deg);-moz-transform:rotate(2deg);-o-transform:rotate(2deg);-ms-transform:rotate(2deg);transform:rotate(2deg);right:10px;left:auto;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container span.messege{display:block;vertical-align:middle;margin-left:auto;margin-right:auto;text-align:center;background:#ffffff;font-size:28px;font-weight:bold;text-transform:uppercase;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text{display:table;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text .container{display:table-cell;vertical-align:middle;font-size:15px;line-height:20px;color:#666666;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text .container p{margin-bottom:20px;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter{text-align:left;margin-left:auto;margin-right:auto;margin-bottom:15px;clear:both;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter blockquote{font-size:15px;line-height:20px;color:#666666;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter blockquote p{font-size:28px;line-height:36px;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#000000;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter blockquote .quote-mark{color:#666666;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .created-at{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-256px -24px;width:24px;height:24px;overflow:hidden;margin-left:15px;display:inline-block;float:right;filter:alpha(opacity=25);-khtml-opacity:0.25;-moz-opacity:0.25;opacity:0.25;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .created-at:hover{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard{float:right;margin-bottom:15px;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard a{color:#333333;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard a:hover{text-decoration:none;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard a:hover .fn{text-decoration:underline;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard .fn,.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard .nickname{padding-left:42px;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard .fn{display:block;font-weight:bold;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard .nickname{margin-top:3px;display:block;color:#666666;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard .avatar{float:left;display:block;width:32px;height:32px;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .twitter .vcard .avatar img{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia{font-size:15px;line-height:20px;text-align:left;margin-left:auto;margin-right:auto;margin-bottom:15px;clear:both;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia .wiki-source{margin-bottom:15px;font-size:13px;line-height:19px;font-style:italic;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4{border-bottom:1px solid #cccccc;margin-bottom:5px;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4 a{color:#000000;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4 a:hover{color:#0088cc;text-decoration:none;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia p{font-size:13px;line-height:19px;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .map{line-height:normal;z-index:200;text-align:left;background-color:#ffffff;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .map img{max-height:none !important;max-width:none !important;border:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .map .google-map{height:100%;width:100%;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution{position:absolute;z-index:201;bottom:0px;width:100%;overflow:hidden;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution .attribution-text{height:19px;overflow:hidden;-webkit-user-select:none;line-height:19px;margin-right:60px;padding-left:65px;font-family:Arial,sans-serif;font-size:10px;color:#444;white-space:nowrap;color:#ffffff;text-shadow:1px 1px 1px #333333;text-align:center;}.slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution .attribution-text a{color:#ffffff !important;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .credit{color:#999999;text-align:right;display:block;margin:0 auto;margin-top:6px;font-size:10px;line-height:13px;}
|
||||
.slider .slider-item .content .content-container .media .media-wrapper .caption{text-align:left;margin-top:10px;color:#666666;font-size:11px;line-height:14px;text-rendering:optimizeLegibility;}
|
||||
.slider .slider-item .content .media.text-media .media-wrapper .media-container{border:none;background-color:#ffffff;}
|
||||
.slider .slider-item .content-container.layout-text-media .text-media{border-top:1px solid #e3e3e3;padding-top:15px;padding-right:0;}
|
||||
.slider .slider-item .content-container.layout-text-media.pad-left .text-media{padding-right:15px;padding-top:0;border-right:1px solid #e3e3e3;border-top:0px solid #e3e3e3;}
|
||||
.slider .slider-item .content-container.layout-text{width:100%;}.slider .slider-item .content-container.layout-text .text{width:100%;max-width:100%;}.slider .slider-item .content-container.layout-text .text .container{display:block;vertical-align:middle;text-align:left;padding:0px;width:90%;text-align:left;margin-left:auto;margin-right:auto;}
|
||||
.slider .slider-item .content-container.layout-media{width:100%;}.slider .slider-item .content-container.layout-media .text{width:100%;height:100%;max-width:100%;display:block;text-align:center;}.slider .slider-item .content-container.layout-media .text .container{display:block;text-align:center;width:100%;margin-left:none;margin-right:none;}
|
||||
.slider .slider-item .content-container.layout-media .media{width:100%;min-width:50%;float:none;}.slider .slider-item .content-container.layout-media .media .media-wrapper{display:block;}.slider .slider-item .content-container.layout-media .media .media-wrapper .media-container{margin-left:auto;margin-right:auto;line-height:0px;padding:0px;}
|
||||
.slider .slider-item .content-container.layout-media .twitter,.slider .slider-item .content-container.layout-media .wikipedia{max-width:70%;}
|
||||
.vmm-timeline .navigation{clear:both;cursor:move;width:100%;height:200px;border-top:1px solid #e3e3e3;position:relative;}.vmm-timeline .navigation .toolbar{position:absolute;top:45px;left:0px;z-index:202;background-color:#ffffff;border:1px solid #cccccc;-webkit-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);}.vmm-timeline .navigation .toolbar .zoom-in,.vmm-timeline .navigation .toolbar .zoom-out,.vmm-timeline .navigation .toolbar .back-home{font-weight:normal;font-size:10px;line-height:20px;top:0px;z-index:202;width:18px;height:18px;color:#333333;text-align:center;font-weight:bold;border:1px solid #ffffff;padding:5px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vmm-timeline .navigation .toolbar .zoom-in:hover,.vmm-timeline .navigation .toolbar .zoom-out:hover,.vmm-timeline .navigation .toolbar .back-home:hover{color:#0088cc;cursor:pointer;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
|
||||
.vmm-timeline .navigation .toolbar .zoom-in .icon{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-256px 0;width:24px;height:24px;}
|
||||
.vmm-timeline .navigation .toolbar .zoom-out .icon{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-280px 0;width:24px;height:24px;}
|
||||
.vmm-timeline .navigation .toolbar .back-home .icon{background-image:url(timeline.png);background-repeat:no-repeat;background-position:-328px 0;width:24px;height:24px;}
|
||||
.vmm-timeline .navigation .timenav-background{position:absolute;cursor:move;top:0px;left:0px;height:150px;width:100%;background-color:#e9e9e9;}.vmm-timeline .navigation .timenav-background .timenav-interval-background{position:absolute;top:151px;left:0px;background:#ffffff;width:100%;height:49px;-webkit-box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);-moz-box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);}.vmm-timeline .navigation .timenav-background .timenav-interval-background .top-highlight{position:absolute;top:-1px;left:0px;z-index:30;width:100%;height:1px;background:#ffffff;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;-webkit-box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);}
|
||||
.vmm-timeline .navigation .timenav-background .timenav-line{position:absolute;top:0px;left:50%;width:3px;height:150px;background:#0088cc;z-index:201;-webkit-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);}
|
||||
.vmm-timeline .navigation .timenav-background .timenav-indicator{position:absolute;top:-1px;left:50%;z-index:202;background-image:url(timeline.png);background-repeat:no-repeat;background-position:-160px -48px;width:24px;height:24px;}
|
||||
.vmm-timeline .navigation .timenav-background .timenav-tag{height:50px;}.vmm-timeline .navigation .timenav-background .timenav-tag div{height:50px;display:table;}.vmm-timeline .navigation .timenav-background .timenav-tag div h3{display:table-cell;vertical-align:middle;padding-left:65px;font-size:15px;color:#9d9d9d;}
|
||||
.vmm-timeline .navigation .timenav-background .timenav-tag-row-2{background:#f1f1f1;}
|
||||
.vmm-timeline .navigation .timenav-background .timenav-tag-row-3{background:#e9e9e9;}
|
||||
.vmm-timeline .navigation .timenav{position:absolute;top:0px;left:-250px;z-index:1;}.vmm-timeline .navigation .timenav .content{position:relative;}.vmm-timeline .navigation .timenav .content .marker.start{display:none;}
|
||||
.vmm-timeline .navigation .timenav .content .marker.active .dot{background:#0088cc;z-index:200;}
|
||||
.vmm-timeline .navigation .timenav .content .marker.active .line{z-index:199;background:#0088cc;width:1px;}.vmm-timeline .navigation .timenav .content .marker.active .line .event-line{background:#0088cc;filter:alpha(opacity=75);-khtml-opacity:0.75;-moz-opacity:0.75;opacity:0.75;}
|
||||
.vmm-timeline .navigation .timenav .content .marker.active .flag{z-index:200;background-image:url(timeline.png);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;}.vmm-timeline .navigation .timenav .content .marker.active .flag .flag-content h3{color:#0088cc;}
|
||||
.vmm-timeline .navigation .timenav .content .marker.active .flag .flag-content .thumbnail{opacity:1;-moz-opacity:1;filter:alpha(opacity=100);}
|
||||
.vmm-timeline .navigation .timenav .content .marker.active .flag.row1,.vmm-timeline .navigation .timenav .content .marker.active .flag.row2,.vmm-timeline .navigation .timenav .content .marker.active .flag.row3{z-index:200;}
|
||||
.vmm-timeline .navigation .timenav .content .marker.active:hover{cursor:default;}.vmm-timeline .navigation .timenav .content .marker.active:hover .flag .flag-content h3{color:#0088cc;}
|
||||
.vmm-timeline .navigation .timenav .content .marker.active:hover .flag .flag-content h4{color:#999999;}
|
||||
.vmm-timeline .navigation .timenav .content .marker:hover .line{z-index:24;background:#999999;}
|
||||
.vmm-timeline .navigation .timenav .content .marker{position:absolute;top:0px;left:150px;display:block;}.vmm-timeline .navigation .timenav .content .marker .dot{position:absolute;top:150px;left:0px;display:block;width:6px;height:6px;background:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;z-index:21;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .line{position:absolute;top:0px;left:3px;width:1px;height:150px;background:#cccccc;-moz-box-shadow:1px 0 0 #ffffff;-webkit-box-shadow:1px 0 0 #ffffff;box-shadow:1px 0 0 #ffffff;z-index:22;}.vmm-timeline .navigation .timenav .content .marker .line .event-line{position:absolute;z-index:22;left:0px;height:1px;width:1px;background:#0088cc;filter:alpha(opacity=15);-khtml-opacity:0.15;-moz-opacity:0.15;opacity:0.15;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag{position:absolute;top:15px;left:3px;padding:0px;display:block;z-index:23;width:153px;height:56px;background-image:url(timeline.png);background-repeat:no-repeat;background-position:0 0;width:153px;height:53px;}.vmm-timeline .navigation .timenav .content .marker .flag .flag-content{padding:0px 7px 2px 6px;overflow:hidden;height:36px;}.vmm-timeline .navigation .timenav .content .marker .flag .flag-content h3{font-weight:bold;font-size:15px;line-height:20px;font-size:11px;line-height:11px;color:#999999;margin-top:5px;margin-bottom:2px;}.vmm-timeline .navigation .timenav .content .marker .flag .flag-content h3 small{display:none;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag .flag-content h4{display:none;font-weight:normal;font-size:15px;line-height:20px;margin-top:5px;font-size:10px;line-height:10px;color:#aaaaaa;}.vmm-timeline .navigation .timenav .content .marker .flag .flag-content h4 small{display:none;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag .flag-content .thumbnail{margin-bottom:15px;margin-right:3px;opacity:0.5;-moz-opacity:0.5;filter:alpha(opacity=50);}.vmm-timeline .navigation .timenav .content .marker .flag .flag-content .thumbnail img{width:22px;height:22px;max-height:none;max-width:none;border:0;border:1px solid #999999;padding:0;margin:0;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag:hover{cursor:pointer;background-image:url(timeline.png);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;}.vmm-timeline .navigation .timenav .content .marker .flag:hover .flag-content h3{color:#333333;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag:hover .flag-content h4{color:#aaaaaa;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag:hover .flag-content .thumbnail{opacity:1;-moz-opacity:1;filter:alpha(opacity=100);}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag.row1{z-index:25;top:48px;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag.row2{z-index:24;top:96px;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag.row3{z-index:23;top:1px;}
|
||||
.vmm-timeline .navigation .timenav .content .marker .flag.zFront{z-index:201;}
|
||||
.vmm-timeline .navigation .timenav .content .era{position:absolute;top:138px;left:150px;height:12px;display:block;background:#0088cc;overflow:hidden;border-left:1px solid #cccccc;border-right:1px solid #cccccc;border-top:1px solid #cccccc;filter:alpha(opacity=75);-khtml-opacity:0.75;-moz-opacity:0.75;opacity:0.75;-moz-border-radius-topleft:7px;-webkit-border-top-left-radius:7px;border-top-left-radius:7px;-moz-border-radius-topright:7px;-webkit-border-top-right-radius:7px;border-top-right-radius:7px;z-index:-10;}.vmm-timeline .navigation .timenav .content .era h3{font-weight:bold;font-size:10px;line-height:10px;color:#ffffff;position:absolute;top:-1px;left:9px;}
|
||||
.vmm-timeline .navigation .timenav .time{position:absolute;left:0px;top:150px;height:50px;background-color:#ffffff;}.vmm-timeline .navigation .timenav .time .time-interval-minor{max-width:none;height:6px;white-space:nowrap;position:absolute;top:-9px;left:8px;z-index:10;}.vmm-timeline .navigation .timenav .time .time-interval-minor .minor{position:relative;top:2px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);width:100px;height:6px;background-position:center top;white-space:nowrap;color:#666666;margin-top:0px;padding-top:0px;}
|
||||
.vmm-timeline .navigation .timenav .time .time-interval{white-space:nowrap;position:absolute;top:5px;left:0px;}.vmm-timeline .navigation .timenav .time .time-interval div{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);background-position:left top;background-repeat:no-repeat;padding-top:3px;position:absolute;height:3px;left:0px;display:block;font-weight:normal;font-size:10px;line-height:20px;text-transform:uppercase;text-align:left;text-indent:0px;white-space:nowrap;color:#666666;margin-left:0px;margin-right:0px;margin-top:1px;z-index:2;}.vmm-timeline .navigation .timenav .time .time-interval div strong{font-weight:bold;color:#000000;}
|
||||
.vmm-timeline .navigation .timenav .time .time-interval-major{white-space:nowrap;position:absolute;top:5px;left:0px;}.vmm-timeline .navigation .timenav .time .time-interval-major div{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);background-position:left top;background-repeat:no-repeat;padding-top:15px;position:absolute;height:15px;left:0px;display:block;font-weight:bold;font-size:12px;line-height:20px;text-transform:uppercase;text-align:left;text-indent:0px;white-space:nowrap;color:#333333;margin-left:0px;margin-right:0px;margin-top:1px;z-index:5;}.vmm-timeline .navigation .timenav .time .time-interval-major div strong{font-weight:bold;color:#000000;}
|
||||
.vmm-timeline{font-size:15px;font-weight:normal;line-height:20px;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;}.vmm-timeline p{font-size:15px;font-weight:normal;line-height:20px;margin-bottom:20px;color:#666666;}.vmm-timeline p small{font-size:12px;line-height:17px;}
|
||||
.vmm-timeline p:first-child{margin-top:20px;}
|
||||
.vmm-timeline .navigation p{color:#999999;}
|
||||
.vmm-timeline .feature h3,.vmm-timeline .feature h4,.vmm-timeline .feature h5,.vmm-timeline .feature h6{margin-bottom:15px;}
|
||||
.vmm-timeline .feature p{color:#666666;}
|
||||
.vmm-timeline .date a,.vmm-timeline .title a{color:#999999;}
|
||||
.vmm-timeline .hyphenate{-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;}
|
||||
.vmm-timeline h1,.vmm-timeline h2,.vmm-timeline h3,.vmm-timeline h4,.vmm-timeline h5,.vmm-timeline h6{font-weight:normal;color:#000000;text-transform:none;}.vmm-timeline h1 a,.vmm-timeline h2 a,.vmm-timeline h3 a,.vmm-timeline h4 a,.vmm-timeline h5 a,.vmm-timeline h6 a{color:#999999;}
|
||||
.vmm-timeline h1 small,.vmm-timeline h2 small,.vmm-timeline h3 small,.vmm-timeline h4 small,.vmm-timeline h5 small,.vmm-timeline h6 small{color:#999999;}
|
||||
.vmm-timeline h1.date,.vmm-timeline h2.date,.vmm-timeline h3.date,.vmm-timeline h4.date,.vmm-timeline h5.date,.vmm-timeline h6.date{font-weight:bold;}
|
||||
.vmm-timeline h2.start{font-size:36px;line-height:38px;margin-bottom:15px;}
|
||||
.vmm-timeline h1{margin-bottom:15px;font-size:32px;line-height:34px;}.vmm-timeline h1 small{font-size:18px;}
|
||||
.vmm-timeline h2{margin-bottom:15px;font-size:28px;line-height:30px;}.vmm-timeline h2 small{font-size:14px;line-height:16px;}
|
||||
.vmm-timeline h2.date{font-size:16px;line-height:18px;margin-bottom:3.75px;color:#999999;}
|
||||
.vmm-timeline h3,.vmm-timeline h4,.vmm-timeline h5,.vmm-timeline h6{line-height:40px;}.vmm-timeline h3 .active,.vmm-timeline h4 .active,.vmm-timeline h5 .active,.vmm-timeline h6 .active{color:#0088cc;}
|
||||
.vmm-timeline h3{font-size:28px;line-height:30px;}.vmm-timeline h3 small{font-size:14px;}
|
||||
.vmm-timeline h4{font-size:16px;line-height:18px;}.vmm-timeline h4 small{font-size:12px;}
|
||||
.vmm-timeline h5{font-size:14px;line-height:16px;}
|
||||
.vmm-timeline h6{font-size:13px;line-height:14px;text-transform:uppercase;}
|
||||
.vmm-timeline strong{font-weight:bold;}
|
||||
.vmm-timeline Q{quotes:'„' '“';font-style:italic;}
|
||||
.vmm-timeline blockquote{font-size:28px;text-align:left;line-height:36px;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#000000;}
|
||||
.vmm-timeline .credit{color:#999999;text-align:right;font-size:10px;line-height:10px;display:block;margin:0 auto;clear:both;}
|
||||
.vmm-timeline .caption{text-align:left;margin-top:5px;color:#666666;font-size:11px;line-height:14px;clear:both;}
|
||||
.tooltip{position:absolute;z-index:205;display:block;visibility:visible;padding:5px;opacity:0;filter:alpha(opacity=0);font-size:15px;font-weight:bold;line-height:20px;font-size:12px;line-height:12px;}
|
||||
.tooltip.in{opacity:0.8;filter:alpha(opacity=80);}
|
||||
.tooltip.top{margin-top:-2px;}
|
||||
.tooltip.right{margin-left:2px;}
|
||||
.tooltip.bottom{margin-top:2px;}
|
||||
.tooltip.left{margin-left:-2px;}
|
||||
.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
|
||||
.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
|
||||
.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
|
||||
.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
|
||||
.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
||||
.tooltip-arrow{position:absolute;width:0;height:0;}
|
||||
@media only screen and (max-width:480px),only screen and (max-device-width:480px){}@media (max-width:600px){.slider .slider-item .content .content-container{display:block;}.slider .slider-item .content .content-container .text{width:100%;max-width:100%;min-width:120px;display:block;}.slider .slider-item .content .content-container .text .container{display:block;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;} .slider .slider-item .content .content-container .media{width:100%;min-width:50%;float:none;}.slider .slider-item .content .content-container .media .media-wrapper{margin-left:0px;margin-right:0px;width:100%;display:block;} .slider .slider-item .content .content-container .media.text-media .media-wrapper .media-container{border:none;background-color:#ffffff;}}
|
||||
BIN
vendor/timeline/20120520/css/timeline.png
vendored
BIN
vendor/timeline/20120520/css/timeline.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 9.2 KiB |
7637
vendor/timeline/20120520/js/timeline.js
vendored
7637
vendor/timeline/20120520/js/timeline.js
vendored
File diff suppressed because it is too large
Load Diff
365
vendor/timeline/LICENSE
vendored
Normal file
365
vendor/timeline/LICENSE
vendored
Normal file
@ -0,0 +1,365 @@
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
|
||||
-------------------------------------------
|
||||
|
||||
Map tiles by [Stamen Design](http://stamen.com "Stamen Design"), under
|
||||
[CC BY 3.0](http://creativecommons.org/licenses/by/3.0 "CC BY 3.0").
|
||||
Data by [OpenStreetMap](http://openstreetmap.org "OpenStreetMap"),
|
||||
under [CC BY SA](http://creativecommons.org/licenses/by-sa/3.0 "CC BY SA").
|
||||
1
vendor/timeline/README
vendored
Normal file
1
vendor/timeline/README
vendored
Normal file
@ -0,0 +1 @@
|
||||
Verite TimelineJS v2.25
|
||||
BIN
vendor/timeline/css/loading.gif
vendored
Normal file
BIN
vendor/timeline/css/loading.gif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
284
vendor/timeline/css/timeline.css
vendored
Normal file
284
vendor/timeline/css/timeline.css
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
.vco-storyjs{}.vco-storyjs div *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
|
||||
.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6,.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs pre,.vco-storyjs a,.vco-storyjs abbr,.vco-storyjs acronym,.vco-storyjs address,.vco-storyjs cite,.vco-storyjs code,.vco-storyjs del,.vco-storyjs dfn,.vco-storyjs em,.vco-storyjs img,.vco-storyjs q,.vco-storyjs s,.vco-storyjs samp,.vco-storyjs small,.vco-storyjs strike,.vco-storyjs strong,.vco-storyjs sub,.vco-storyjs sup,.vco-storyjs tt,.vco-storyjs var,.vco-storyjs dd,.vco-storyjs dl,.vco-storyjs dt,.vco-storyjs li,.vco-storyjs ol,.vco-storyjs ul,.vco-storyjs fieldset,.vco-storyjs form,.vco-storyjs label,.vco-storyjs legend,.vco-storyjs button,.vco-storyjs table,.vco-storyjs caption,.vco-storyjs tbody,.vco-storyjs tfoot,.vco-storyjs thead,.vco-storyjs tr,.vco-storyjs th,.vco-storyjs td,.vco-storyjs .vco-container,.vco-storyjs .content-container,.vco-storyjs .media,.vco-storyjs .text,.vco-storyjs .vco-slider,.vco-storyjs .slider,.vco-storyjs .date,.vco-storyjs .title,.vco-storyjs .messege,.vco-storyjs .map,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .vco-feedback,.vco-storyjs .vco-feature,.vco-storyjs .toolbar,.vco-storyjs .marker,.vco-storyjs .dot,.vco-storyjs .line,.vco-storyjs .flag,.vco-storyjs .time,.vco-storyjs .era,.vco-storyjs .major,.vco-storyjs .minor,.vco-storyjs .vco-navigation,.vco-storyjs .start,.vco-storyjs .active{margin:0;padding:0;border:0;font-weight:normal;font-style:normal;font-size:100%;line-height:1;font-family:inherit;width:auto;float:none;}
|
||||
.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{clear:none;}
|
||||
.vco-storyjs table{border-collapse:collapse;border-spacing:0;}
|
||||
.vco-storyjs ol,.vco-storyjs ul{list-style:none;}
|
||||
.vco-storyjs q:before,.vco-storyjs q:after,.vco-storyjs blockquote:before,.vco-storyjs blockquote:after{content:"";}
|
||||
.vco-storyjs a:focus{outline:thin dotted;}
|
||||
.vco-storyjs a:hover,.vco-storyjs a:active{outline:0;}
|
||||
.vco-storyjs article,.vco-storyjs aside,.vco-storyjs details,.vco-storyjs figcaption,.vco-storyjs figure,.vco-storyjs footer,.vco-storyjs header,.vco-storyjs hgroup,.vco-storyjs nav,.vco-storyjs section{display:block;}
|
||||
.vco-storyjs audio,.vco-storyjs canvas,.vco-storyjs video{display:inline-block;*display:inline;*zoom:1;}
|
||||
.vco-storyjs audio:not([controls]){display:none;}
|
||||
.vco-storyjs div{max-width:none;}
|
||||
.vco-storyjs sub,.vco-storyjs sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}
|
||||
.vco-storyjs sup{top:-0.5em;}
|
||||
.vco-storyjs sub{bottom:-0.25em;}
|
||||
.vco-storyjs img{border:0;-ms-interpolation-mode:bicubic;}
|
||||
.vco-storyjs button,.vco-storyjs input,.vco-storyjs select,.vco-storyjs textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;}
|
||||
.vco-storyjs button,.vco-storyjs input{line-height:normal;*overflow:visible;}
|
||||
.vco-storyjs button::-moz-focus-inner,.vco-storyjs input::-moz-focus-inner{border:0;padding:0;}
|
||||
.vco-storyjs button,.vco-storyjs input[type="button"],.vco-storyjs input[type="reset"],.vco-storyjs input[type="submit"]{cursor:pointer;-webkit-appearance:button;}
|
||||
.vco-storyjs input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
|
||||
.vco-storyjs input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}
|
||||
.vco-storyjs textarea{overflow:auto;vertical-align:top;}
|
||||
.vco-storyjs{font-family:"Georgia",Times New Roman,Times,serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;}
|
||||
.vco-storyjs h1.date,.vco-storyjs h2.date,.vco-storyjs h3.date,.vco-storyjs h4.date,.vco-storyjs h5.date,.vco-storyjs h6.date{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;}
|
||||
.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;}
|
||||
.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:"Georgia",Times New Roman,Times,serif !important;}
|
||||
.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:"Georgia",Times New Roman,Times,serif;}
|
||||
.timeline-tooltip{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;}
|
||||
.thumbnail{background-image:url(timeline.png?v4.4);}
|
||||
@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.thumbnail{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;}}.vco-storyjs{font-size:15px;font-weight:normal;line-height:20px;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;}.vco-storyjs p{font-size:15px;font-weight:normal;line-height:20px;margin-bottom:20px;color:#666666;}.vco-storyjs p small{font-size:12px;line-height:17px;}
|
||||
.vco-storyjs p:first-child{margin-top:20px;}
|
||||
.vco-storyjs .vco-navigation p{color:#999999;}
|
||||
.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{margin-bottom:15px;}
|
||||
.vco-storyjs .vco-feature p{color:#666666;}
|
||||
.vco-storyjs .vco-feature blockquote,.vco-storyjs .vco-feature blockquote p{color:#000000;}
|
||||
.vco-storyjs .date a,.vco-storyjs .title a{color:#999999;}
|
||||
.vco-storyjs .hyphenate{-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;}
|
||||
.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{font-weight:normal;color:#000000;text-transform:none;}.vco-storyjs h1 a,.vco-storyjs h2 a,.vco-storyjs h3 a,.vco-storyjs h4 a,.vco-storyjs h5 a,.vco-storyjs h6 a{color:#999999;}
|
||||
.vco-storyjs h1 small,.vco-storyjs h2 small,.vco-storyjs h3 small,.vco-storyjs h4 small,.vco-storyjs h5 small,.vco-storyjs h6 small{color:#999999;}
|
||||
.vco-storyjs h1.date,.vco-storyjs h2.date,.vco-storyjs h3.date,.vco-storyjs h4.date,.vco-storyjs h5.date,.vco-storyjs h6.date{font-weight:bold;}
|
||||
.vco-storyjs h2.start{font-size:36px;line-height:38px;margin-bottom:15px;}
|
||||
.vco-storyjs h1{margin-bottom:15px;font-size:32px;line-height:34px;}.vco-storyjs h1 small{font-size:18px;}
|
||||
.vco-storyjs h2{margin-bottom:15px;font-size:28px;line-height:30px;}.vco-storyjs h2 small{font-size:14px;line-height:16px;}
|
||||
.vco-storyjs h2.date{font-size:16px;line-height:18px;margin-bottom:3.75px;color:#999999;}
|
||||
.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{line-height:40px;}.vco-storyjs h3 .active,.vco-storyjs h4 .active,.vco-storyjs h5 .active,.vco-storyjs h6 .active{color:#0088cc;}
|
||||
.vco-storyjs h3{font-size:28px;line-height:30px;}.vco-storyjs h3 small{font-size:14px;}
|
||||
.vco-storyjs h4{font-size:20px;line-height:22px;}.vco-storyjs h4 small{font-size:12px;}
|
||||
.vco-storyjs h5{font-size:16px;line-height:18px;}
|
||||
.vco-storyjs h6{font-size:13px;line-height:14px;text-transform:uppercase;}
|
||||
.vco-storyjs strong{font-weight:bold;font-style:inherit;}
|
||||
.vco-storyjs em{font-style:italic;font-weight:inherit;}
|
||||
.vco-storyjs Q{quotes:'„' '“';font-style:italic;}
|
||||
.vco-storyjs blockquote,.vco-storyjs blockquote p{font-size:24px;line-height:32px;text-align:left;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#000000;}
|
||||
.vco-storyjs .credit{color:#999999;text-align:right;font-size:10px;line-height:10px;display:block;margin:0 auto;clear:both;}
|
||||
.vco-storyjs .caption{text-align:left;margin-top:5px;color:#666666;font-size:11px;line-height:14px;clear:both;}
|
||||
.vco-storyjs.vco-right-to-left h1,.vco-storyjs.vco-right-to-left h2,.vco-storyjs.vco-right-to-left h3,.vco-storyjs.vco-right-to-left h4,.vco-storyjs.vco-right-to-left h5,.vco-storyjs.vco-right-to-left h6,.vco-storyjs.vco-right-to-left p,.vco-storyjs.vco-right-to-left blockquote,.vco-storyjs.vco-right-to-left pre,.vco-storyjs.vco-right-to-left a,.vco-storyjs.vco-right-to-left abbr,.vco-storyjs.vco-right-to-left acronym,.vco-storyjs.vco-right-to-left address,.vco-storyjs.vco-right-to-left cite,.vco-storyjs.vco-right-to-left code,.vco-storyjs.vco-right-to-left del,.vco-storyjs.vco-right-to-left dfn,.vco-storyjs.vco-right-to-left em,.vco-storyjs.vco-right-to-left img,.vco-storyjs.vco-right-to-left q,.vco-storyjs.vco-right-to-left s,.vco-storyjs.vco-right-to-left samp,.vco-storyjs.vco-right-to-left small,.vco-storyjs.vco-right-to-left strike,.vco-storyjs.vco-right-to-left strong,.vco-storyjs.vco-right-to-left sub,.vco-storyjs.vco-right-to-left sup,.vco-storyjs.vco-right-to-left tt,.vco-storyjs.vco-right-to-left var,.vco-storyjs.vco-right-to-left dd,.vco-storyjs.vco-right-to-left dl,.vco-storyjs.vco-right-to-left dt,.vco-storyjs.vco-right-to-left li,.vco-storyjs.vco-right-to-left ol,.vco-storyjs.vco-right-to-left ul,.vco-storyjs.vco-right-to-left fieldset,.vco-storyjs.vco-right-to-left form,.vco-storyjs.vco-right-to-left label,.vco-storyjs.vco-right-to-left legend,.vco-storyjs.vco-right-to-left button,.vco-storyjs.vco-right-to-left table,.vco-storyjs.vco-right-to-left caption,.vco-storyjs.vco-right-to-left tbody,.vco-storyjs.vco-right-to-left tfoot,.vco-storyjs.vco-right-to-left thead,.vco-storyjs.vco-right-to-left tr,.vco-storyjs.vco-right-to-left th,.vco-storyjs.vco-right-to-left td{direction:rtl;}
|
||||
.timeline-tooltip{position:absolute;z-index:205;display:block;visibility:visible;padding:5px;opacity:0;filter:alpha(opacity=0);font-size:15px;font-weight:bold;line-height:20px;font-size:12px;line-height:12px;}
|
||||
.timeline-tooltip.in{opacity:0.8;filter:alpha(opacity=80);}
|
||||
.timeline-tooltip.top{margin-top:-2px;}
|
||||
.timeline-tooltip.right{margin-left:2px;}
|
||||
.timeline-tooltip.bottom{margin-top:2px;}
|
||||
.timeline-tooltip.left{margin-left:-2px;}
|
||||
.timeline-tooltip.top .timeline-tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
|
||||
.timeline-tooltip.left .timeline-tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
|
||||
.timeline-tooltip.bottom .timeline-tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
|
||||
.timeline-tooltip.right .timeline-tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
|
||||
.timeline-tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
||||
.timeline-tooltip-arrow{position:absolute;width:0;height:0;}
|
||||
@media only screen and (max-width:480px),only screen and (max-device-width:480px){.vco-slider .nav-next,.vco-slider .nav-previous{display:none;}}@media (max-width:640px){}.vco-skinny .vco-slider .slider-item .content .layout-text-media .text .container{text-align:center !important;}
|
||||
.vco-skinny .vco-slider .slider-item .content .layout-text-media h2,.vco-skinny .vco-slider .slider-item .content .layout-text-media h3{display:block !important;width:100% !important;text-align:center !important;}
|
||||
.vco-skinny .vco-slider .slider-item .content .content-container{display:block;}.vco-skinny .vco-slider .slider-item .content .content-container .text{width:100%;max-width:100%;min-width:120px;display:block;}.vco-skinny .vco-slider .slider-item .content .content-container .text .container{display:block;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;}
|
||||
.vco-skinny .vco-slider .slider-item .content .content-container .media{width:100%;min-width:50%;float:none;}.vco-skinny .vco-slider .slider-item .content .content-container .media .media-wrapper{margin-left:0px;margin-right:0px;width:100%;display:block;}
|
||||
.vco-skinny.vco-notouch .vco-slider .nav-previous,.vco-skinny.vco-notouch .vco-slider .nav-next{z-index:203;}.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .title{filter:alpha(opacity=1);-khtml-opacity:0.01;-moz-opacity:0.01;opacity:0.01;}
|
||||
.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .icon{filter:alpha(opacity=15);-khtml-opacity:0.15;-moz-opacity:0.15;opacity:0.15;}
|
||||
.vco-skinny.vco-notouch .vco-slider .nav-previous .icon{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-208px 0;width:24px;height:24px;overflow:hidden;margin-left:10px;}
|
||||
.vco-skinny.vco-notouch .vco-slider .nav-next .icon{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-232px 0;width:24px;height:24px;overflow:hidden;margin-left:66px;}
|
||||
.vco-skinny.vco-notouch .vco-slider .nav-previous:hover,.vco-skinny.vco-notouch .vco-slider .nav-next:hover{color:#aaaaaa !important;background-color:#333333;background-color:rgba(0, 0, 0, 0.65);-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;}.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;font-weight:bold;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
|
||||
.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{padding-bottom:5px;}
|
||||
.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{padding-left:5px;padding-right:5px;}
|
||||
@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-skinny.vco-notouch .vco-slider .nav-previous .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-208px 0;width:24px;height:24px;overflow:hidden;} .vco-skinny.vco-notouch .vco-slider .nav-next .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-232px 0;width:24px;height:24px;overflow:hidden;}}.vco-slider{width:100%;height:100%;overflow:hidden;}.vco-slider .slider-container-mask{text-align:center;width:100%;height:100%;overflow:hidden;}.vco-slider .slider-container-mask .slider-container{position:absolute;top:0px;left:-2160px;width:100%;height:100%;text-align:center;display:block;}.vco-slider .slider-container-mask .slider-container .slider-item-container{display:table-cell;vertical-align:middle;}
|
||||
.vco-notouch .vco-slider .nav-previous:hover,.vco-notouch .vco-slider .nav-next:hover{color:#333333;cursor:pointer;}
|
||||
.vco-notouch .vco-slider .nav-previous:hover .icon{margin-left:10px;}
|
||||
.vco-notouch .vco-slider .nav-next:hover .icon{margin-left:66px;}
|
||||
.vco-notouch .vco-slider .slider-item .content .content-container .media .media-container .wikipedia h4 a:hover{color:#0088cc;text-decoration:none;}
|
||||
.vco-notouch .vco-slider .slider-item .content .content-container .created-at:hover{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
|
||||
.vco-notouch .vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments a:hover{text-decoration:none;}.vco-notouch .vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments a:hover h5{text-decoration:underline;}
|
||||
.vco-slider img,.vco-slider embed,.vco-slider object,.vco-slider video,.vco-slider iframe{max-width:100%;}
|
||||
.vco-slider .nav-previous,.vco-slider .nav-next{position:absolute;top:0px;width:100px;color:#DBDBDB;font-size:11px;}.vco-slider .nav-previous .nav-container,.vco-slider .nav-next .nav-container{height:100px;width:100px;position:absolute;}
|
||||
.vco-slider .nav-previous .icon,.vco-slider .nav-next .icon{margin-top:12px;margin-bottom:15px;}
|
||||
.vco-slider .nav-previous .date,.vco-slider .nav-next .date,.vco-slider .nav-previous .title,.vco-slider .nav-next .title{line-height:14px;}.vco-slider .nav-previous .date a,.vco-slider .nav-next .date a,.vco-slider .nav-previous .title a,.vco-slider .nav-next .title a{color:#999999;}
|
||||
.vco-slider .nav-previous .date small,.vco-slider .nav-next .date small,.vco-slider .nav-previous .title small,.vco-slider .nav-next .title small{display:none;}
|
||||
.vco-slider .nav-previous .date,.vco-slider .nav-next .date{font-size:13px;line-height:13px;font-weight:bold;text-transform:uppercase;margin-bottom:5px;}
|
||||
.vco-slider .nav-previous .title,.vco-slider .nav-next .title{font-size:11px;line-height:13px;}
|
||||
.vco-slider .nav-previous{float:left;text-align:left;}.vco-slider .nav-previous .icon{margin-left:15px;background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-160px 0;width:24px;height:24px;overflow:hidden;}
|
||||
.vco-slider .nav-previous .date,.vco-slider .nav-previous .title{text-align:left;padding-left:15px;}
|
||||
.vco-slider .nav-next{float:right;text-align:right;}.vco-slider .nav-next .icon{margin-left:61px;background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-184px 0;width:24px;height:24px;overflow:hidden;}
|
||||
.vco-slider .nav-next .date,.vco-slider .nav-next .title{text-align:right;padding-right:15px;}
|
||||
@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-slider .nav-previous .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-160px 0;width:24px;height:24px;overflow:hidden;} .vco-slider .nav-next .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-184px 0;width:24px;height:24px;overflow:hidden;}}.vco-slider .slider-item{position:absolute;width:700px;height:100%;padding:0px;margin:0px;display:table;overflow-y:auto;}.vco-slider .slider-item .content{display:table-cell;vertical-align:middle;}.vco-slider .slider-item .content .pad-top .text .container{padding-top:15px;}
|
||||
.vco-slider .slider-item .content .pad-right .text .container{padding-right:15px;}
|
||||
.vco-slider .slider-item .content .pad-left .text .container{padding-left:30px;}
|
||||
.vco-slider .slider-item .content .pad-left .media.text-media .media-wrapper .media-container{border:none;background-color:#ffffff;}
|
||||
.vco-slider .slider-item .content .content-container{display:table;vertical-align:middle;}.vco-slider .slider-item .content .content-container .text{width:40%;max-width:50%;min-width:120px;display:table-cell;vertical-align:middle;}.vco-slider .slider-item .content .content-container .text .container{display:table-cell;vertical-align:middle;text-align:left;}.vco-slider .slider-item .content .content-container .text .container p{-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;}
|
||||
.vco-slider .slider-item .content .content-container .text .container h2.date{font-size:15px;line-height:15px;font-weight:normal;}
|
||||
.vco-slider .slider-item .content .content-container .text .container .slide-tag{font-size:11px;font-weight:bold;color:#ffffff;background-color:#cccccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;vertical-align:baseline;white-space:nowrap;line-height:11px;padding:1px 3px 1px;margin-left:7.5px;margin-bottom:7.5px;}
|
||||
.vco-slider .slider-item .content .content-container .media{width:100%;min-width:50%;float:left;}.vco-slider .slider-item .content .content-container .media .media-wrapper{display:inline-block;margin-left:auto;margin-right:auto;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container{display:inline-block;line-height:0px;padding:0px;max-height:100%;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-frame,.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-image img{border:1px solid;border-color:#cccccc #999999 #999999 #cccccc;background-color:#ffffff;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-frame iframe{background-color:#ffffff;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .soundcloud{border:0;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-image{display:inline-block;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow{position:relative;z-index:1;background:#ffffff;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow:before,.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow:after{z-index:-1;position:absolute;content:"";bottom:15px;left:10px;width:50%;top:80%;max-width:300px;background:#999999;-webkit-box-shadow:0 15px 10px #999999;-moz-box-shadow:0 15px 10px #999999;box-shadow:0 15px 10px #999999;-webkit-transform:rotate(-2deg);-moz-transform:rotate(-2deg);-ms-transform:rotate(-2deg);-o-transform:rotate(-2deg);transform:rotate(-2deg);}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow::after{-webkit-transform:rotate(2deg);-moz-transform:rotate(2deg);-ms-transform:rotate(2deg);-o-transform:rotate(2deg);transform:rotate(2deg);right:10px;left:auto;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text{display:table;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text .container{display:table-cell;vertical-align:middle;font-size:15px;line-height:20px;color:#666666;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text .container p{margin-bottom:20px;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia{font-size:15px;line-height:20px;text-align:left;margin-left:auto;margin-right:auto;margin-bottom:15px;clear:both;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia .wiki-source{margin-bottom:15px;font-size:13px;line-height:19px;font-style:italic;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4{border-bottom:1px solid #cccccc;margin-bottom:5px;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4 a{color:#000000;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia p{font-size:13px;line-height:19px;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map{line-height:normal;z-index:200;text-align:left;background-color:#ffffff;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map img{max-height:none !important;max-width:none !important;border:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .google-map{height:100%;width:100%;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution{position:absolute;z-index:201;bottom:0px;width:100%;overflow:hidden;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution .attribution-text{height:19px;overflow:hidden;-webkit-user-select:none;line-height:19px;margin-right:60px;padding-left:65px;font-family:Arial,sans-serif;font-size:10px;color:#444;white-space:nowrap;color:#ffffff;text-shadow:1px 1px 1px #333333;text-align:center;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution .attribution-text a{color:#ffffff !important;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .credit{color:#999999;text-align:right;display:block;margin:0 auto;margin-top:6px;font-size:10px;line-height:13px;}
|
||||
.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .caption{text-align:left;margin-top:10px;color:#666666;font-size:11px;line-height:14px;text-rendering:optimizeLegibility;word-wrap:break-word;}
|
||||
.vco-slider .slider-item .content .content-container .media.text-media .media-wrapper .media-container{border:none;background-color:#ffffff;}
|
||||
.vco-slider .slider-item .content .content-container .created-at{width:24px;height:24px;overflow:hidden;margin-left:7.5px;margin-top:2px;display:inline-block;float:right;filter:alpha(opacity=25);-khtml-opacity:0.25;-moz-opacity:0.25;opacity:0.25;}
|
||||
.vco-slider .slider-item .content .content-container .storify .created-at{background-repeat:no-repeat;background-position:-328px -96px;}
|
||||
.vco-slider .slider-item .content .content-container .twitter .created-at{background-repeat:no-repeat;background-position:-256px -24px;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content{font-size:13px;line-height:19px;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#666666;}.vco-slider .slider-item .content .content-container .googleplus .googleplus-content p{font-size:13px;line-height:19px;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-title{font-size:24px;line-height:32px;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#000000;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-annotation{font-size:15px;line-height:20px;color:#000000;border-bottom:1px solid #e3e3e3;padding-bottom:7.5px;margin-bottom:7.5px;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments{border-top:1px solid #e3e3e3;padding-top:15px;margin-top:15px;border-bottom:1px solid #e3e3e3;padding-bottom:15px;margin-bottom:15px;*zoom:1;}.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:before,.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:after{display:table;content:"";}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:after{clear:both;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments h5{margin-bottom:5px;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments div{width:50%;padding-left:15px;display:inline-block;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments p{font-size:11px;line-height:14px;margin-bottom:5px;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments img{float:left;display:block;bottom:0;left:0;margin:auto;position:relative;right:0;top:0;width:40%;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .proflinkPrefix{color:#0088cc;}
|
||||
.vco-slider .slider-item .content .content-container .googleplus .created-at{background-repeat:no-repeat;background-position:-208px -72px;}
|
||||
.vco-slider .slider-item .content .content-container .twitter,.vco-slider .slider-item .content .content-container .plain-text-quote,.vco-slider .slider-item .content .content-container .storify,.vco-slider .slider-item .content .content-container .googleplus{text-align:left;margin-left:auto;margin-right:auto;margin-bottom:15px;clear:both;}.vco-slider .slider-item .content .content-container .twitter blockquote,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote,.vco-slider .slider-item .content .content-container .storify blockquote,.vco-slider .slider-item .content .content-container .googleplus blockquote{color:#666666;}.vco-slider .slider-item .content .content-container .twitter blockquote p,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote p,.vco-slider .slider-item .content .content-container .storify blockquote p,.vco-slider .slider-item .content .content-container .googleplus blockquote p{font-size:24px;line-height:32px;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#000000;}
|
||||
.vco-slider .slider-item .content .content-container .twitter blockquote .quote-mark,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote .quote-mark,.vco-slider .slider-item .content .content-container .storify blockquote .quote-mark,.vco-slider .slider-item .content .content-container .googleplus blockquote .quote-mark{color:#666666;}
|
||||
.vco-slider .slider-item .content .content-container .twitter blockquote{font-size:15px;}.vco-slider .slider-item .content .content-container .twitter blockquote p{font-size:24px;}
|
||||
.vco-slider .slider-item .content .content-container.layout-text-media .text-media{border-top:1px solid #e3e3e3;padding-top:15px;padding-right:0;}
|
||||
.vco-slider .slider-item .content .content-container.layout-text-media.pad-left .text-media{padding-right:15px;padding-top:0;border-right:1px solid #e3e3e3;border-top:0px solid #e3e3e3;}
|
||||
.vco-slider .slider-item .content .content-container.layout-text{width:100%;}.vco-slider .slider-item .content .content-container.layout-text .text{width:100%;max-width:100%;}.vco-slider .slider-item .content .content-container.layout-text .text .container{display:block;vertical-align:middle;padding:0px;width:90%;text-align:left;margin-left:auto;margin-right:auto;}
|
||||
.vco-slider .slider-item .content .content-container.layout-media{width:100%;}.vco-slider .slider-item .content .content-container.layout-media .text{width:100%;height:100%;max-width:100%;display:block;text-align:center;}.vco-slider .slider-item .content .content-container.layout-media .text .container{display:block;text-align:center;width:100%;margin-left:none;margin-right:none;}
|
||||
.vco-slider .slider-item .content .content-container.layout-media .media{width:100%;min-width:50%;float:none;}.vco-slider .slider-item .content .content-container.layout-media .media .media-wrapper .media-container{margin-left:auto;margin-right:auto;line-height:0px;padding:0px;}
|
||||
.vco-slider .slider-item .content .content-container.layout-media .twitter,.vco-slider .slider-item .content .content-container.layout-media .wikipedia,.vco-slider .slider-item .content .content-container.layout-media .googleplus{max-width:70%;}
|
||||
.storyjs-embed{background-color:#ffffff;margin-bottom:20px;border:1px solid #cccccc;padding-top:20px;padding-bottom:20px;clear:both;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;-webkit-box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);-moz-box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);}
|
||||
.storyjs-embed.full-embed{overflow:hidden;border:0 !important;padding:0 !important;margin:0 !important;clear:both;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;-webkit-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;-moz-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;}
|
||||
.storyjs-embed.sized-embed{overflow:hidden;border:1px solid #cccccc;padding-top:7px;padding-bottom:7px;margin:0 !important;clear:both;-webkit-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;-moz-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;}
|
||||
.vco-storyjs{width:100%;height:100%;padding:0px;margin:0px;background-color:#ffffff;position:absolute;z-index:100;clear:both;overflow:hidden;}.vco-storyjs .vmm-clear:before,.vco-storyjs .vmm-clear:after{content:"";display:table;}
|
||||
.vco-storyjs .vmm-clear:after{clear:both;}
|
||||
.vco-storyjs .vmm-clear{*zoom:1;}
|
||||
.vco-storyjs .vco-feature{width:100%;}.vco-storyjs .vco-feature .slider,.vco-storyjs .vco-feature .vco-slider{width:100%;float:left;position:relative;z-index:10;padding-top:15px;-webkit-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);}
|
||||
.vco-storyjs .vco-feedback{position:absolute;display:table;overflow:hidden;top:0px;left:0px;z-index:205;width:100%;height:100%;}
|
||||
.vco-storyjs div.vco-loading,.vco-storyjs div.vco-explainer{display:table;text-align:center;min-width:100px;margin-top:15px;height:100%;width:100%;background-color:#ffffff;}.vco-storyjs div.vco-loading .vco-loading-container,.vco-storyjs div.vco-explainer .vco-loading-container,.vco-storyjs div.vco-loading .vco-explainer-container,.vco-storyjs div.vco-explainer .vco-explainer-container{display:table-cell;vertical-align:middle;}.vco-storyjs div.vco-loading .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-loading-icon{display:block;background-repeat:no-repeat;vertical-align:middle;margin-left:auto;margin-right:auto;text-align:center;background-image:url(loading.gif?v3.4);width:28px;height:28px;}
|
||||
.vco-storyjs div.vco-loading .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-gesture-icon{display:block;vertical-align:middle;margin-left:auto;margin-right:auto;text-align:center;background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-160px -160px;width:48px;height:48px;}
|
||||
.vco-storyjs div.vco-loading .vco-loading-container .vco-message,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message{display:block;}
|
||||
.vco-storyjs div.vco-loading .vco-loading-container .vco-message,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message,.vco-storyjs div.vco-loading .vco-loading-container .vco-message p,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message p,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message p,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message p{text-align:center;font-size:11px;line-height:13px;text-transform:uppercase;margin-top:7.5px;margin-bottom:7.5px;}
|
||||
.vco-storyjs div.vco-explainer{background-color:transparent;}
|
||||
.vco-storyjs .vco-bezel{background-color:#333333;background-color:rgba(0, 0, 0, 0.8);width:80px;height:50px;padding:50px;padding-top:25px;padding:25px 20px 50px 20px;margin:auto;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;}.vco-storyjs .vco-bezel .vco-message,.vco-storyjs .vco-bezel .vco-message p{color:#ffffff;font-weight:bold;}
|
||||
.vco-storyjs .vco-container.vco-main{position:absolute;top:0px;left:0px;padding-bottom:3px;width:auto;height:auto;margin:0px;clear:both;}
|
||||
.vco-storyjs img,.vco-storyjs embed,.vco-storyjs object,.vco-storyjs video,.vco-storyjs iframe{max-width:100%;}
|
||||
.vco-storyjs img{max-height:100%;border:1px solid #999999;}
|
||||
.vco-storyjs a{color:#0088cc;text-decoration:none;}
|
||||
.vco-storyjs a:hover{color:#005580;text-decoration:underline;}
|
||||
.vco-storyjs .vcard{float:right;margin-bottom:15px;}.vco-storyjs .vcard a{color:#333333;}
|
||||
.vco-storyjs .vcard a:hover{text-decoration:none;}.vco-storyjs .vcard a:hover .fn{text-decoration:underline;}
|
||||
.vco-storyjs .vcard .fn,.vco-storyjs .vcard .nickname{padding-left:42px;}
|
||||
.vco-storyjs .vcard .fn{display:block;font-weight:bold;}
|
||||
.vco-storyjs .vcard .nickname{margin-top:1px;display:block;color:#666666;}
|
||||
.vco-storyjs .vcard .avatar{float:left;display:block;width:32px;height:32px;}.vco-storyjs .vcard .avatar img{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;}
|
||||
.vco-storyjs .thumbnail{width:24px;height:24px;overflow:hidden;float:left;margin:0;margin-right:1px;margin-top:6px;border:0;padding:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
||||
.vco-storyjs a.thumbnail:hover{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
||||
.vco-storyjs .thumbnail.thumb-plaintext{background-repeat:no-repeat;background-position:-280px -48px;}
|
||||
.vco-storyjs .thumbnail.thumb-quote{background-repeat:no-repeat;background-position:-232px -48px;}
|
||||
.vco-storyjs .thumbnail.thumb-document{background-repeat:no-repeat;background-position:-256px -48px;}
|
||||
.vco-storyjs .thumbnail.thumb-photo{background-repeat:no-repeat;background-position:-280px -24px;border:0;}.vco-storyjs .thumbnail.thumb-photo img{border:0px none #cccccc !important;}
|
||||
.vco-storyjs .thumbnail.thumb-twitter{background-repeat:no-repeat;background-position:-256px -24px;}
|
||||
.vco-storyjs .thumbnail.thumb-vimeo{background-repeat:no-repeat;background-position:-328px -48px;}
|
||||
.vco-storyjs .thumbnail.thumb-vine{background-repeat:no-repeat;background-position:-232px -72px;}
|
||||
.vco-storyjs .thumbnail.thumb-youtube{background-repeat:no-repeat;background-position:-328px -72px;}
|
||||
.vco-storyjs .thumbnail.thumb-video{background-repeat:no-repeat;background-position:-328px -24px;}
|
||||
.vco-storyjs .thumbnail.thumb-audio{background-repeat:no-repeat;background-position:-304px -24px;}
|
||||
.vco-storyjs .thumbnail.thumb-map{background-repeat:no-repeat;background-position:-208px -48px;}
|
||||
.vco-storyjs .thumbnail.thumb-website{background-repeat:no-repeat;background-position:-232px -24px;}
|
||||
.vco-storyjs .thumbnail.thumb-link{background-repeat:no-repeat;background-position:-184px -72px;}
|
||||
.vco-storyjs .thumbnail.thumb-wikipedia{background-repeat:no-repeat;background-position:-184px -48px;}
|
||||
.vco-storyjs .thumbnail.thumb-storify{background-repeat:no-repeat;background-position:-328px -96px;}
|
||||
.vco-storyjs .thumbnail.thumb-googleplus{background-repeat:no-repeat;background-position:-208px -72px;}
|
||||
.vco-storyjs thumbnail.thumb-instagram{background-repeat:no-repeat;background-position:-208px -96px;}
|
||||
.vco-storyjs thumbnail.thumb-instagram-full{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-232px -96px;width:48px;height:24px;}
|
||||
.vco-storyjs .thumb-storify-full{height:12px;background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-280px -96px;width:48px;}
|
||||
.vco-storyjs .thumbnail-inline{width:16px;height:14px;overflow:hidden;display:inline-block;margin-right:1px;margin-left:3px;margin-top:2px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vco-storyjs .twitter .thumbnail-inline{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-160px -96px;}
|
||||
.vco-storyjs .storify .thumbnail-inline{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-184px -96px;}
|
||||
.vco-storyjs .googleplus .thumbnail-inline{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-208px -96px;}
|
||||
.vco-storyjs .zFront{z-index:204;}
|
||||
@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-storyjs div.vco-loading .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-loading-icon{background-image:url(loading@2x.gif?v3.4);} .vco-storyjs div.vco-loading .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-gesture-icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-160px -160px;width:48px;height:48px;}}.vco-notouch .vco-navigation .vco-toolbar .zoom-in:hover,.vco-notouch .vco-navigation .vco-toolbar .zoom-out:hover,.vco-notouch .vco-navigation .vco-toolbar .back-home:hover{color:#0088cc;cursor:pointer;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker.active:hover{cursor:default;}.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag .flag-content h3,.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag-small .flag-content h3{color:#0088cc;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag .flag-content h4,.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag-small .flag-content h4{color:#999999;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker:hover .line{z-index:24;background:#999999;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker .flag:hover,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{cursor:pointer;}.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content h3,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h3{color:#333333;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content h4,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h4{color:#aaaaaa;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content .thumbnail,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content .thumbnail{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker .flag:hover{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{height:56px;background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content{height:36px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h3{margin-top:5px;}
|
||||
.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover .flag-content{height:14px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover .flag-content h3{margin-top:4px;}
|
||||
.vco-timeline .vco-navigation{clear:both;cursor:move;width:100%;height:200px;border-top:1px solid #e3e3e3;position:relative;}.vco-timeline .vco-navigation .vco-toolbar{position:absolute;top:45px;left:0px;z-index:202;background-color:#ffffff;border:1px solid #cccccc;-webkit-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);}.vco-timeline .vco-navigation .vco-toolbar .zoom-in,.vco-timeline .vco-navigation .vco-toolbar .zoom-out,.vco-timeline .vco-navigation .vco-toolbar .back-home{font-weight:normal;font-size:10px;line-height:20px;top:0px;z-index:202;width:18px;height:18px;color:#333333;text-align:center;font-weight:bold;border:1px solid #ffffff;padding:5px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vco-timeline .vco-navigation .vco-toolbar .zoom-in .icon{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-256px 0;width:24px;height:24px;}
|
||||
.vco-timeline .vco-navigation .vco-toolbar .zoom-out .icon{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-280px 0;width:24px;height:24px;}
|
||||
.vco-timeline .vco-navigation .vco-toolbar .back-home .icon{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-328px 0;width:24px;height:24px;}
|
||||
.vco-timeline .vco-navigation .vco-toolbar.touch{-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;background-color:transparent;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-in,.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-out,.vco-timeline .vco-navigation .vco-toolbar.touch .back-home{width:40px;height:40px;padding:5px;background-color:#ffffff;border:1px solid #cccccc;-webkit-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
|
||||
.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-in .icon{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-208px -160px;width:40px;height:40px;}
|
||||
.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-out .icon{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-256px -160px;width:40px;height:40px;}
|
||||
.vco-timeline .vco-navigation .vco-toolbar.touch .back-home .icon{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-304px -160px;width:40px;height:40px;}
|
||||
.vco-timeline .vco-navigation .timenav-background{position:absolute;cursor:move;top:0px;left:0px;height:150px;width:100%;background-color:#e9e9e9;}.vco-timeline .vco-navigation .timenav-background .timenav-interval-background{position:absolute;top:151px;left:0px;background:#ffffff;width:100%;height:49px;-webkit-box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);-moz-box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);}.vco-timeline .vco-navigation .timenav-background .timenav-interval-background .top-highlight{position:absolute;top:-1px;left:0px;z-index:30;width:100%;height:1px;background:#ffffff;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;-webkit-box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);}
|
||||
.vco-timeline .vco-navigation .timenav-background .timenav-line{position:absolute;top:0px;left:50%;width:3px;height:150px;background-color:#0088cc;z-index:1;-webkit-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);}
|
||||
.vco-timeline .vco-navigation .timenav-background .timenav-indicator{position:absolute;top:-1px;left:50%;z-index:202;background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-160px -48px;width:24px;height:24px;}
|
||||
.vco-timeline .vco-navigation .timenav-background .timenav-tag div{height:50px;display:table;}.vco-timeline .vco-navigation .timenav-background .timenav-tag div h3{display:table-cell;vertical-align:middle;padding-left:65px;font-size:15px;color:#d0d0d0;font-weight:bold;text-shadow:0px 1px 1px #ffffff;}
|
||||
.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-half{height:25px;}.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-half div{height:25px;}
|
||||
.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-full{height:50px;}.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-full div{height:50px;}
|
||||
.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-2,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-4,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-6{background:#f1f1f1;}
|
||||
.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-1,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-3,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-5{background:#e9e9e9;}
|
||||
.vco-timeline .vco-navigation .timenav{position:absolute;top:0px;left:-250px;z-index:1;}.vco-timeline .vco-navigation .timenav .content{position:relative;}.vco-timeline .vco-navigation .timenav .content .marker.start{display:none;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker.active .dot{background:#0088cc;z-index:200;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker.active .line{z-index:199;background:#0088cc;width:1px;}.vco-timeline .vco-navigation .timenav .content .marker.active .line .event-line{background:#0088cc;filter:alpha(opacity=75);-khtml-opacity:0.75;-moz-opacity:0.75;opacity:0.75;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker.active .flag,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small{z-index:200;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content{height:36px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3{color:#0088cc;margin-top:5px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content .thumbnail,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content .thumbnail{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row1,.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row2,.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row3,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row1,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row2,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row3{z-index:200;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker.active .flag{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content{height:14px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3{margin-top:4px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker{position:absolute;top:0px;left:150px;display:block;}.vco-timeline .vco-navigation .timenav .content .marker .dot{position:absolute;top:150px;left:0px;display:block;width:6px;height:6px;background:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;z-index:21;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .line{position:absolute;top:0px;left:3px;width:1px;height:150px;background-color:#cccccc;background-color:rgba(204, 204, 204, 0.5);-webkit-box-shadow:1px 0 0 rgba(255, 255, 255, 0.5);-moz-box-shadow:1px 0 0 rgba(255, 255, 255, 0.5);box-shadow:1px 0 0 rgba(255, 255, 255, 0.5);z-index:22;}.vco-timeline .vco-navigation .timenav .content .marker .line .event-line{position:absolute;z-index:22;left:0px;height:1px;width:1px;background:#0088cc;filter:alpha(opacity=15);-khtml-opacity:0.15;-moz-opacity:0.15;opacity:0.15;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag,.vco-timeline .vco-navigation .timenav .content .marker .flag-small{position:absolute;top:15px;left:3px;padding:0px;display:block;z-index:23;width:153px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content{padding:0px 7px 2px 6px;overflow:hidden;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3{font-weight:bold;font-size:15px;line-height:20px;font-size:11px;line-height:11px;color:#999999;margin-bottom:2px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3 small,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3 small{display:none;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h4,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h4{display:none;font-weight:normal;font-size:15px;line-height:20px;margin-top:5px;font-size:10px;line-height:10px;color:#aaaaaa;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h4 small,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h4 small{display:none;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content .thumbnail,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail{margin-bottom:15px;margin-right:3px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content .thumbnail img,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail img{width:22px;height:22px;max-height:none;max-width:none;border:0;border:1px solid #999999;padding:0;margin:0;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag{height:56px;background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:0 0;width:153px;height:53px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content{height:36px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3{margin-top:5px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:0 -135px;width:153px;height:26px;}.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content{height:14px;}.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3{margin-top:4px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail{width:16px;height:10px;margin-right:1px;margin-top:6px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-plaintext{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-280px -130px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-quote{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-232px -130px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-document{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-256px -130px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-photo{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-280px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-twitter{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-256px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-vimeo{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-328px -130px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-vine{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-160px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-youtube{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-304px -130px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-video{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-328px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-audio{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-304px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-map{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-208px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-website{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-232px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-link{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-232px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-wikipedia{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-184px -120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-storify{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-184px -130px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-googleplus{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-208px -130px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content thumbnail.thumb-instagram{background-image:url(timeline.png?v4.4);background-repeat:no-repeat;background-position:-208px -96px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag.row1{z-index:25;top:48px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag.row2{z-index:24;top:96px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag.row3{z-index:23;top:1px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row1{z-index:28;top:24px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row2{z-index:27;top:48px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row3{z-index:26;top:72px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row4{z-index:25;top:96px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row5{z-index:24;top:120px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row6{z-index:23;top:1px;}
|
||||
.vco-timeline .vco-navigation .timenav .content .marker .flag.zFront,.vco-timeline .vco-navigation .timenav .content .marker .flag-small.zFront{z-index:201;}
|
||||
.vco-timeline .vco-navigation .timenav .content .era{position:absolute;top:138px;left:150px;height:12px;display:block;overflow:hidden;}.vco-timeline .vco-navigation .timenav .content .era div{height:50px;width:100%;height:100%;line-height:0px;background:#e9e9e9;background:rgba(233, 233, 233, 0.33);}.vco-timeline .vco-navigation .timenav .content .era div h3,.vco-timeline .vco-navigation .timenav .content .era div h4{position:absolute;bottom:1px;padding-left:15px;font-size:15px;font-weight:bold;color:rgba(0, 136, 204, 0.35);text-shadow:0px 1px 1px #ffffff;}
|
||||
.vco-timeline .vco-navigation .timenav .content .era1 div{background:#cc4400;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(204, 68, 0, 0.1);border-right:1px solid rgba(255, 85, 0, 0.05);}.vco-timeline .vco-navigation .timenav .content .era1 div h3,.vco-timeline .vco-navigation .timenav .content .era1 div h4{color:rgba(204, 68, 0, 0.35);text-shadow:0px 1px 1px #ffffff;}
|
||||
.vco-timeline .vco-navigation .timenav .content .era2 div{background:#cc0022;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(204, 0, 34, 0.1);border-right:1px solid rgba(255, 0, 43, 0.05);}.vco-timeline .vco-navigation .timenav .content .era2 div h3,.vco-timeline .vco-navigation .timenav .content .era2 div h4{color:rgba(204, 0, 34, 0.35);text-shadow:0px 1px 1px #ffffff;}
|
||||
.vco-timeline .vco-navigation .timenav .content .era3 div{background:#0022cc;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(0, 34, 204, 0.1);border-right:1px solid rgba(0, 43, 255, 0.05);}.vco-timeline .vco-navigation .timenav .content .era3 div h3,.vco-timeline .vco-navigation .timenav .content .era3 div h4{color:rgba(0, 34, 204, 0.35);text-shadow:0px 1px 1px #ffffff;}
|
||||
.vco-timeline .vco-navigation .timenav .content .era4 div{background:#ccaa00;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(204, 170, 0, 0.1);border-right:1px solid rgba(255, 213, 0, 0.05);}.vco-timeline .vco-navigation .timenav .content .era4 div h3,.vco-timeline .vco-navigation .timenav .content .era4 div h4{color:rgba(204, 170, 0, 0.35);text-shadow:0px 1px 1px #ffffff;}
|
||||
.vco-timeline .vco-navigation .timenav .content .era5 div{background:#00ccaa;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(0, 204, 170, 0.1);border-right:1px solid rgba(0, 255, 213, 0.05);}.vco-timeline .vco-navigation .timenav .content .era5 div h3,.vco-timeline .vco-navigation .timenav .content .era5 div h4{color:rgba(0, 204, 170, 0.35);text-shadow:0px 1px 1px #ffffff;}
|
||||
.vco-timeline .vco-navigation .timenav .content .era6 div{background:#0088cc;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(0, 136, 204, 0.1);border-right:1px solid rgba(0, 170, 255, 0.05);}.vco-timeline .vco-navigation .timenav .content .era6 div h3,.vco-timeline .vco-navigation .timenav .content .era6 div h4{color:rgba(0, 136, 204, 0.35);text-shadow:0px 1px 1px #ffffff;}
|
||||
.vco-timeline .vco-navigation .timenav .time{position:absolute;left:0px;top:150px;height:50px;background-color:#ffffff;line-height:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval-minor{max-width:none;height:6px;white-space:nowrap;position:absolute;top:-2px;left:8px;z-index:10;}.vco-timeline .vco-navigation .timenav .time .time-interval-minor .minor{position:relative;top:2px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);width:100px;height:6px;background-position:center top;white-space:nowrap;color:#666666;margin-top:0px;padding-top:0px;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval{white-space:nowrap;position:absolute;top:5px;left:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval div{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);background-position:left top;background-repeat:no-repeat;padding-top:6px;position:absolute;height:3px;left:0px;display:block;font-weight:normal;font-size:10px;line-height:20px;text-transform:uppercase;text-align:left;text-indent:0px;white-space:nowrap;color:#666666;margin-left:0px;margin-right:0px;margin-top:0px;z-index:2;}.vco-timeline .vco-navigation .timenav .time .time-interval div strong{font-weight:bold;color:#000000;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval div.era{font-weight:bold;padding-top:0px;margin-top:-3px;margin-left:2px;background-image:none;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval .era1{color:#cc4400;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval .era2{color:#cc0022;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval .era3{color:#0022cc;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval .era4{color:#ccaa00;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval .era5{color:#00ccaa;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval .era6{color:#0088cc;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}
|
||||
.vco-timeline .vco-navigation .timenav .time .time-interval-major{white-space:nowrap;position:absolute;top:5px;left:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval-major div{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAQAQMAAADtUYf0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyOTAzRjI3REIzNDcxMUUxQUQ3QUZCOThEODQ1NDhCNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyOTAzRjI3RUIzNDcxMUUxQUQ3QUZCOThEODQ1NDhCNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjI5MDNGMjdCQjM0NzExRTFBRDdBRkI5OEQ4NDU0OEI3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjI5MDNGMjdDQjM0NzExRTFBRDdBRkI5OEQ4NDU0OEI3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+DPWNfQAAAANQTFRFzMzMylJEJwAAAAtJREFUCB1jYMAPAAAgAAHDvpOtAAAAAElFTkSuQmCC);background-position:left top;background-repeat:no-repeat;padding-top:15px;position:absolute;height:15px;left:0px;display:block;font-weight:bold;font-size:12px;line-height:20px;text-transform:uppercase;text-align:left;text-indent:0px;white-space:nowrap;color:#333333;margin-left:0px;margin-right:0px;margin-top:1px;z-index:5;}.vco-timeline .vco-navigation .timenav .time .time-interval-major div strong{font-weight:bold;color:#000000;}
|
||||
@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-notouch .vco-navigation .vco-toolbar .zoom-in .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-256px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar .zoom-out .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-280px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar .back-home .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-328px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar.touch .zoom-in .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-208px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .vco-toolbar.touch .zoom-out .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-256px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .vco-toolbar.touch .back-home .icon{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-304px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .timenav .content .marker .flag:hover{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} .vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} .vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;} .vco-notouch .vco-navigation .timenav-background .timenav-indicator{background-image:url(timeline@2x.png?v4.4);background-size:352px 260px;background-repeat:no-repeat;background-position:-160px -48px;width:24px;height:24px;}}@media screen and (-webkit-max-device-pixel-ratio:1){}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (-o-min-device-pixel-ratio:3/2),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-device-pixel-ratio:1.5){}@media screen and (max-device-width:480px) and (orientation:portrait){.storyjs-embed.full-embed{height:557px !important;width:320px !important;}.storyjs-embed.full-embed .vco-feature{height:356px !important;}}@media screen and (max-device-width:480px) and (orientation:landscape){.storyjs-embed.full-embed{height:409px !important;width:480px !important;}.storyjs-embed.full-embed .vco-feature{height:208px !important;}}@media screen and (min-device-width:481px) and (orientation:portrait){}@media screen and (min-device-width:481px) and (orientation:landscape){}@media (max-width:480px){}@media only screen and (max-width:480px){}
|
||||
BIN
vendor/timeline/css/timeline.png
vendored
Normal file
BIN
vendor/timeline/css/timeline.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
vendor/timeline/css/timeline@2x.png
vendored
Normal file
BIN
vendor/timeline/css/timeline@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
10015
vendor/timeline/js/timeline.js
vendored
Normal file
10015
vendor/timeline/js/timeline.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,14 @@
|
||||
// Underscore.js 1.4.2
|
||||
// http://underscorejs.org
|
||||
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Underscore may be freely distributed under the MIT license.
|
||||
// Underscore.js 1.4.4
|
||||
// ===================
|
||||
|
||||
// > http://underscorejs.org
|
||||
// > (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// > Underscore may be freely distributed under the MIT license.
|
||||
|
||||
// Baseline setup
|
||||
// --------------
|
||||
(function() {
|
||||
|
||||
// Baseline setup
|
||||
// --------------
|
||||
|
||||
// Establish the root object, `window` in the browser, or `global` on the server.
|
||||
var root = this;
|
||||
|
||||
@ -24,7 +25,6 @@
|
||||
var push = ArrayProto.push,
|
||||
slice = ArrayProto.slice,
|
||||
concat = ArrayProto.concat,
|
||||
unshift = ArrayProto.unshift,
|
||||
toString = ObjProto.toString,
|
||||
hasOwnProperty = ObjProto.hasOwnProperty;
|
||||
|
||||
@ -61,11 +61,11 @@
|
||||
}
|
||||
exports._ = _;
|
||||
} else {
|
||||
root['_'] = _;
|
||||
root._ = _;
|
||||
}
|
||||
|
||||
// Current version.
|
||||
_.VERSION = '1.4.2';
|
||||
_.VERSION = '1.4.4';
|
||||
|
||||
// Collection Functions
|
||||
// --------------------
|
||||
@ -102,6 +102,8 @@
|
||||
return results;
|
||||
};
|
||||
|
||||
var reduceError = 'Reduce of empty array with no initial value';
|
||||
|
||||
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||||
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
||||
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
||||
@ -119,7 +121,7 @@
|
||||
memo = iterator.call(context, memo, value, index, list);
|
||||
}
|
||||
});
|
||||
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
||||
if (!initial) throw new TypeError(reduceError);
|
||||
return memo;
|
||||
};
|
||||
|
||||
@ -130,7 +132,7 @@
|
||||
if (obj == null) obj = [];
|
||||
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||||
if (context) iterator = _.bind(iterator, context);
|
||||
return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||
}
|
||||
var length = obj.length;
|
||||
if (length !== +length) {
|
||||
@ -146,7 +148,7 @@
|
||||
memo = iterator.call(context, memo, obj[index], index, list);
|
||||
}
|
||||
});
|
||||
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
||||
if (!initial) throw new TypeError(reduceError);
|
||||
return memo;
|
||||
};
|
||||
|
||||
@ -177,12 +179,9 @@
|
||||
|
||||
// Return all the elements for which a truth test fails.
|
||||
_.reject = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
each(obj, function(value, index, list) {
|
||||
if (!iterator.call(context, value, index, list)) results[results.length] = value;
|
||||
});
|
||||
return results;
|
||||
return _.filter(obj, function(value, index, list) {
|
||||
return !iterator.call(context, value, index, list);
|
||||
}, context);
|
||||
};
|
||||
|
||||
// Determine whether all of the elements match a truth test.
|
||||
@ -216,20 +215,19 @@
|
||||
// Determine if the array or object contains a given value (using `===`).
|
||||
// Aliased as `include`.
|
||||
_.contains = _.include = function(obj, target) {
|
||||
var found = false;
|
||||
if (obj == null) return found;
|
||||
if (obj == null) return false;
|
||||
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||
found = any(obj, function(value) {
|
||||
return any(obj, function(value) {
|
||||
return value === target;
|
||||
});
|
||||
return found;
|
||||
};
|
||||
|
||||
// Invoke a method (with arguments) on every item in a collection.
|
||||
_.invoke = function(obj, method) {
|
||||
var args = slice.call(arguments, 2);
|
||||
var isFunc = _.isFunction(method);
|
||||
return _.map(obj, function(value) {
|
||||
return (_.isFunction(method) ? method : value[method]).apply(value, args);
|
||||
return (isFunc ? method : value[method]).apply(value, args);
|
||||
});
|
||||
};
|
||||
|
||||
@ -239,10 +237,10 @@
|
||||
};
|
||||
|
||||
// Convenience version of a common use case of `filter`: selecting only objects
|
||||
// with specific `key:value` pairs.
|
||||
_.where = function(obj, attrs) {
|
||||
if (_.isEmpty(attrs)) return [];
|
||||
return _.filter(obj, function(value) {
|
||||
// containing specific `key:value` pairs.
|
||||
_.where = function(obj, attrs, first) {
|
||||
if (_.isEmpty(attrs)) return first ? null : [];
|
||||
return _[first ? 'find' : 'filter'](obj, function(value) {
|
||||
for (var key in attrs) {
|
||||
if (attrs[key] !== value[key]) return false;
|
||||
}
|
||||
@ -250,6 +248,12 @@
|
||||
});
|
||||
};
|
||||
|
||||
// Convenience version of a common use case of `find`: getting the first object
|
||||
// containing specific `key:value` pairs.
|
||||
_.findWhere = function(obj, attrs) {
|
||||
return _.where(obj, attrs, true);
|
||||
};
|
||||
|
||||
// Return the maximum element or (element-based computation).
|
||||
// Can't optimize arrays of integers longer than 65,535 elements.
|
||||
// See: https://bugs.webkit.org/show_bug.cgi?id=80797
|
||||
@ -258,7 +262,7 @@
|
||||
return Math.max.apply(Math, obj);
|
||||
}
|
||||
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
||||
var result = {computed : -Infinity};
|
||||
var result = {computed : -Infinity, value: -Infinity};
|
||||
each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed >= result.computed && (result = {value : value, computed : computed});
|
||||
@ -272,7 +276,7 @@
|
||||
return Math.min.apply(Math, obj);
|
||||
}
|
||||
if (!iterator && _.isEmpty(obj)) return Infinity;
|
||||
var result = {computed : Infinity};
|
||||
var result = {computed : Infinity, value: Infinity};
|
||||
each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed < result.computed && (result = {value : value, computed : computed});
|
||||
@ -321,7 +325,7 @@
|
||||
// An internal function used for aggregate "group by" operations.
|
||||
var group = function(obj, value, context, behavior) {
|
||||
var result = {};
|
||||
var iterator = lookupIterator(value);
|
||||
var iterator = lookupIterator(value || _.identity);
|
||||
each(obj, function(value, index) {
|
||||
var key = iterator.call(context, value, index, obj);
|
||||
behavior(result, key, value);
|
||||
@ -341,7 +345,7 @@
|
||||
// either a string attribute to count by, or a function that returns the
|
||||
// criterion.
|
||||
_.countBy = function(obj, value, context) {
|
||||
return group(obj, value, context, function(result, key, value) {
|
||||
return group(obj, value, context, function(result, key) {
|
||||
if (!_.has(result, key)) result[key] = 0;
|
||||
result[key]++;
|
||||
});
|
||||
@ -363,12 +367,14 @@
|
||||
// Safely convert anything iterable into a real, live array.
|
||||
_.toArray = function(obj) {
|
||||
if (!obj) return [];
|
||||
if (obj.length === +obj.length) return slice.call(obj);
|
||||
if (_.isArray(obj)) return slice.call(obj);
|
||||
if (obj.length === +obj.length) return _.map(obj, _.identity);
|
||||
return _.values(obj);
|
||||
};
|
||||
|
||||
// Return the number of elements in an object.
|
||||
_.size = function(obj) {
|
||||
if (obj == null) return 0;
|
||||
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
|
||||
};
|
||||
|
||||
@ -379,6 +385,7 @@
|
||||
// values in the array. Aliased as `head` and `take`. The **guard** check
|
||||
// allows it to work with `_.map`.
|
||||
_.first = _.head = _.take = function(array, n, guard) {
|
||||
if (array == null) return void 0;
|
||||
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
||||
};
|
||||
|
||||
@ -393,6 +400,7 @@
|
||||
// Get the last element of an array. Passing **n** will return the last N
|
||||
// values in the array. The **guard** check allows it to work with `_.map`.
|
||||
_.last = function(array, n, guard) {
|
||||
if (array == null) return void 0;
|
||||
if ((n != null) && !guard) {
|
||||
return slice.call(array, Math.max(array.length - n, 0));
|
||||
} else {
|
||||
@ -410,7 +418,7 @@
|
||||
|
||||
// Trim out all falsy values from an array.
|
||||
_.compact = function(array) {
|
||||
return _.filter(array, function(value){ return !!value; });
|
||||
return _.filter(array, _.identity);
|
||||
};
|
||||
|
||||
// Internal implementation of a recursive `flatten` function.
|
||||
@ -439,6 +447,11 @@
|
||||
// been sorted, you have the option of using a faster algorithm.
|
||||
// Aliased as `unique`.
|
||||
_.uniq = _.unique = function(array, isSorted, iterator, context) {
|
||||
if (_.isFunction(isSorted)) {
|
||||
context = iterator;
|
||||
iterator = isSorted;
|
||||
isSorted = false;
|
||||
}
|
||||
var initial = iterator ? _.map(array, iterator, context) : array;
|
||||
var results = [];
|
||||
var seen = [];
|
||||
@ -491,6 +504,7 @@
|
||||
// pairs, or two parallel arrays of the same length -- one of keys, and one of
|
||||
// the corresponding values.
|
||||
_.object = function(list, values) {
|
||||
if (list == null) return {};
|
||||
var result = {};
|
||||
for (var i = 0, l = list.length; i < l; i++) {
|
||||
if (values) {
|
||||
@ -561,25 +575,23 @@
|
||||
// Function (ahem) Functions
|
||||
// ------------------
|
||||
|
||||
// Reusable constructor function for prototype setting.
|
||||
var ctor = function(){};
|
||||
|
||||
// Create a function bound to a given object (assigning `this`, and arguments,
|
||||
// optionally). Binding with arguments is also known as `curry`.
|
||||
// Delegates to **ECMAScript 5**'s native `Function.bind` if available.
|
||||
// We check for `func.bind` first, to fail fast when `func` is undefined.
|
||||
_.bind = function bind(func, context) {
|
||||
var bound, args;
|
||||
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
|
||||
// available.
|
||||
_.bind = function(func, context) {
|
||||
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
||||
if (!_.isFunction(func)) throw new TypeError;
|
||||
args = slice.call(arguments, 2);
|
||||
return bound = function() {
|
||||
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
|
||||
ctor.prototype = func.prototype;
|
||||
var self = new ctor;
|
||||
var result = func.apply(self, args.concat(slice.call(arguments)));
|
||||
if (Object(result) === result) return result;
|
||||
return self;
|
||||
var args = slice.call(arguments, 2);
|
||||
return function() {
|
||||
return func.apply(context, args.concat(slice.call(arguments)));
|
||||
};
|
||||
};
|
||||
|
||||
// Partially apply a function by creating a version that has had some of its
|
||||
// arguments pre-filled, without changing its dynamic `this` context.
|
||||
_.partial = function(func) {
|
||||
var args = slice.call(arguments, 1);
|
||||
return function() {
|
||||
return func.apply(this, args.concat(slice.call(arguments)));
|
||||
};
|
||||
};
|
||||
|
||||
@ -587,7 +599,7 @@
|
||||
// all callbacks defined on an object belong to it.
|
||||
_.bindAll = function(obj) {
|
||||
var funcs = slice.call(arguments, 1);
|
||||
if (funcs.length == 0) funcs = _.functions(obj);
|
||||
if (funcs.length === 0) funcs = _.functions(obj);
|
||||
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||||
return obj;
|
||||
};
|
||||
@ -618,25 +630,26 @@
|
||||
// Returns a function, that, when invoked, will only be triggered at most once
|
||||
// during a given window of time.
|
||||
_.throttle = function(func, wait) {
|
||||
var context, args, timeout, throttling, more, result;
|
||||
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
|
||||
var context, args, timeout, result;
|
||||
var previous = 0;
|
||||
var later = function() {
|
||||
previous = new Date;
|
||||
timeout = null;
|
||||
result = func.apply(context, args);
|
||||
};
|
||||
return function() {
|
||||
context = this; args = arguments;
|
||||
var later = function() {
|
||||
var now = new Date;
|
||||
var remaining = wait - (now - previous);
|
||||
context = this;
|
||||
args = arguments;
|
||||
if (remaining <= 0) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
if (more) {
|
||||
result = func.apply(context, args);
|
||||
}
|
||||
whenDone();
|
||||
};
|
||||
if (!timeout) timeout = setTimeout(later, wait);
|
||||
if (throttling) {
|
||||
more = true;
|
||||
} else {
|
||||
throttling = true;
|
||||
previous = now;
|
||||
result = func.apply(context, args);
|
||||
} else if (!timeout) {
|
||||
timeout = setTimeout(later, remaining);
|
||||
}
|
||||
whenDone();
|
||||
return result;
|
||||
};
|
||||
};
|
||||
@ -754,8 +767,10 @@
|
||||
// Extend a given object with all the properties in passed-in object(s).
|
||||
_.extend = function(obj) {
|
||||
each(slice.call(arguments, 1), function(source) {
|
||||
for (var prop in source) {
|
||||
obj[prop] = source[prop];
|
||||
if (source) {
|
||||
for (var prop in source) {
|
||||
obj[prop] = source[prop];
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
@ -784,8 +799,10 @@
|
||||
// Fill in a given object with default properties.
|
||||
_.defaults = function(obj) {
|
||||
each(slice.call(arguments, 1), function(source) {
|
||||
for (var prop in source) {
|
||||
if (obj[prop] == null) obj[prop] = source[prop];
|
||||
if (source) {
|
||||
for (var prop in source) {
|
||||
if (obj[prop] == null) obj[prop] = source[prop];
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
@ -950,7 +967,7 @@
|
||||
|
||||
// Is a given object a finite number?
|
||||
_.isFinite = function(obj) {
|
||||
return _.isNumber(obj) && isFinite(obj);
|
||||
return isFinite(obj) && !isNaN(parseFloat(obj));
|
||||
};
|
||||
|
||||
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
|
||||
@ -996,7 +1013,9 @@
|
||||
|
||||
// Run a function **n** times.
|
||||
_.times = function(n, iterator, context) {
|
||||
for (var i = 0; i < n; i++) iterator.call(context, i);
|
||||
var accum = Array(n);
|
||||
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
|
||||
return accum;
|
||||
};
|
||||
|
||||
// Return a random integer between min and max (inclusive).
|
||||
@ -1005,7 +1024,7 @@
|
||||
max = min;
|
||||
min = 0;
|
||||
}
|
||||
return min + (0 | Math.random() * (max - min + 1));
|
||||
return min + Math.floor(Math.random() * (max - min + 1));
|
||||
};
|
||||
|
||||
// List of HTML entities for escaping.
|
||||
@ -1061,7 +1080,7 @@
|
||||
// Useful for temporary DOM ids.
|
||||
var idCounter = 0;
|
||||
_.uniqueId = function(prefix) {
|
||||
var id = idCounter++;
|
||||
var id = ++idCounter + '';
|
||||
return prefix ? prefix + id : id;
|
||||
};
|
||||
|
||||
@ -1096,6 +1115,7 @@
|
||||
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||||
// and correctly escapes quotes within interpolated code.
|
||||
_.template = function(text, data, settings) {
|
||||
var render;
|
||||
settings = _.defaults({}, settings, _.templateSettings);
|
||||
|
||||
// Combine delimiters into one regular expression via alternation.
|
||||
@ -1111,11 +1131,18 @@
|
||||
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
||||
source += text.slice(index, offset)
|
||||
.replace(escaper, function(match) { return '\\' + escapes[match]; });
|
||||
source +=
|
||||
escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" :
|
||||
interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" :
|
||||
evaluate ? "';\n" + evaluate + "\n__p+='" : '';
|
||||
|
||||
if (escape) {
|
||||
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
||||
}
|
||||
if (interpolate) {
|
||||
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
||||
}
|
||||
if (evaluate) {
|
||||
source += "';\n" + evaluate + "\n__p+='";
|
||||
}
|
||||
index = offset + match.length;
|
||||
return match;
|
||||
});
|
||||
source += "';\n";
|
||||
|
||||
@ -1127,7 +1154,7 @@
|
||||
source + "return __p;\n";
|
||||
|
||||
try {
|
||||
var render = new Function(settings.variable || 'obj', '_', source);
|
||||
render = new Function(settings.variable || 'obj', '_', source);
|
||||
} catch (e) {
|
||||
e.source = source;
|
||||
throw e;
|
||||
Loading…
x
Reference in New Issue
Block a user