/*global require */ /*jshint unused:false */ 'use strict'; 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', metacatuiConnectors: MetacatUI.root + "/js/connectors/Filters-Search", // 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', // woofmark - markdown editor woofmark: MetacatUI.root + '/components/woofmark.min', // drop zone creates drag and drop areas Dropzone: MetacatUI.root + '/components/dropzone-amd-module', // Packages that convert between json data to markdown table markdownTableFromJson: MetacatUI.root + '/components/markdown-table-from-json.min', markdownTableToJson: MetacatUI.root + '/components/markdown-table-to-json', // Polyfill required for using dropzone with older browsers corejs: MetacatUI.root + '/components/core-js', // Searchable multi-select dropdown component semanticUItransition: MetacatUI.root + '/components/semanticUI/transition.min', semanticUIdropdown: MetacatUI.root + '/components/semanticUI/dropdown.min', // To make elements drag and drop, sortable sortable: MetacatUI.root + '/components/sortable.min', //Cesium cesium: MetacatUI.root + "/components/cesium/Cesium", //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' }, metacatuiConnectors: { exports: "FiltersSearchConnector" } } }); MetacatUI.appModel = MetacatUI.appModel || {}; MetacatUI.appView = MetacatUI.appView || {}; MetacatUI.uiRouter = MetacatUI.uiRouter || {}; MetacatUI.appSearchResults = MetacatUI.appSearchResults || {}; MetacatUI.appSearchModel = MetacatUI.appSearchModel || {}; /** * @name MetacatUI.rootDataPackage * @type {string} * @description The top-level {@link DataPackage} that is currently being viewed or edited in MetacatUI. */ 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(); MetacatUI.appView.render(); // 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); } }); MetacatUI.appModel.trigger("appInitialized"); }); });