/*global require */
/*jshint unused:false */
'use strict';
/* NOTE: The theme name and themeMap are specified in the loader.js file */
if( !MetacatUI ){
/**
* The global variable that stores all the top-level data for this application
* @type {object}
*/
var MetacatUI = {};
}
MetacatUI.recaptchaURL = 'https://www.google.com/recaptcha/api/js/recaptcha_ajax';
if( MetacatUI.mapKey ){
var gmapsURL = 'https://maps.googleapis.com/maps/api/js?v=3&key=' + MetacatUI.mapKey;
define('gmaps',
['async!' + gmapsURL],
function() {
return google.maps;
});
} else {
define('gmaps', null);
}
MetacatUI.d3URL = '../components/d3.v3.min';
/* Configure the app to use requirejs, and map dependency aliases to their
directory location (.js is ommitted). Shim libraries that don't natively
support requirejs. */
require.config({
baseUrl: MetacatUI.root + '/js/',
waitSeconds: 180, //wait 3 minutes before throwing a timeout error
map: MetacatUI.themeMap,
urlArgs: "v=" + (MetacatUI.AppConfig.cachebuster || MetacatUI.metacatUIVersion),
paths: {
jquery: MetacatUI.root + '/components/jquery-1.9.1.min',
jqueryui: MetacatUI.root + '/components/jquery-ui.min',
jqueryform: MetacatUI.root + '/components/jquery.form',
underscore: MetacatUI.root + '/components/underscore-min',
backbone: MetacatUI.root + '/components/backbone-min',
localforage: MetacatUI.root + '/components/localforage.min',
bootstrap: MetacatUI.root + '/components/bootstrap.min',
text: MetacatUI.root + '/components/require-text',
jws: MetacatUI.root + '/components/jws-3.2.min',
jsrasign: MetacatUI.root + '/components/jsrsasign-4.9.0.min',
async: MetacatUI.root + '/components/async',
recaptcha: [MetacatUI.recaptchaURL, 'scripts/placeholder'],
nGeohash: MetacatUI.root + '/components/geohash/main',
fancybox: MetacatUI.root + '/components/fancybox/jquery.fancybox.pack', //v. 2.1.5
annotator: MetacatUI.root + '/components/annotator/v1.2.10/annotator-full',
bioportal: MetacatUI.root + '/components/bioportal/jquery.ncbo.tree-2.0.2',
clipboard: MetacatUI.root + '/components/clipboard.min',
uuid: MetacatUI.root + '/components/uuid',
md5: MetacatUI.root + '/components/md5',
rdflib: MetacatUI.root + '/components/rdflib.min',
x2js: MetacatUI.root + '/components/xml2json',
he: MetacatUI.root + '/components/he',
citation: MetacatUI.root + '/components/citation.min',
promise: MetacatUI.root + '/components/es6-promise.min',
// showdown + extensions (used in the markdownView to convert markdown to html)
showdown: MetacatUI.root + '/components/showdown/showdown.min',
showdownHighlight: MetacatUI.root + '/components/showdown/extensions/showdown-highlight/showdown-highlight',
highlight: MetacatUI.root + '/components/showdown/extensions/showdown-highlight/highlight.pack',
showdownFootnotes: MetacatUI.root + '/components/showdown/extensions/showdown-footnotes',
showdownBootstrap: MetacatUI.root + '/components/showdown/extensions/showdown-bootstrap',
showdownDocbook: MetacatUI.root + '/components/showdown/extensions/showdown-docbook',
showdownKatex: MetacatUI.root + '/components/showdown/extensions/showdown-katex/showdown-katex.min',
showdownCitation: MetacatUI.root + '/components/showdown/extensions/showdown-citation/showdown-citation',
showdownImages: MetacatUI.root + '/components/showdown/extensions/showdown-images',
showdownXssFilter: MetacatUI.root + '/components/showdown/extensions/showdown-xss-filter/showdown-xss-filter',
xss: MetacatUI.root + '/components/showdown/extensions/showdown-xss-filter/xss.min',
showdownHtags: MetacatUI.root + '/components/showdown/extensions/showdown-htags',
// drop zone creates drag and drop areas
Dropzone: MetacatUI.root + '/components/dropzone-amd-module',
// Polyfill required for using dropzone with older browsers
corejs: MetacatUI.root + '/components/core-js',
//Have a null fallback for our d3 components for browsers that don't support SVG
d3: MetacatUI.d3URL,
LineChart: ['views/LineChartView', null],
BarChart: ['views/BarChartView', null],
CircleBadge: ['views/CircleBadgeView', null],
DonutChart: ['views/DonutChartView', null],
MetricsChart: ['views/MetricsChartView', null],
},
shim: { /* used for libraries without native AMD support */
underscore: {
exports: '_',
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
bootstrap: {
deps: ['jquery'],
exports: 'Bootstrap'
},
annotator: {
exports: 'Annotator'
},
bioportal: {
exports: 'Bioportal'
},
jws: {
exports: 'JWS',
deps: ['jsrasign'],
},
nGeohash: {
exports: "geohash"
},
fancybox: {
deps: ['jquery']
},
uuid: {
exports: 'uuid'
},
rdflib: {
exports: 'rdf'
},
xss: {
exports: 'filterXSS'
},
citation: {
exports: 'citationRequire'
},
promise: {
exports: 'Promise'
}
}
});
MetacatUI.appModel = MetacatUI.appModel || {};
MetacatUI.appView = MetacatUI.appView || {};
MetacatUI.uiRouter = MetacatUI.uiRouter || {};
MetacatUI.appSearchResults = MetacatUI.appSearchResults || {};
MetacatUI.appSearchModel = MetacatUI.appSearchModel || {};
MetacatUI.rootDataPackage = MetacatUI.rootDataPackage || {};
MetacatUI.statsModel = MetacatUI.statsModel || {};
MetacatUI.mapModel = MetacatUI.mapModel || {};
MetacatUI.appLookupModel = MetacatUI.appLookupModel || {};
MetacatUI.nodeModel = MetacatUI.nodeModel || {};
MetacatUI.appUserModel = MetacatUI.appUserModel || {};
/* Setup the application scaffolding first */
require(['bootstrap', 'views/AppView', 'models/AppModel'],
function(Bootstrap, AppView, AppModel) {
'use strict';
// Create an AppModel, which controls the global app configuration and app states
// To be compatible with MetacatUI 2.11.X and earlier, we need to set the metacat context attribute here.
// This supports the old way tof configuring the app via the index.html file.
// As of MetacatUI 2.12.0, it is recommended that you configure MetacatUI via an AppConfig file.
MetacatUI.appModel = new AppModel({ context: MetacatUI.AppConfig.metacatContext });
//Check for custom settings in the theme config file
if(typeof MetacatUI.customAppConfig == "function") MetacatUI.customAppConfig();
/* Now require the rest of the libraries for the application */
require(['underscore', 'backbone', 'routers/router', 'collections/SolrResults', 'models/Search',
'models/Stats', 'models/Map', 'models/LookupModel', 'models/NodeModel',
'models/UserModel', 'models/DataONEObject', 'collections/DataPackage'
],
function(_, Backbone, UIRouter, SolrResultList, Search, Stats, MapModel, LookupModel, NodeModel, UserModel, DataONEObject, DataPackage) {
'use strict';
//Create all the other models and collections first
MetacatUI.appSearchResults = new SolrResultList([], {});
MetacatUI.appSearchModel = new Search();
MetacatUI.statsModel = new Stats();
MetacatUI.mapModel = (typeof customMapModelOptions == "object")? new MapModel(customMapModelOptions) : new MapModel();
MetacatUI.appLookupModel = new LookupModel();
MetacatUI.nodeModel = new NodeModel();
MetacatUI.appUserModel = new UserModel();
/* Create a general event dispatcher to enable
communication across app components
*/
MetacatUI.eventDispatcher = _.clone(Backbone.Events);
//Load the App View now
MetacatUI.appView = new AppView();
// Initialize routing and start Backbone.history()
(function() {
/**
* Backbone.routeNotFound
*
* Simple plugin that listens for false returns on Backbone.history.loadURL and fires an event
* to let the application know that no routes matched.
*
* @author STRML
*/
var oldLoadUrl = Backbone.History.prototype.loadUrl;
_.extend(Backbone.History.prototype, {
/*
* Override loadUrl & watch return value. Trigger event if no route was matched.
* @extends Backbone.History
* @return {Boolean} True if a route was matched
*/
loadUrl : function(fragment) {
if (!this.matchRoot()) return false;
fragment = this.fragment = this.getFragment(fragment);
var match = _.some(this.handlers, function(handler) {
if (handler.route.test(fragment)) {
handler.callback(fragment);
return true;
}
});
if(!match) this.trigger("routeNotFound");
return match;
},
matchRoot: function() {
var path = this.decodeFragment(this.location.pathname);
var rootPath = path.slice(0, this.root.length - 1) + '/';
return rootPath === this.root;
},
decodeFragment: function(fragment) {
return decodeURI(fragment.replace(/%25/g, '%2525'));
}
});
}).call(this);
//Make the router and begin the Backbone history
//The router will figure out which view to load first based on window location
MetacatUI.uiRouter = new UIRouter();
//Take the protocol and origin out of the root URL when sending it to Backbone.history.
// The root URL sent to Backbone.history should be either `/` or `/directory/...`
var historyRoot = MetacatUI.root;
//If there is a protocol
if( historyRoot.indexOf("://") > -1 ){
//Get the substring after the ``://``
historyRoot = historyRoot.substring(historyRoot.indexOf("://") + 3);
//If there is no `/`, this must be the root directory
if( historyRoot.indexOf("/") == -1 )
historyRoot = "/";
//Otherwise get the substring after the first /
else
historyRoot = historyRoot.substring( historyRoot.indexOf("/") );
}
//If there are no colons, periods, or slashes, this is a directory name
else if( historyRoot.indexOf(":") == -1 &&
historyRoot.indexOf(".") == -1 &&
historyRoot.indexOf("/") == -1 ){
//So the root is a leading slash and the directory name
historyRoot = "/" + historyRoot;
}
//If there is a slash, get the path name starting with the slash
else if( historyRoot.indexOf("/") > -1 ){
historyRoot = historyRoot.substring( historyRoot.indexOf("/") );
}
//All other strings are the root directory
else{
historyRoot = "/";
}
Backbone.history.start({
pushState: true,
root: historyRoot
});
$(document).on("click", "a:not([data-toggle],[target])", function(evt) {
// Don't hijack the event if the user had Control or Command held down
if (evt.ctrlKey || evt.metaKey) {
return;
}
var href = { prop: $(this).prop("href"), attr: $(this).attr("href") };
// Stop if the click happened on an a w/o an href
// This is kind of a weird edge case where. This could be removed if
// we remove these instances from the codebase
if (typeof href === "undefined" || typeof href.attr === "undefined" ||
href.attr === "") {
return;
}
//Don't route to URLs with the DataONE API, which are sometimes proxied
// via Apache ProxyPass so start with the MetacatUI origin
if( href.attr.indexOf("/cn/v2/") > 0 || href.attr.indexOf("/mn/v2/") > 0 ){
return;
}
var root = location.protocol + "//" + location.host + Backbone.history.options.root;
// Remove the MetacatUI (plus a trailing /) from the value in the 'href'
// attribute of the clicked element so Backbone.history.navigate works.
// Note that a RegExp was used here to anchor the .replace call to the
// front of the string so that this code works when MetacatUI.root is "".
var route = href.attr.replace(new RegExp("^" + MetacatUI.root + "/"), "");
// Catch routes hrefs that start with # and don't do anything with them
if (href.attr.indexOf("#") == 0) { return; }
//If the URL is not a route defined in the app router, then follow the link
//If the URL is not at the MetacatUI root, then follow the link
if (href.prop && href.prop.slice(0, root.length) === root &&
_.contains(MetacatUI.uiRouter.getRouteNames(), MetacatUI.uiRouter.getRouteName(route))) {
evt.preventDefault();
Backbone.history.navigate(route, true);
}
});
});
});