<commit_before>define([
  "dojo/_base/declare"
, "dojo/when"
, "dojo/topic"
, "dojo/on"
, "dojo/dom-construct"
, "dojo/dom-style"
, "dojo/dom-attr"
, "dojo/dom-class"
, "dojo/dom-geometry"
, "dojo/_base/lang"

, "dijit/_WidgetBase"
, "dijit/_OnDijitClickMixin"
, "dijit/_Container"
, "dijit/layout/_ContentPaneResizeMixin"
, "dijit/_TemplatedMixin"
, "dijit/_WidgetsInTemplateMixin"
, "dijit/form/_FormValueMixin"

, "dgrid/OnDemandList"
, "dgrid/Selection"
, "dgrid/Keyboard"
, "dgrid/extensions/DijitRegistry"
, "put-selector/put"

, "hotplate/hotDojoWidgets/_OverlayMixin"
, "hotplate/hotDojoStores/stores"

], function(
  declare
, when
, topic
, on
, domConstruct
, domStyle
, domAttr
, domClass
, domGeometry
, lang

, _WidgetBase
, _OnDijitClickMixin
, _Container
, _ContentPaneResizeMixin
, _TemplatedMixin
, _WidgetsInTemplateMixin
, _FormValueMixin

, OnDemandList
, Selection
, Keyboard
, DijitRegistry
, put

, _OverlayMixin
, stores

){

  return declare( [ _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _Container, _ContentPaneResizeMixin, _OnDijitClickMixin, _FormValueMixin, _OverlayMixin ] , {

    templateString: '
\n' +
                    '
\n'+
                    '

Pick

\n' +
                    '

\n' +
                    '
\n'+
                    '

\n'+
                    '    <input type="hidden" ${!nameAttrSetting} data-dojo-attach-point="valueNode" value="${value}" aria-hidden="true" />\n'+
                    '
\n'+
                    '\n'+
                    '',

    widgetsInTemplate: true,

    // Store
    //store: null,

    ownClass: null,

    // Store name. Useful for topics etc.
    storeName: '',
    storeExtraParameters: {},
    storeParameters: {},

    initialSort: [],
    initialFilter: null,

    // Refresh immediately on refreshData topic
    immediateRefresh: false,

    // renderRow which will be used by the created dgrid.
    // It needs to be defined
    renderRow: function( o ){ return "renderRow not defined"; } ,

    // The list widget
    listWidget: null,

    // Whether the listWidget is visible or not
    expanded: false,

    // When automatically moving based on the current window,
    // the minimum distance to the bottom
    distanceFromBottom: 20,

    _loadingValue: false,

    // Proxy method for listwidget.row()
    row: function( p ){
      if( this.listWidget ){
        return this.listWidget.row( p );
      }
    },

    resize: function(){
      this._moveIfNecessary();
      this.inherited(arguments);
    },

    destroy: function(){
      this.listWidget.destroy();
      this.inherited(arguments);
    },

    // STOLEN FROM _FormWidget.js
    postMixInProperties: function(){
      // Setup name=foo string to be referenced from the template (but only if a name has been specified)
      // Unfortunately we can't use _setNameAttr to set the name due to IE limitations, see #8484, #8660.
      // Regarding escaping, see heading "Attribute values" in
      // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
      this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/"/g, """) + '"') : '';
      this.inherited(arguments);

      // Copy attribute over from the prototype
      this.storeExtraParameters = lang.mixin( this.storeExtraParameters );

      // Mixin the extra parameters with storeParameters
      this.storeParameters = lang.mixin( {}, this.storeParameters, this.storeExtraParameters );

      // Make up the store internal variable
      this.store = stores( this.storeName, this.storeParameters );

    },

    // Override automatic assigning type --> focusNode, it causes exception on IE.
    // Instead, type must be specified as ${type} in the template, as part of the original DOM
    _setTypeAttr: null,

    // Sets valueNode in the DOM
    _setValueAttr: function(value){

      this.inherited(arguments);
      var self = this;

      self._set( 'value', value );

      // Set the valueNode (the hidden field in this widget)
      domAttr.set(this.valueNode, "value", value);
      // domAttr.set(this.valueNode, "value", this.get("value"));

      if( value ){

        // If the row is displayed in the dgrid List, then take it from there...
        var row = self.row( value );
        if( row && row.data ){
          self.labelNode.innerHTML = '';
          put( self.labelNode, self.renderRow( row.data ) );

        // Otherwise, if the raw is not in the dgrid list, load it up
        } else {

          when( self.store.get( value ) ).then(

            function( data ){
              self.labelNode.innerHTML = '';
              put( self.labelNode, self.renderRow( data ) );
            },
            function( err ) {
              self.labelNode.innerHTML = "ID: " + value;
            }

          );

          //self.labelNode.innerHTML = "ID: " + value;
        }
      }

    },

    startup: function(){
      this.inherited(arguments);
    },

    postCreate: function(){

      this.inherited(arguments);

      var self = this;

      // Set this widget's own class, if defined in prototype
      if( self.ownClass ){
        domClass.add( self.domNode, self.ownClass );
      }

      // Overlayed, non-clickable by default
      //self.set( 'overlayStatus', { overlayed: true, clickable: false } );

      // Make up the constructor for the select list. It's basically a dgrid, with the
      // renderRow set as the parent's, and single selection mode
      var ListConstructor = declare( [ OnDemandList, Selection, Keyboard, DijitRegistry ], {
        renderRow: self.renderRow,
        selectionMode: 'single',
        //minRowsPerPage: 0, // Download the _lot_, or selected item might not be in memory

        // Adding and deleting rows will trigger the "position calculation"
        // function to make sure that the select list is not ourside of the
        // visible area
        newRow: function(){
          var r = this.inherited(arguments);
          self._moveIfNecessary();
          return r;
        },
        removeRow: function(){
          var r = this.inherited(arguments);
          self._moveIfNecessary();
          return r;
        },

        postCreate: function(){
          this.inherited(arguments);
        },

      } );

      // Make up the collection with the initial sorting/filters
      var collection = self.store;
      if( self.initialSort.length) collection = collection.sort( self.initialSort );
      if( self.initialFilter ) collection = collection.filter( self.initialFilter );

      // Make the dgrid widget. Note that query and queryOptions NEED to
      // be passed to the widget via the constructor
      self.listWidget = new ListConstructor( { collection: collection });

      // Place the grid, invisible, in the right node, start it up, and
      // make it invisible
      domConstruct.place( self.listWidget.domNode, self.listWidgetNode );
      self.listWidget.startup();
      domStyle.set( self.listWidget.domNode, { display: 'none' } );

      self.listWidget.on("dgrid-select", function( e ) {
        var rowId = e.rows[0].id;
        self.set( 'value', rowId );
      });

      // If there is a change and store is queryEngine-less and has sorting/filtering, will need to refresh
      self.store.on( 'add,update,remove', function( event ){
      if( ! self.store.queryEngine && self.listWidget._renderedCollection.queryLog.length ) {

          // Zap partialResults, so that Observable doesn't actually work
          self.listWidget._renderedCollection._partialResults = null;

          // Refresh the data
          self.listWidget.refresh( { keepScrollPosition: true } );
        }
      });

      // If the element currently selected is changed, need to re-render
      // the labelNode to reflect the changes.
      // Ditto for deletions.
      self.store.on( 'update', function( event ){
        if( event.target[ self.store.idProperty ] == self.value ){
          self.labelNode.innerHTML = '';
          put( self.labelNode, self.renderRow( event.target ) );
        }
      });
      self.store.on( 'remove', function( event ){
        if( event.target[ self.store.idProperty ] == self.value ){
          self.labelNode.innerHTML = 'Item deleted';
        }
      });

      self.own(

        // Reload ON can ne triggered by a click, or by a refreshData
        on( self.domNode, 'overlayClick', function( e ){
          self.set( 'overlayStatus', { overlayed: false, clickable: true } ); // CLICKME OFF
          self.set( 'overlayStatus', { overlayed: true, clickable: false } ); // LOADING ON
          self.listWidget.refresh();
        }),
        topic.subscribe('refreshData', function( ){
          if( self.immediateRefresh ){
            self.set( 'overlayStatus', { overlayed: true, clickable: false } ); // LOADING ON
            self.listWidget.refresh();
          } else {
            self.set( 'overlayStatus', { overlayed: true, clickable: true } ); // CLICKME ON
            collapseList();
          }
        }),

        // Reload OFF can be triggered by a refresh-complete or by a dgrid error
        on( self.listWidget.domNode, 'dgrid-refresh-complete', function( e ){
           self.set( 'overlayStatus', { overlayed: false, clickable: false } ); // LOADING OFF
           self.set( 'value', self.value );
        }),
        on( self.listWidget.domNode, 'dgrid-error', function( e ){
           self.set( 'overlayStatus', { overlayed: false, clickable: false } ); // LOADING OFF
           self.set( 'overlayStatus', { overlayed: true, clickable: true } ); // CLICKME ON
          topic.publish( 'globalAlert', 'Error: ' + e.error.message, 5000 );
          collapseList();
        }),

        // Escape pressed at body level: close the select box, select
        // value that selected in the first place when it was open
        //on( document.body, 'keydown', function( e ) {
        on( self.listWidget.domNode, 'keydown', function( e ) {
          if( e.keyCode == 27 && self.expanded){
            e.stopPropagation();
            domStyle.set( self.listWidget.domNode, { display: 'none' } );
            self.expanded = false;
            self.listWidget.clearSelection();
            self.listWidget.select( self.valueWhenOpen );
          }
        }),

        // Open or close when pressing enter
        on( self.domNode, 'keydown', function( e ){
          if( e.keyCode == 13 ){
            if( ! self.expanded  ){
              expandList();
            } else {
              collapseList( self.row( e ) );
            }
          }
        }),

        // Open or close when rlicking on it with mouse
        on( self.domNode, 'click', function( e ){
         // self.listWidget.refresh();
          if( ! self.expanded ){
            expandList();
          } else {
            collapseList( self.row( e ) );
         }
        }),

        // Focus out: hide the select box
        // FIXME: Haven't quite managed this one yet
        on( document.body, 'click', function( e ) {
          if( self.expanded){
          //  domStyle.set( self.listWidget.domNode, { display: 'none' } );
          //  self.expanded = false;
          }
        })

      );

      // Function to expand the widget to include the select list.
      // It will do all of the required operations: make it visible in the CSS,
      // give the focus to the right element, mark it as "expanded", and move it
      // if necessary to do so (e.g. its bottom is out of the visible screen)
      function expandList(){
        self.valueWhenOpen = self.value;
        domStyle.set( self.listWidget.domNode, { display: 'block' } );
        var r = self.row( self.value );
        self.listWidget.focus( r );
        self.expanded = true;
        self._moveIfNecessary();
      }

      // Function to collapse the widget so that the select list is no longe there.
      // It will just make it invisible, but it will also set the widget value to
      // the row element. This is to be called once a pick is successful, either
      // with an Enter or with a mouse click.
      function collapseList( row ){

        domStyle.set( self.listWidget.domNode, { display: 'none' } );
        self.expanded = false;
        if( row ){
          self.set( 'value', row.id);
        }
      }

    },

    // Te dgrid might grow to the point that its bottom is outside of the
    // actual visible area. This would be bad (the bottom elements would be
    // unreachable). So, it calculates things up and makes sure that the dgrid
    // is moved up, also considering the required self.distanceFromBottom
    _moveIfNecessary: function(){
      var self = this;

      //self.listWidget.resize();
      domStyle.set( self.listWidget.domNode, { top: '' } );
      var bodyBox = domGeometry.getContentBox( document.body );
      var listBox = domGeometry.position( self.listWidget.domNode, true );
      var delta = bodyBox.h - ( listBox.y + listBox.h ) - self.distanceFromBottom;
      if( delta < 0 ){
        domStyle.set( self.listWidget.domNode, { top: (delta)+'px' } );
      } else {
        domStyle.set( self.listWidget.domNode, { top: '' } );
      }

    },

  });

});

<commit_msg>Style changes<commit_after>define([
  "dojo/_base/declare"
, "dojo/when"
, "dojo/topic"
, "dojo/on"
, "dojo/dom-construct"
, "dojo/dom-style"
, "dojo/dom-attr"
, "dojo/dom-class"
, "dojo/dom-geometry"
, "dojo/_base/lang"

, "dijit/_WidgetBase"
, "dijit/_OnDijitClickMixin"
, "dijit/_Container"
, "dijit/layout/_ContentPaneResizeMixin"
, "dijit/_TemplatedMixin"
, "dijit/_WidgetsInTemplateMixin"
, "dijit/form/_FormValueMixin"

, "dgrid/OnDemandList"
, "dgrid/Selection"
, "dgrid/Keyboard"
, "dgrid/extensions/DijitRegistry"
, "put-selector/put"

, "hotplate/hotDojoWidgets/_OverlayMixin"
, "hotplate/hotDojoStores/stores"

], function(
  declare
, when
, topic
, on
, domConstruct
, domStyle
, domAttr
, domClass
, domGeometry
, lang

, _WidgetBase
, _OnDijitClickMixin
, _Container
, _ContentPaneResizeMixin
, _TemplatedMixin
, _WidgetsInTemplateMixin
, _FormValueMixin

, OnDemandList
, Selection
, Keyboard
, DijitRegistry
, put

, _OverlayMixin
, stores

){

  return declare( [ _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, _Container, _ContentPaneResizeMixin, _OnDijitClickMixin, _FormValueMixin, _OverlayMixin ] , {

    templateString: '
\n' +
                    '
\n'+
                    '

Pick

\n' +
                    '

\n' +
                    '
\n'+
                    '

\n'+
                    '    <input type="hidden" ${!nameAttrSetting} data-dojo-attach-point="valueNode" value="${value}" aria-hidden="true" />\n'+
                    '
\n'+
                    '\n'+
                    '',

    widgetsInTemplate: true,

    // Store
    //store: null,

    ownClass: null,

    // Store name. Useful for topics etc.
    storeName: '',
    storeExtraParameters: {},
    storeParameters: {},

    initialSort: [],
    initialFilter: null,

    // Refresh immediately on refreshData topic
    immediateRefresh: false,

    // renderRow which will be used by the created dgrid.
    // It needs to be defined
    renderRow: function( o ){ return "renderRow not defined"; } ,

    // The list widget
    listWidget: null,

    // Whether the listWidget is visible or not
    expanded: false,

    // When automatically moving based on the current window,
    // the minimum distance to the bottom
    distanceFromBottom: 20,

    _loadingValue: false,

    // Proxy method for listwidget.row()
    row: function( p ){
      if( this.listWidget ){
        return this.listWidget.row( p );
      }
    },

    resize: function(){
      this._moveIfNecessary();
      this.inherited(arguments);
    },

    destroy: function(){
      this.listWidget.destroy();
      this.inherited(arguments);
    },

    // STOLEN FROM _FormWidget.js
    postMixInProperties: function(){
      // Setup name=foo string to be referenced from the template (but only if a name has been specified)
      // Unfortunately we can't use _setNameAttr to set the name due to IE limitations, see #8484, #8660.
      // Regarding escaping, see heading "Attribute values" in
      // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
      this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/"/g, """) + '"') : '';
      this.inherited(arguments);

      // Copy attribute over from the prototype
      this.storeExtraParameters = lang.mixin( this.storeExtraParameters );

      // Mixin the extra parameters with storeParameters
      this.storeParameters = lang.mixin( {}, this.storeParameters, this.storeExtraParameters );

      // Make up the store internal variable
      this.store = stores( this.storeName, this.storeParameters );

    },

    // Override automatic assigning type --> focusNode, it causes exception on IE.
    // Instead, type must be specified as ${type} in the template, as part of the original DOM
    _setTypeAttr: null,

    // Sets valueNode in the DOM
    _setValueAttr: function(value){

      this.inherited(arguments);
      var self = this;

      self._set( 'value', value );

      // Set the valueNode (the hidden field in this widget)
      domAttr.set(this.valueNode, "value", value);
      // domAttr.set(this.valueNode, "value", this.get("value"));

      if( value ){

        // If the row is displayed in the dgrid List, then take it from there...
        var row = self.row( value );
        if( row && row.data ){
          self.labelNode.innerHTML = '';
          put( self.labelNode, self.renderRow( row.data ) );

        // Otherwise, if the raw is not in the dgrid list, load it up
        } else {

          when( self.store.get( value ) ).then(

            function( data ){
              self.labelNode.innerHTML = '';
              put( self.labelNode, self.renderRow( data ) );
            },
            function( err ) {
              self.labelNode.innerHTML = "ID: " + value;
            }

          );

          //self.labelNode.innerHTML = "ID: " + value;
        }
      }

    },

    startup: function(){
      this.inherited(arguments);
    },

    postCreate: function(){

      this.inherited(arguments);

      var self = this;

      // Set this widget's own class, if defined in prototype
      if( self.ownClass ){
        domClass.add( self.domNode, self.ownClass );
      }

      // Overlayed, non-clickable by default
      //self.set( 'overlayStatus', { overlayed: true, clickable: false } );

      // Make up the constructor for the select list. It's basically a dgrid, with the
      // renderRow set as the parent's, and single selection mode
      var ListConstructor = declare( [ OnDemandList, Selection, Keyboard, DijitRegistry ], {
        renderRow: self.renderRow,
        selectionMode: 'single',
        //minRowsPerPage: 0, // Download the _lot_, or selected item might not be in memory

        // Adding and deleting rows will trigger the "position calculation"
        // function to make sure that the select list is not ourside of the
        // visible area
        newRow: function(){
          var r = this.inherited(arguments);
          self._moveIfNecessary();
          return r;
        },
        removeRow: function(){
          var r = this.inherited(arguments);
          self._moveIfNecessary();
          return r;
        },

        postCreate: function(){
          this.inherited(arguments);
        },

      } );

      // Make up the collection with the initial sorting/filters
      var collection = self.store;
      if( self.initialSort.length) collection = collection.sort( self.initialSort );
      if( self.initialFilter ) collection = collection.filter( self.initialFilter );

      // Make the dgrid widget.
      self.listWidget = new ListConstructor( { collection: collection });

      // Place the grid, invisible, in the right node, start it up, and
      // make it invisible
      domConstruct.place( self.listWidget.domNode, self.listWidgetNode );
      self.listWidget.startup();
      domStyle.set( self.listWidget.domNode, { display: 'none' } );

      self.listWidget.on("dgrid-select", function( e ) {
        var rowId = e.rows[0].id;
        self.set( 'value', rowId );
      });

      // If there is a change and store is queryEngine-less and has sorting/filtering, will need to refresh
      self.store.on( 'add,update,remove', function( event ){

        if( ! self.store.queryEngine && self.listWidget._renderedCollection.queryLog.length ) {

          // Zap partialResults, so that Observable doesn't actually work
          self.listWidget._renderedCollection._partialResults = null;

          // Refresh the data
          self.listWidget.refresh( { keepScrollPosition: true } );
        }
      });

      // If the element currently selected is changed, need to re-render
      // the labelNode to reflect the changes.
      // Ditto for deletions.
      self.store.on( 'update', function( event ){
        if( event.target[ self.store.idProperty ] == self.value ){
          self.labelNode.innerHTML = '';
          put( self.labelNode, self.renderRow( event.target ) );
        }
      });
      self.store.on( 'remove', function( event ){
        if( event.target[ self.store.idProperty ] == self.value ){
          self.labelNode.innerHTML = 'Item deleted';
        }
      });

      self.own(

        // Reload ON can ne triggered by a click, or by a refreshData
        on( self.domNode, 'overlayClick', function( e ){
          self.set( 'overlayStatus', { overlayed: false, clickable: true } ); // CLICKME OFF
          self.set( 'overlayStatus', { overlayed: true, clickable: false } ); // LOADING ON
          self.listWidget.refresh();
        }),
        topic.subscribe('refreshData', function( ){
          if( self.immediateRefresh ){
            self.set( 'overlayStatus', { overlayed: true, clickable: false } ); // LOADING ON
            self.listWidget.refresh();
          } else {
            self.set( 'overlayStatus', { overlayed: true, clickable: true } ); // CLICKME ON
            collapseList();
          }
        }),

        // Reload OFF can be triggered by a refresh-complete or by a dgrid error
        on( self.listWidget.domNode, 'dgrid-refresh-complete', function( e ){
           self.set( 'overlayStatus', { overlayed: false, clickable: false } ); // LOADING OFF
           self.set( 'value', self.value );
        }),
        on( self.listWidget.domNode, 'dgrid-error', function( e ){
           self.set( 'overlayStatus', { overlayed: false, clickable: false } ); // LOADING OFF
           self.set( 'overlayStatus', { overlayed: true, clickable: true } ); // CLICKME ON
          topic.publish( 'globalAlert', 'Error: ' + e.error.message, 5000 );
          collapseList();
        }),

        // Escape pressed at body level: close the select box, select
        // value that selected in the first place when it was open
        //on( document.body, 'keydown', function( e ) {
        on( self.listWidget.domNode, 'keydown', function( e ) {
          if( e.keyCode == 27 && self.expanded){
            e.stopPropagation();
            domStyle.set( self.listWidget.domNode, { display: 'none' } );
            self.expanded = false;
            self.listWidget.clearSelection();
            self.listWidget.select( self.valueWhenOpen );
          }
        }),

        // Open or close when pressing enter
        on( self.domNode, 'keydown', function( e ){
          if( e.keyCode == 13 ){
            if( ! self.expanded  ){
              expandList();
            } else {
              collapseList( self.row( e ) );
            }
          }
        }),

        // Open or close when rlicking on it with mouse
        on( self.domNode, 'click', function( e ){
         // self.listWidget.refresh();
          if( ! self.expanded ){
            expandList();
          } else {
            collapseList( self.row( e ) );
         }
        }),

        // Focus out: hide the select box
        // FIXME: Haven't quite managed this one yet
        on( document.body, 'click', function( e ) {
          if( self.expanded){
          //  domStyle.set( self.listWidget.domNode, { display: 'none' } );
          //  self.expanded = false;
          }
        })

      );

      // Function to expand the widget to include the select list.
      // It will do all of the required operations: make it visible in the CSS,
      // give the focus to the right element, mark it as "expanded", and move it
      // if necessary to do so (e.g. its bottom is out of the visible screen)
      function expandList(){
        self.valueWhenOpen = self.value;
        domStyle.set( self.listWidget.domNode, { display: 'block' } );
        var r = self.row( self.value );
        self.listWidget.focus( r );
        self.expanded = true;
        self._moveIfNecessary();
      }

      // Function to collapse the widget so that the select list is no longe there.
      // It will just make it invisible, but it will also set the widget value to
      // the row element. This is to be called once a pick is successful, either
      // with an Enter or with a mouse click.
      function collapseList( row ){

        domStyle.set( self.listWidget.domNode, { display: 'none' } );
        self.expanded = false;
        if( row ){
          self.set( 'value', row.id);
        }
      }

    },

    // Te dgrid might grow to the point that its bottom is outside of the
    // actual visible area. This would be bad (the bottom elements would be
    // unreachable). So, it calculates things up and makes sure that the dgrid
    // is moved up, also considering the required self.distanceFromBottom
    _moveIfNecessary: function(){
      var self = this;

      //self.listWidget.resize();
      domStyle.set( self.listWidget.domNode, { top: '' } );
      var bodyBox = domGeometry.getContentBox( document.body );
      var listBox = domGeometry.position( self.listWidget.domNode, true );
      var delta = bodyBox.h - ( listBox.y + listBox.h ) - self.distanceFromBottom;
      if( delta < 0 ){
        domStyle.set( self.listWidget.domNode, { top: (delta)+'px' } );
      } else {
        domStyle.set( self.listWidget.domNode, { top: '' } );
      }

    },

  });

});

<|endoftext|>


<commit_before>/**
 * Created by cbrownroberts on 9/13/16.
 */
function bookList() {

    "use strict";

    var myBookList = {

        settings: {},
        strings: {},
        bindUiActions: function () {
            myBookList.iterateUrls();
        },
            init: function () {
                myBookList.bindUiActions();

                var isotopeScript = "http://unpkg.com/isotope-layout@3.0.1/dist/isotope.pkgd.min.js";

                //get script
                $.getScript(isotopeScript, function(){
                    $("head").append("


<commit_before>// # can/view/ejs/ejs.js
//
// `can.EJS`: Embedded JavaScript Templates
//
steal('can/util',
	'can/view',
	'can/util/string',
	'can/compute',
	'can/view/scanner.js',
	'can/view/render.js',
function (can) {
	// ## Helper methods
	var extend = can.extend,
		EJS = function (options) {
			// Supports calling EJS without the constructor.
			// This returns a function that renders the template.
			if (this.constructor !== EJS) {
				var ejs = new EJS(options);
				return function (data, helpers) {
					return ejs.render(data, helpers);
				};
			}
			// If we get a `function` directly, it probably is coming from
			// a `steal`-packaged view.
			if (typeof options === 'function') {
				this.template = {
					fn: options
				};
				return;
			}
			// Set options on self.
			extend(this, options);
			this.template = this.scanner.scan(this.text, this.name);
		};
	// Expose EJS via the `can` object.
	can.EJS = EJS;

	EJS.prototype.
	// ## Render
	// Render a view object with data and helpers.
	render = function (object, extraHelpers) {
		object = object || {};
		return this.template.fn.call(object, object, new EJS.Helpers(object, extraHelpers || {}));
	};
	extend(EJS.prototype, {
		// ## Scanner
		// Singleton scanner instance for parsing templates. See [scanner.js](scanner.html)
		// for more information.
		//
		// ### Text
		//
		// #### Definitions
		//
		// * `outStart` - Wrapper start text for view function.
		//
		// * `outEnd` - Wrapper end text for view function.
		//
		// * `argNames` - Arguments passed into view function.
		scanner: new can.view.Scanner({
			text: {
				outStart: 'with(_VIEW) { with (_CONTEXT) {',
				outEnd: "}}",
				argNames: '_CONTEXT,_VIEW',
				context: "this"
			},
			// ### Tokens
			//
			// An ordered token registry for the scanner.
			tokens: [
				// Template
				["templateLeft", "<%%"],
				// Right Template
				["templateRight", "%>"],
				// Return Unescaped
				["returnLeft", "<%=="],
				// Return Escaped
				["escapeLeft", "<%="],
				// Comment
				["commentLeft", "<%#"],
				// Evaluate code
				["left", "<%"],
				// Right -> All have same FOR Mustache ...
				["right", "%>"],
				["returnRight", "%>"]
			],
			// ### Helpers
			helpers: [
				{
					// #### name
					// Regex to see if its a func like `()->`.
					name: /\s*\(([\$\w]+)\)\s*->([^\n]*)/,
					// #### fn
					// Evaluate rocket syntax function with correct context.
					fn: function (content) {
						var quickFunc = /\s*\(([\$\w]+)\)\s*->([^\n]*)/,
							parts = content.match(quickFunc);

						return "can.proxy(function(__){var " + parts[1] + "=can.$(__);" + parts[2] + "}, this);";
					}
				}
			],
			// ### transform
			// Transforms the EJS template to add support for shared blocks.
			// Essentially, this breaks up EJS tags into multiple EJS tags
			// if they contained unmatched brackets.
			//
			// For example, this doesn't work:
			//
			// `<% if (1) { %><% if (1) { %> hi <% } } %>`
			//
			// ...without isolated EJS blocks:
			//
			// `<% if (1) { %><% if (1) { %> hi <% } %><% } %>`
			//
			// The result of transforming:
			//
			// `<% if (1) { %><% %><% if (1) { %><% %> hi <% } %><% } %>`
			/**
			 * @hide
			 * Transforms the EJS template to add support for shared blocks.
			 * Essentially, this breaks up EJS tags into multiple EJS tags
			 * if they contained unmatched brackets.
			 *
			 * For example, this doesn't work:
			 *	<% if (1) { %><% if (1) { %> hi <% } } %>
			 * ...without isolated EJS blocks:
			 *	<% if (1) { %><% if (1) { %> hi <% } %><% } %>
			 * The result of transforming:
			 *	<% if (1) { %><% %><% if (1) { %><% %> hi <% } %><% } %>
			 */
			transform: function (source) {
				return source.replace(/<%([\s\S]+?)%>/gm, function (whole, part) {
					var brackets = [],
						foundBracketPair, i;
					// Look for brackets (for removing self-contained blocks)
					part.replace(/[{}]/gm, function (bracket, offset) {
						brackets.push([
							bracket,
							offset
						]);
					});
					// Remove bracket pairs from the list of replacements
					do {
						foundBracketPair = false;
						for (i = brackets.length - 2; i >= 0; i--) {
							if (brackets[i][0] === '{' && brackets[i + 1][0] === '}') {
								brackets.splice(i, 2);
								foundBracketPair = true;
								break;
							}
						}
					} while (foundBracketPair);
					// Unmatched brackets found, inject EJS tags
					if (brackets.length >= 2) {
						var result = ['<%'],
							bracket, last = 0;
						for (i = 0; bracket = brackets[i]; i++) {
							result.push(part.substring(last, last = bracket[1]));
							if (bracket[0] === '{' && i < brackets.length - 1 || bracket[0] === '}' && i > 0) {
								result.push(bracket[0] === '{' ? '{ %><% ' : ' %><% }');
							} else {
								result.push(bracket[0]);
							}
							++last;
						}
						result.push(part.substring(last), '%>');
						return result.join('');
					}
					// Otherwise return the original
					else {
						return '<%' + part + '%>';
					}
				});
			}
		})
	});

	// ## Helpers
	// By adding functions to can.EJS.Helpers.prototype, those functions will be available in the
	// views.
	//
	// The following helper converts a given string to upper case:
	//
	//     can.EJS.Helpers.prototype.toUpper = function(params) {
	//       return params.toUpperCase();
	//     }

	// Use it like this in any EJS template:

	// `<%= toUpper('javascriptmvc') %>`

	// To access the current DOM element return a function that takes the element as a parameter:

	//     can.EJS.Helpers.prototype.upperHtml = function(params) {
	//       return function(el) {
	//         $(el).html(params.toUpperCase());
	//       }
	//     }

	// In your EJS view you can then call the helper on an element tag:

	// `<div <%= upperHtml('javascriptmvc') %>></div>`
	EJS.Helpers = function (data, extras) {
		this._data = data;
		this._extras = extras;
		extend(this, extras);
	};

	EJS.Helpers.prototype = {
		// TODO Deprecated!!
		list: function (list, cb) {
			can.each(list, function (item, i) {
				cb(item, i, list);
			});
		},
		each: function (list, cb) {
			// Normal arrays don't get live updated
			if (can.isArray(list)) {
				this.list(list, cb);
			} else {
				can.view.lists(list, cb);
			}
		}
	};
	// Options for `steal`'s build.
	can.view.register({
		suffix: 'ejs',
		script: function (id, src) {
			return 'can.EJS(function(_CONTEXT,_VIEW) { ' + new EJS({
				text: src,
				name: id
			})
				.template.out + ' })';
		},
		renderer: function (id, text) {
			return EJS({
				text: text,
				name: id
			});
		}
	});
	return can;
});
<commit_msg>removing docjs artifact #843<commit_after>// # can/view/ejs/ejs.js
//
// `can.EJS`: Embedded JavaScript Templates
//
steal('can/util',
	'can/view',
	'can/util/string',
	'can/compute',
	'can/view/scanner.js',
	'can/view/render.js',
function (can) {
	// ## Helper methods
	var extend = can.extend,
		EJS = function (options) {
			// Supports calling EJS without the constructor.
			// This returns a function that renders the template.
			if (this.constructor !== EJS) {
				var ejs = new EJS(options);
				return function (data, helpers) {
					return ejs.render(data, helpers);
				};
			}
			// If we get a `function` directly, it probably is coming from
			// a `steal`-packaged view.
			if (typeof options === 'function') {
				this.template = {
					fn: options
				};
				return;
			}
			// Set options on self.
			extend(this, options);
			this.template = this.scanner.scan(this.text, this.name);
		};
	// Expose EJS via the `can` object.
	can.EJS = EJS;

	EJS.prototype.
	// ## Render
	// Render a view object with data and helpers.
	render = function (object, extraHelpers) {
		object = object || {};
		return this.template.fn.call(object, object, new EJS.Helpers(object, extraHelpers || {}));
	};
	extend(EJS.prototype, {
		// ## Scanner
		// Singleton scanner instance for parsing templates. See [scanner.js](scanner.html)
		// for more information.
		//
		// ### Text
		//
		// #### Definitions
		//
		// * `outStart` - Wrapper start text for view function.
		//
		// * `outEnd` - Wrapper end text for view function.
		//
		// * `argNames` - Arguments passed into view function.
		scanner: new can.view.Scanner({
			text: {
				outStart: 'with(_VIEW) { with (_CONTEXT) {',
				outEnd: "}}",
				argNames: '_CONTEXT,_VIEW',
				context: "this"
			},
			// ### Tokens
			//
			// An ordered token registry for the scanner.
			tokens: [
				// Template
				["templateLeft", "<%%"],
				// Right Template
				["templateRight", "%>"],
				// Return Unescaped
				["returnLeft", "<%=="],
				// Return Escaped
				["escapeLeft", "<%="],
				// Comment
				["commentLeft", "<%#"],
				// Evaluate code
				["left", "<%"],
				// Right -> All have same FOR Mustache ...
				["right", "%>"],
				["returnRight", "%>"]
			],
			// ### Helpers
			helpers: [
				{
					// #### name
					// Regex to see if its a func like `()->`.
					name: /\s*\(([\$\w]+)\)\s*->([^\n]*)/,
					// #### fn
					// Evaluate rocket syntax function with correct context.
					fn: function (content) {
						var quickFunc = /\s*\(([\$\w]+)\)\s*->([^\n]*)/,
							parts = content.match(quickFunc);

						return "can.proxy(function(__){var " + parts[1] + "=can.$(__);" + parts[2] + "}, this);";
					}
				}
			],
			// ### transform
			// Transforms the EJS template to add support for shared blocks.
			// Essentially, this breaks up EJS tags into multiple EJS tags
			// if they contained unmatched brackets.
			//
			// For example, this doesn't work:
			//
			// `<% if (1) { %><% if (1) { %> hi <% } } %>`
			//
			// ...without isolated EJS blocks:
			//
			// `<% if (1) { %><% if (1) { %> hi <% } %><% } %>`
			//
			// The result of transforming:
			//
			// `<% if (1) { %><% %><% if (1) { %><% %> hi <% } %><% } %>`
			transform: function (source) {
				return source.replace(/<%([\s\S]+?)%>/gm, function (whole, part) {
					var brackets = [],
						foundBracketPair, i;
					// Look for brackets (for removing self-contained blocks)
					part.replace(/[{}]/gm, function (bracket, offset) {
						brackets.push([
							bracket,
							offset
						]);
					});
					// Remove bracket pairs from the list of replacements
					do {
						foundBracketPair = false;
						for (i = brackets.length - 2; i >= 0; i--) {
							if (brackets[i][0] === '{' && brackets[i + 1][0] === '}') {
								brackets.splice(i, 2);
								foundBracketPair = true;
								break;
							}
						}
					} while (foundBracketPair);
					// Unmatched brackets found, inject EJS tags
					if (brackets.length >= 2) {
						var result = ['<%'],
							bracket, last = 0;
						for (i = 0; bracket = brackets[i]; i++) {
							result.push(part.substring(last, last = bracket[1]));
							if (bracket[0] === '{' && i < brackets.length - 1 || bracket[0] === '}' && i > 0) {
								result.push(bracket[0] === '{' ? '{ %><% ' : ' %><% }');
							} else {
								result.push(bracket[0]);
							}
							++last;
						}
						result.push(part.substring(last), '%>');
						return result.join('');
					}
					// Otherwise return the original
					else {
						return '<%' + part + '%>';
					}
				});
			}
		})
	});

	// ## Helpers
	// By adding functions to can.EJS.Helpers.prototype, those functions will be available in the
	// views.
	//
	// The following helper converts a given string to upper case:
	//
	//     can.EJS.Helpers.prototype.toUpper = function(params) {
	//       return params.toUpperCase();
	//     }

	// Use it like this in any EJS template:

	// `<%= toUpper('javascriptmvc') %>`

	// To access the current DOM element return a function that takes the element as a parameter:

	//     can.EJS.Helpers.prototype.upperHtml = function(params) {
	//       return function(el) {
	//         $(el).html(params.toUpperCase());
	//       }
	//     }

	// In your EJS view you can then call the helper on an element tag:

	// `<div <%= upperHtml('javascriptmvc') %>></div>`
	EJS.Helpers = function (data, extras) {
		this._data = data;
		this._extras = extras;
		extend(this, extras);
	};

	EJS.Helpers.prototype = {
		// TODO Deprecated!!
		list: function (list, cb) {
			can.each(list, function (item, i) {
				cb(item, i, list);
			});
		},
		each: function (list, cb) {
			// Normal arrays don't get live updated
			if (can.isArray(list)) {
				this.list(list, cb);
			} else {
				can.view.lists(list, cb);
			}
		}
	};
	// Options for `steal`'s build.
	can.view.register({
		suffix: 'ejs',
		script: function (id, src) {
			return 'can.EJS(function(_CONTEXT,_VIEW) { ' + new EJS({
				text: src,
				name: id
			})
				.template.out + ' })';
		},
		renderer: function (id, text) {
			return EJS({
				text: text,
				name: id
			});
		}
	});
	return can;
});
<|endoftext|>


<commit_before>function timer(table, doc, time, howmany) {

}

module.exports = timer;
<commit_msg>Variables  / JSdocs / start<commit_after>const ms   = require('ms');
const time = require('moment');

/**
* @param {String} time - the unformatted time of the punishment
* @param {String} table - what table to look into
* @param {String} user - the selected user ID
*/
async function timer(time, table, user) {
  /*
  * Get the inserted time of the user from the database.
  */
  let userObj = await r.table(table).filter({userID : user}).run()[0];

}

module.exports = timer;
<|endoftext|>


<commit_before>/* jshint esversion: 6 */

(function(root, factory) {
  if (typeof define === "function" && define.amd) {
    define([], factory);
  } else if (typeof module === "object" && module.exports) {
    module.exports = factory();
  } else {
    root.CSV = factory();
  }
}(this, function() {
  'use strict';

  /* =========================================
   * Constants ===============================
   * ========================================= */
  var CELL_DELIMITERS = [",", ";", "\t", "|", "^"];
  var LINE_DELIMITERS = ["\r\n", "\r", "\n"];

  var STANDARD_DECODE_OPTS = {
    skip: 0,
    limit: false,
    header: false,
    cast: false
  };

  var STANDARD_ENCODE_OPTS = {
    delimiter: CELL_DELIMITERS[0],
    newline: LINE_DELIMITERS[0],
    skip: 0,
    limit: false,
    header: false
  };

  var quoteMark = '"';
  var doubleQuoteMark = '""';
  var quoteRegex = /"/g;

  /* =========================================
   * Utility Functions =======================
   * ========================================= */
  function assign() {
    var args = Array.prototype.slice.call(arguments);
    var base = args[0];
    var rest = args.slice(1);
    for (var i = 0, len = rest.length; i < len; i++) {
      for (var attr in rest[i]) {
        base[attr] = rest[i][attr];
      }
    }
    return base;
  }

  function map(collection, fn) {
    var results = [];
    for (var i = 0, len = collection.length; i < len; i++) {
      results[i] = fn(collection[i], i);
    }
    return results;
  }

  var getType = function (obj) { return Object.prototype.toString.call(obj).slice(8, -1); };

  var getLimit = function (limit, len) { return limit === false ? len : limit; };

  var getter = function (index) { return ("d[" + index + "]"); };

  var getterCast = function (value, index) {
    if (!isNaN(Number(value))) {
      return ("Number(" + (getter(index)) + ")");
    } else if (value == "false" || value == "true" || value == "t" || value == "f") {
      return ((getter(index)) + " === \"true\" || " + (getter(index)) + " === \"t\"");
    } else {
      return getter(index);
    }
  };

  function buildObjectConstructor(fields, sample, cast) {
    var body = ["let object = new Object()"];
    var setter = function (attr) { return ("object[" + (JSON.stringify(attr)) + "] = "); };
    if (cast === true) {
      body = body.concat(map(fields, function (attr, idx) { return setter(attr) + getterCast(sample[idx], idx); }));
    } else {
      body = body.concat(map(fields, function (attr, idx) { return setter(attr) + getter(idx); }));
    }
    body.push("return object;");
    return new Function("d", body.join(";\n"));
  }

  function buildArrayConstructor(sample, cast) {
    var body = ["let row = new Array(" + sample.length + ")"];
    var setter = function (idx) { return ("row[" + idx + "] = "); };
    if (cast === true) {
      body = body.concat(map(sample, function (val, idx) { return setter(idx) + getterCast(val, idx); }));
    } else {
      body = body.concat(map(sample, function (_, idx) { return setter(idx) + getter(idx); }));
    }
    body.push("return row;");
    return new Function("d", body.join(";\n"));
  }

  function frequency(coll, needle, limit) {
    if ( limit === void 0 ) limit = false;

    var count = 0;
    var lastIndex = 0;
    var maxIndex = getLimit(limit, coll.length);

    while (lastIndex < maxIndex) {
      lastIndex = coll.indexOf(needle, lastIndex);
      if (lastIndex === -1) break;
      count++;
    }

    return count;
  }

  function mostFrequent(coll, needles, limit) {
    var max = 0;
    var detected;

    for (var cur = needles.length - 1; cur >= 0; cur--) {
      if (frequency(coll, needles[cur], limit) > max) {
        detected = needles[cur];
      }
    }

    return detected || needles[0];
  }

  function unsafeParse(text, opts, fn) {
    var lines = text.split(opts.newline);

    if (opts.skip > 0) {
      lines.splice(opts.skip);
    }

    var fields;
    var constructor;

    function cells(line) {
      return line.split(opts.delimiter);
    }

    if (opts.header) {
      if (opts.header === true) {
        fields = cells(lines.shift());
      } else if (getType(opts.header) === "Array") {
        fields = opts.header;
      }

      constructor = buildObjectConstructor(fields, cells(lines[0]), opts.cast);
    } else {
      constructor = buildArrayConstructor(cells(lines[0]), opts.cast);
    }

    for (var cur = 0, lim = getLimit(opts.limit, lines.length); cur < lim; cur++) {
      var row = cells(lines[cur]);
      if (row.length > 1) {
        fn(constructor(row));
      }
    }

    return true;
  }

  function safeParse(text, opts, fn) {
    var delimiter = opts.delimiter;
    var newline = opts.newline;

    var lines = text.split(newline);
    if (opts.skip > 0) {
      lines.splice(opts.skip);
    }

    // for (let cur = 0, lim = getLimit(opts.limit, lines.length); cur < lim; cur++) {
    //   let line = lines[cur];
    //   if (frequency(line, quoteMark) % 2 !== 0) {
    //     line += lines.splice(cur + 1, 1)[0];
    //     cur -= 1;
    //     continue;
    //   }
    //   let cells = line.split(delimiter);
    //   for (let cell = 0, len = cells.length; cell < len; cell++) {
    //     if (frequency(cell, quoteMark) % 2 !== 0) {
    //       cell += cells.splice(cur + 1, 1)[0];
    //       cell -= 1;
    //       continue;
    //     }
    //   }
    //   fn(cells);
    // }

    return true;
  }

  function encodeCells(line, delimiter, newline) {
    var row = line.slice(0);
    for (var i = 0, len = row.length; i < len; i++) {
      if (row[i].indexOf(quoteMark) !== -1) {
        row[i] = row[i].replace(quoteRegex, doubleQuoteMark);
      }
      if (row[i].indexOf(delimiter !== -1) || row[i].indexOf(newline) !== -1) {
        row[i] = quoteMark + row[i] + quoteMark;
      }
    }
    return row.join(delimiter);
  }

  function encodeArrays(coll, opts, fn) {
    var delimiter = opts.delimiter;
    var newline = opts.newline;

    if (opts.header && getType(opts.header) === "Array") {
      fn(encodeCells(opts.header, delimiter, newline));
    }

    for (var cur = 0, lim = getLimit(opts.limit, coll.length); cur < lim; cur++) {
      fn(encodeCells(coll[cur], delimiter, newline));
    }

    return true;
  }

  function encodeObjects(coll, opts, fn) {
    var delimiter = opts.delimiter;
    var newline = opts.newline;
    var header;
    var row;

    header = [];
    row = [];
    for (var key in coll[0]) {
      header.push(key);
      row.push(coll[0][key]);
    }

    if (opts.header === true) {
      fn(encodeCells(header, delimiter, newline));
    } else if (getType(opts.header) === "Array") {
      fn(encodeCells(opts.header, delimiter, newline));
    }

    fn(encodeCells(row, delimiter));

    for (var cur = 1, lim = getLimit(opts.limit, coll.length); cur < lim; cur++) {
      row = [];
      for (var key$1 = 0, len = header.length; key$1 < len; key$1++) {
        row.push(coll[cur][header[key$1]]);
      }
      fn(encodeCells(row, delimiter, newline));
    }

    return true;
  }

  var CSV = {};

  CSV.parse = function parse(text, opts, fn) {
    var rows;

    if (getType(opts) === "Function") {
      fn = opts;
      opts = {};
    } else if (getType(fn) !== "Function") {
      rows = [];
      fn = rows.push.bind(rows);
    }

    opts = assign({}, STANDARD_DECODE_OPTS, opts);

    if (!opts.delimiter || !opts.newline) {
      var limit = Math.min(48, Math.floor(text.length / 20), text.length);
      opts.delimiter = opts.delimiter || mostFrequent(text, CELL_DELIMITERS, limit);
      opts.newline = opts.newline || mostFrequent(text, LINE_DELIMITERS, limit);
    }

    return (text.indexOf(quoteMark) === -1 ? unsafeParse : safeParse)(text, opts, fn) &&
           (rows.length > 0 ? rows : true);
  };

  CSV.encode = function encode(coll, opts, fn) {
    var lines;

    if (getType(opts) === "Function") {
      fn = opts;
      opts = {};
    } else if (getType(fn) !== "Function") {
      lines = [];
      fn = lines.push.bind(lines);
    }

    opts = assign({}, STANDARD_ENCODE_OPTS, opts);

    if (opts.skip > 0) {
      coll = coll.slice(opts.skip);
    }

    return (getType(coll[0]) === "Array" ? encodeArrays : encodeObjects)(coll, opts, fn) &&
           (lines.length > 0 ? lines.join(opts.newline) : true);
  };

  return CSV;
}));

<commit_msg>Update csv.js<commit_after>/* jshint esversion: 6 */

(function(root, factory) {
  if (typeof define === "function" && define.amd) {
    define([], factory);
  } else if (typeof module === "object" && module.exports) {
    module.exports = factory();
  } else {
    root.CSV = factory();
  }
}(this, function() {
  'use strict';

  /* =========================================
   * Constants ===============================
   * ========================================= */
  var CELL_DELIMITERS = [",", ";", "\t", "|", "^"];
  var LINE_DELIMITERS = ["\r\n", "\r", "\n"];

  var STANDARD_DECODE_OPTS = {
    skip: 0,
    limit: false,
    header: false,
    cast: false
  };

  var STANDARD_ENCODE_OPTS = {
    delimiter: CELL_DELIMITERS[0],
    newline: LINE_DELIMITERS[0],
    skip: 0,
    limit: false,
    header: false
  };

  var quoteMark = '"';
  var doubleQuoteMark = '""';
  var quoteRegex = /"/g;

  /* =========================================
   * Utility Functions =======================
   * ========================================= */
  function assign() {
    var args = Array.prototype.slice.call(arguments);
    var base = args[0];
    var rest = args.slice(1);
    for (var i = 0, len = rest.length; i < len; i++) {
      for (var attr in rest[i]) {
        base[attr] = rest[i][attr];
      }
    }
    return base;
  }

  function map(collection, fn) {
    var results = [];
    for (var i = 0, len = collection.length; i < len; i++) {
      results[i] = fn(collection[i], i);
    }
    return results;
  }

  var getType = function (obj) { return Object.prototype.toString.call(obj).slice(8, -1); };

  var getLimit = function (limit, len) { return limit === false ? len : limit; };

  var getter = function (index) { return ("d[" + index + "]"); };

  var getterCast = function (value, index) {
    if (!isNaN(Number(value))) {
      return ("Number(" + (getter(index)) + ")");
    } else if (value == "false" || value == "true" || value == "t" || value == "f") {
      return ((getter(index)) + " === \"true\" || " + (getter(index)) + " === \"t\"");
    } else {
      return getter(index);
    }
  };

  function buildObjectConstructor(fields, sample, cast) {
    var body = ["let object = new Object()"];
    var setter = function (attr) { return ("object[" + (JSON.stringify(attr)) + "] = "); };
    if (cast === true) {
      body = body.concat(map(fields, function (attr, idx) { return setter(attr) + getterCast(sample[idx], idx); }));
    } else {
      body = body.concat(map(fields, function (attr, idx) { return setter(attr) + getter(idx); }));
    }
    body.push("return object;");
    return new Function("d", body.join(";\n"));
  }

  function buildArrayConstructor(sample, cast) {
    var body = ["let row = new Array(" + sample.length + ")"];
    var setter = function (idx) { return ("row[" + idx + "] = "); };
    if (cast === true) {
      body = body.concat(map(sample, function (val, idx) { return setter(idx) + getterCast(val, idx); }));
    } else {
      body = body.concat(map(sample, function (_, idx) { return setter(idx) + getter(idx); }));
    }
    body.push("return row;");
    return new Function("d", body.join(";\n"));
  }

  function frequency(coll, needle, limit) {
    if ( limit === void 0 ) limit = false;

    var count = 0;
    var lastIndex = 0;
    var maxIndex = getLimit(limit, coll.length);

    while (lastIndex < maxIndex) {
      lastIndex = coll.indexOf(needle, lastIndex);
      if (lastIndex === -1) break;
      count++;
    }

    return count;
  }

  function mostFrequent(coll, needles, limit) {
    var max = 0;
    var detected;

    for (var cur = needles.length - 1; cur >= 0; cur--) {
      if (frequency(coll, needles[cur], limit) > max) {
        detected = needles[cur];
      }
    }

    return detected || needles[0];
  }

  function unsafeParse(text, opts, fn) {
    var lines = text.split(opts.newline);

    if (opts.skip > 0) {
      lines.splice(opts.skip);
    }

    var fields;
    var constructor;

    function cells(line) {
      return line.split(opts.delimiter);
    }

    if (opts.header) {
      if (opts.header === true) {
        fields = cells(lines.shift());
      } else if (getType(opts.header) === "Array") {
        fields = opts.header;
      }

      constructor = buildObjectConstructor(fields, cells(lines[0]), opts.cast);
    } else {
      constructor = buildArrayConstructor(cells(lines[0]), opts.cast);
    }

    for (var cur = 0, lim = getLimit(opts.limit, lines.length); cur < lim; cur++) {
      var row = cells(lines[cur]);
      if (row.length > 1) {
        fn(constructor(row));
      }
    }

    return true;
  }

  function safeParse(text, opts, fn) {
    var delimiter = opts.delimiter;
    var newline = opts.newline;

    var lines = text.split(newline);
    if (opts.skip > 0) {
      lines.splice(opts.skip);
    }

    // for (let cur = 0, lim = getLimit(opts.limit, lines.length); cur < lim; cur++) {
    //   let line = lines[cur];
    //   if (frequency(line, quoteMark) % 2 !== 0) {
    //     line += lines.splice(cur + 1, 1)[0];
    //     cur -= 1;
    //     continue;
    //   }
    //   let cells = line.split(delimiter);
    //   for (let cell = 0, len = cells.length; cell < len; cell++) {
    //     if (frequency(cell, quoteMark) % 2 !== 0) {
    //       cell += cells.splice(cur + 1, 1)[0];
    //       cell -= 1;
    //       continue;
    //     }
    //   }
    //   fn(cells);
    // }

    return true;
  }

  function encodeCells(line, delimiter, newline) {
    var row = line.slice(0);
    for (var i = 0, len = row.length; i < len; i++) {
      if (row[i].indexOf(quoteMark) !== -1) {
        row[i] = row[i].replace(quoteRegex, doubleQuoteMark);
      }
      if (row[i].indexOf(delimiter) !== -1 || row[i].indexOf(newline) !== -1) {
        row[i] = quoteMark + row[i] + quoteMark;
      }
    }
    return row.join(delimiter);
  }

  function encodeArrays(coll, opts, fn) {
    var delimiter = opts.delimiter;
    var newline = opts.newline;

    if (opts.header && getType(opts.header) === "Array") {
      fn(encodeCells(opts.header, delimiter, newline));
    }

    for (var cur = 0, lim = getLimit(opts.limit, coll.length); cur < lim; cur++) {
      fn(encodeCells(coll[cur], delimiter, newline));
    }

    return true;
  }

  function encodeObjects(coll, opts, fn) {
    var delimiter = opts.delimiter;
    var newline = opts.newline;
    var header;
    var row;

    header = [];
    row = [];
    for (var key in coll[0]) {
      header.push(key);
      row.push(coll[0][key]);
    }

    if (opts.header === true) {
      fn(encodeCells(header, delimiter, newline));
    } else if (getType(opts.header) === "Array") {
      fn(encodeCells(opts.header, delimiter, newline));
    }

    fn(encodeCells(row, delimiter));

    for (var cur = 1, lim = getLimit(opts.limit, coll.length); cur < lim; cur++) {
      row = [];
      for (var key$1 = 0, len = header.length; key$1 < len; key$1++) {
        row.push(coll[cur][header[key$1]]);
      }
      fn(encodeCells(row, delimiter, newline));
    }

    return true;
  }

  var CSV = {};

  CSV.parse = function parse(text, opts, fn) {
    var rows;

    if (getType(opts) === "Function") {
      fn = opts;
      opts = {};
    } else if (getType(fn) !== "Function") {
      rows = [];
      fn = rows.push.bind(rows);
    }

    opts = assign({}, STANDARD_DECODE_OPTS, opts);

    if (!opts.delimiter || !opts.newline) {
      var limit = Math.min(48, Math.floor(text.length / 20), text.length);
      opts.delimiter = opts.delimiter || mostFrequent(text, CELL_DELIMITERS, limit);
      opts.newline = opts.newline || mostFrequent(text, LINE_DELIMITERS, limit);
    }

    return (text.indexOf(quoteMark) === -1 ? unsafeParse : safeParse)(text, opts, fn) &&
           (rows.length > 0 ? rows : true);
  };

  CSV.encode = function encode(coll, opts, fn) {
    var lines;

    if (getType(opts) === "Function") {
      fn = opts;
      opts = {};
    } else if (getType(fn) !== "Function") {
      lines = [];
      fn = lines.push.bind(lines);
    }

    opts = assign({}, STANDARD_ENCODE_OPTS, opts);

    if (opts.skip > 0) {
      coll = coll.slice(opts.skip);
    }

    return (getType(coll[0]) === "Array" ? encodeArrays : encodeObjects)(coll, opts, fn) &&
           (lines.length > 0 ? lines.join(opts.newline) : true);
  };

  return CSV;
}));

<|endoftext|>


<commit_before>var Analyst = Analyst || {};

(function(A, $) {

	A.app = {};

	A.app.instance = new Backbone.Marionette.Application();

	A.app.instance.addRegions({
		appRegion: "#app"
	});

	A.app.instance.addInitializer(function(options){

		A.app.user = new A.models.User({id:"self"});
		A.app.user.fetch();

		A.app.projects  = new A.models.Projects();

		A.app.controller =  new A.app.AppController();

		A.app.appRouter = new A.app.Router({controller: A.app.controller});

		A.app.projects.fetch({reset: true, success: A.app.controller.initProjects});

		if( ! Backbone.History.started) Backbone.history.start();

	});

	A.app.Router = Marionette.AppRouter.extend({
  		appRoutes: {
    			':project/:x/:y/:z(/:namespace/*subroute)': 'invokeSubRoute',
			'create-project': 'invokeSubRoute',
			'home': 'index',
			'': 'index'
		}
	});

	A.app.AppController = Marionette.Controller.extend({

		index: function(options) {
			A.app.main = new A.app.Main();

			A.app.instance.appRegion.show(A.app.main);
			A.app.main.showWelcome();
		},

		invokeSubRoute: function(project, x, y, z, namespace, subroute) {

		    this.setProject(project);

			if(!A.app.main) {
				A.app.main = new A.app.Main();

				A.app.instance.appRegion.show(A.app.main);
			}

			this.setMap(x, y, z);

			if(namespace)
				this.setTab(namespace);

		},

		setMap : function(x,y,z) {
			this.x = x;
			this.y = y;
			this.z = z;

			A.map.setView(new L.LatLng(y,x), z);

			this.updateNav(true);
		},

		initProjects : function() {
			A.app.controller.setProject();
		},

		setProject : function(project) {

			if(project)
				A.app.selectedProject = project;

			if(!A.app.selectedProject)
				return;

			A.app.instance.vent.trigger("setSelectedProject");

			if(A.app.projects) {
				var p = A.app.projects.get(project);
				if(p) {
					this.setMap(p.get('defaultLon'), p.get('defaultLat'), p.get('defaultZoom'));
				}
			}

			this.updateNav(true);
		},

		setTab : function(tab) {

			this.selectedTab = tab;
			this.updateNav(true);

			A.app.instance.vent.trigger("setSelectedTab", this.selectedTab);

			A.app.main.closeSidePanel();

			if(this.selectedTab == "transport-data") {
				var transportDataPanel = new A.transportData.DataLayout();
				A.app.main.showSidePanel(transportDataPanel);
			}
			else if(this.selectedTab == "spatial-data-pointsets") {
				var pointSetDataPanel = new A.spatialData.PointSetDataLayout();
				A.app.main.showSidePanel(pointSetDataPanel);
			}
			else if(this.selectedTab == "spatial-data-shapefiles") {
				var pointSetDataPanel = new A.spatialData.ShapefileDataLayout();
				A.app.main.showSidePanel(pointSetDataPanel);
			}
			else if(this.selectedTab == "analysis-single") {
				var analaysisPanel = new A.analysis.AnalysisSinglePointLayout();
				A.app.main.showSidePanel(analaysisPanel);
			}
			else if(this.selectedTab == "analysis-regional") {
				var analaysisPanel = new A.analysis.AnalysisMultiPointLayout();
				A.app.main.showSidePanel(analaysisPanel);
			}
			else if(this.selectedTab == "create-project") {
				var createProjectPanel = new A.project.ProjectCreateView();
				A.app.main.showSidePanel(createProjectPanel);
			}
			else if(this.selectedTab == "project-settings") {
				var createProjectPanel = new A.project.ProjectCreateView({id: A.app.selectedProject});
				A.app.main.showSidePanel(createProjectPanel);
			}
			else if(this.selectedTab == "manage-users") {
				var manageUsersView = new A.app.ManageUsersView();
				A.app.main.showSidePanel(manageUsersView);
			}

		},

		updateNav : function(replace) {

			if(A.app.selectedProject) {
				var baseUrl = '/' + A.app.selectedProject + '/' + this.x  + '/' + this.y  + '/' +  this.z;

				if(this.selectedTab)
					baseUrl = baseUrl + '/' + this.selectedTab + "/";

				A.app.appRouter.navigate(baseUrl, {replace: replace});
			}
		}
	});

	A.app.Main = Marionette.Layout.extend({

		template: Handlebars.getTemplate('app', 'app-main'),

		regions: {
			appNav: 			"#app-nav",
			appSidePanel:       "#app-side-panel",
			appCenterPanel:     "#app-center-panel"
		},

		initialize : function() {
			var _this = this;

			A.app.instance.vent.on("closeSidePanel", function(){
				_this.closeSidePanel();
			});

		},

		onRender : function() {

			// Get rid of that pesky wrapping-div.
    			// Assumes 1 child element present in template.
    			this.$el = this.$el.children();

			this.$el.unwrap();
			this.setElement(this.$el);

			A.app.nav = new A.app.Nav();

			this.appNav.show(A.app.nav);

		},

		showSidePanel : function (mainLayout) {
			this.$('#app-side-panel').show();
			this.appSidePanel.show(mainLayout);

		},

		closeSidePanel : function() {
			this.appSidePanel.close();
			this.$('#app-side-panel').hide();
		},

		showWelcome : function() {
			var welcomeLayout = new A.app.Welcome();

			this.$('#app-side-panel').show();
			this.appSidePanel.show(welcomeLayout);
		},

		onShow: function() {

			A.map = L.map(this.$("#app-map")[0], { loadingControl: true,  zoomControl: false }).setView([0, -80.00], 4);

			L.tileLayer('http://{s}.tiles.mapbox.com/v3/conveyal.hml987j0/{z}/{x}/{y}.png', {
					attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
					maxZoom: 18
				}).addTo(A.map);

			new L.control.zoom({position: 'bottomleft'}).addTo(A.map);

			A.map.on("moveend", function(evt) {

				if(A.map.getCenter().lng != -80 && A.map.getCenter().lat != 0)
					A.app.controller.setMap(A.map.getCenter().lng, A.map.getCenter().lat, A.map.getZoom());
			});
		}
	});

	A.app.Nav = Marionette.Layout.extend({

		template: Handlebars.getTemplate('app', 'app-nav'),

		regions : {
			projectDropdown: "#projectDropdown",
			userDropdown: "#userDropdown",
		},

		events : {
			'click #transportDataTab' : 'clickTransportData',
			'click #spatialDataTabShapefilesListItem' : 'clickSpatialDataTabShapefilesListItem',
			'click #spatialDataTabPointSetsListItem' : 'clickSpatialDataTabPointSetsListItem',
			'click #analysisTabSinglePoint' : 'clickAnalysisTabSinglePoint',
			'click #analysisTabRegional' : 'clickAnalysisTabRegional',
			'click #projectSettingsTab' : 'clickProjectSettings',
			'click #userDropdownManageUsers' : 'clickManageUsers'
		},

		initialize : function() {

			var _this = this;
			A.app.instance.vent.on("setSelectedProject", function(){
			  _this.render();
			});

			A.app.instance.vent.on("setSelectedTab", function(tab){
			_this.activeTab = tab;
			_this.render();
			});
		},

		onRender : function() {

			// Get rid of that pesky wrapping-div.
			// Assumes 1 child element present in template.
			this.$el = this.$el.children();

			this.$el.unwrap();
			this.setElement(this.$el);

			var projectDropdownView = new A.app.ProjectListView({collection: A.app.projects});

			var userDropdownView = new A.app.UserMenuView({model: A.app.user});

			this.projectDropdown.show(projectDropdownView);
			this.userDropdown.show(userDropdownView);

		},

		clickTransportData : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("transport-data");
		},

		clickSpatialDataTabShapefilesListItem : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("spatial-data-shapefiles");
		},

		clickSpatialDataTabPointSetsListItem : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("spatial-data-pointsets");
		},

		clickAnalysisTabSinglePoint : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("analysis-single");
		},

		clickAnalysisTabRegional : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("analysis-regional");
		},

		clickProjectSettings : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("project-settings");
		},

		clickManageUsers : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("manage-users");
		},

		templateHelpers: {
			selectedProject : function () {
				if(A.app.selectedProject != null)
					return true;
				else
					return false;
			},
			transportDataActive : function () {
					if(this.activeTab == "transport-data")
						return true;
					else
						return false;
			},
			spatialDataActive : function () {
					if(this.activeTab == "spatial-data-shapefiles" || this.activeTab == "spatial-data-pointsets")
						return true;
					else
						return false;
			},
			analysisActive : function () {
					if(this.activeTab == "analysis-single" ||  this.activeTab == "analysis-regional")
						return true;
					else
						return false;
			},
			settingsActive : function () {
					if(this.activeTab == "project-settings")
						return true;
					else
						return false;
			},
			settingsActive : function () {
					if(this.activeTab == "manage-users")
						return true;
					else
						return false;
			},
		}
	});

	A.app.UserMenuView = Backbone.Marionette.ItemView.extend({

		template: Handlebars.getTemplate('app', 'app-user-menu'),
		tagName: 'li',

		initialize: function () {

			this.model.on('change', this.render);
		},

		onRender : function() {
			// Get rid of that pesky wrapping-div.
			// Assumes 1 child element present in template.
			this.$el = this.$el.children();

			this.$el.unwrap();
			this.setElement(this.$el);
		}

	});

	A.app.ManageUsersListItem = Backbone.Marionette.ItemView.extend({

		template: Handlebars.getTemplate('app', 'app-manage-users-list-item'),
		tagName: 'li',

		initialize: function () {

			this.model.on('change', this.render);
		},

		onRender: function () {
		// Get rid of that pesky wrapping-div
		// Assumes 1 child element present in template.
		this.$el = this.$el.children();
		// Unwrap the element to prevent infinitely
		// nesting elements during re-render.
		this.$el.unwrap();
		this.setElement(this.$el);
	}

	});

	A.app.ManageUsersView = Backbone.Marionette.CompositeView.extend({

		template: Handlebars.getTemplate('app', 'app-manage-users'),
		itemView: A.app.ManageUsersListItem,

		initialize: function () {

			this.collection = new A.models.Users();
			this.collection.fetch();
		}

	});

	A.app.ProjectListItemView = Backbone.Marionette.ItemView.extend({

		template: Handlebars.getTemplate('project', 'project-list-item-template'),
		tagName: 'li',

		initialize: function () {

			this.model.on('change', this.render);
		}

	});

	A.app.ProjectListView = Backbone.Marionette.CompositeView.extend({

		template: Handlebars.getTemplate('project', 'project-list-template'),
		itemView: A.app.ProjectListItemView,

		events : {
			'click .selectProject': 'selectProject',
			'click #createNewProject' : 'createNewProject'
		},

		initialize : function() {
		},

		templateHelpers: {
			selectedProject : function () {
				var selectedProject = this.collection.get(A.app.selectedProject);
				if(selectedProject != null)
					return selectedProject.get("name");
				else
					return false;
			}
		},

		onRender : function() {
			// Get rid of that pesky wrapping-div.
			// Assumes 1 child element present in template.
			this.$el = this.$el.children();

			this.$el.unwrap();
			this.setElement(this.$el);
		},

		selectProject : function(evt) {
			evt.preventDefault();
			var id = $(evt.target).data("id");
			A.app.controller.setProject(id);
		},

		createNewProject : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("create-project");
		},

		appendHtml: function(collectionView, itemView){
			collectionView.$("#projectList").prepend(itemView.el);
		}
	});

	A.app.SidePanel = Marionette.Layout.extend({

		template: Handlebars.getTemplate('app', 'app-side-panel'),

		regions: {
			main : '#main'
		},

		initialize : function (options) {

			this.mainLayout = options.mainLayout;
		},

		onShow : function() {

			this.main.show(this.mainLayout);

		}
	});

	A.app.Welcome = Marionette.Layout.extend({

		template: Handlebars.getTemplate('docs', 'docs-welcome', 'en'),

		events : {
			'click #startTour': 'startTour'
		},

		startTour : function(evt) {
			A.app.tour = new Tour({

			steps: [ {
					element: "#transportDataTab",
					title: "Build Transport Scenarios",
					content: "Create a transport scenario by clicking \"Add\" above and uploading a GTFS feed, or create a GTFS feed using TransitMix or TransitWand."
				}, {
					element: "#spatialDataTab",
					title: "Manage Spatial Data",
					content: "Spatial data sets allow measurement of access to spatially distributed characteristics like population or jobs. Create one by clicking \"Add\" above and upload a Shapefile."
			}]});

			// Initialize the tour
			A.app.tour.init();

			// Start the tour
			A.app.tour.start(true);
		}

	});

})(Analyst, jQuery);

$(document).ready(function() {

	Analyst.app.instance.start();

});
<commit_msg>add scale to map.<commit_after>var Analyst = Analyst || {};

(function(A, $) {

	A.app = {};

	A.app.instance = new Backbone.Marionette.Application();

	A.app.instance.addRegions({
		appRegion: "#app"
	});

	A.app.instance.addInitializer(function(options){

		A.app.user = new A.models.User({id:"self"});
		A.app.user.fetch();

		A.app.projects  = new A.models.Projects();

		A.app.controller =  new A.app.AppController();

		A.app.appRouter = new A.app.Router({controller: A.app.controller});

		A.app.projects.fetch({reset: true, success: A.app.controller.initProjects});

		if( ! Backbone.History.started) Backbone.history.start();

	});

	A.app.Router = Marionette.AppRouter.extend({
  		appRoutes: {
    			':project/:x/:y/:z(/:namespace/*subroute)': 'invokeSubRoute',
			'create-project': 'invokeSubRoute',
			'home': 'index',
			'': 'index'
		}
	});

	A.app.AppController = Marionette.Controller.extend({

		index: function(options) {
			A.app.main = new A.app.Main();

			A.app.instance.appRegion.show(A.app.main);
			A.app.main.showWelcome();
		},

		invokeSubRoute: function(project, x, y, z, namespace, subroute) {

		    this.setProject(project);

			if(!A.app.main) {
				A.app.main = new A.app.Main();

				A.app.instance.appRegion.show(A.app.main);
			}

			this.setMap(x, y, z);

			if(namespace)
				this.setTab(namespace);

		},

		setMap : function(x,y,z) {
			this.x = x;
			this.y = y;
			this.z = z;

			A.map.setView(new L.LatLng(y,x), z);

			this.updateNav(true);
		},

		initProjects : function() {
			A.app.controller.setProject();
		},

		setProject : function(project) {

			if(project)
				A.app.selectedProject = project;

			if(!A.app.selectedProject)
				return;

			A.app.instance.vent.trigger("setSelectedProject");

			if(A.app.projects) {
				var p = A.app.projects.get(project);
				if(p) {
					this.setMap(p.get('defaultLon'), p.get('defaultLat'), p.get('defaultZoom'));
				}
			}

			this.updateNav(true);
		},

		setTab : function(tab) {

			this.selectedTab = tab;
			this.updateNav(true);

			A.app.instance.vent.trigger("setSelectedTab", this.selectedTab);

			A.app.main.closeSidePanel();

			if(this.selectedTab == "transport-data") {
				var transportDataPanel = new A.transportData.DataLayout();
				A.app.main.showSidePanel(transportDataPanel);
			}
			else if(this.selectedTab == "spatial-data-pointsets") {
				var pointSetDataPanel = new A.spatialData.PointSetDataLayout();
				A.app.main.showSidePanel(pointSetDataPanel);
			}
			else if(this.selectedTab == "spatial-data-shapefiles") {
				var pointSetDataPanel = new A.spatialData.ShapefileDataLayout();
				A.app.main.showSidePanel(pointSetDataPanel);
			}
			else if(this.selectedTab == "analysis-single") {
				var analaysisPanel = new A.analysis.AnalysisSinglePointLayout();
				A.app.main.showSidePanel(analaysisPanel);
			}
			else if(this.selectedTab == "analysis-regional") {
				var analaysisPanel = new A.analysis.AnalysisMultiPointLayout();
				A.app.main.showSidePanel(analaysisPanel);
			}
			else if(this.selectedTab == "create-project") {
				var createProjectPanel = new A.project.ProjectCreateView();
				A.app.main.showSidePanel(createProjectPanel);
			}
			else if(this.selectedTab == "project-settings") {
				var createProjectPanel = new A.project.ProjectCreateView({id: A.app.selectedProject});
				A.app.main.showSidePanel(createProjectPanel);
			}
			else if(this.selectedTab == "manage-users") {
				var manageUsersView = new A.app.ManageUsersView();
				A.app.main.showSidePanel(manageUsersView);
			}

		},

		updateNav : function(replace) {

			if(A.app.selectedProject) {
				var baseUrl = '/' + A.app.selectedProject + '/' + this.x  + '/' + this.y  + '/' +  this.z;

				if(this.selectedTab)
					baseUrl = baseUrl + '/' + this.selectedTab + "/";

				A.app.appRouter.navigate(baseUrl, {replace: replace});
			}
		}
	});

	A.app.Main = Marionette.Layout.extend({

		template: Handlebars.getTemplate('app', 'app-main'),

		regions: {
			appNav: 			"#app-nav",
			appSidePanel:       "#app-side-panel",
			appCenterPanel:     "#app-center-panel"
		},

		initialize : function() {
			var _this = this;

			A.app.instance.vent.on("closeSidePanel", function(){
				_this.closeSidePanel();
			});

		},

		onRender : function() {

			// Get rid of that pesky wrapping-div.
    			// Assumes 1 child element present in template.
    			this.$el = this.$el.children();

			this.$el.unwrap();
			this.setElement(this.$el);

			A.app.nav = new A.app.Nav();

			this.appNav.show(A.app.nav);

		},

		showSidePanel : function (mainLayout) {
			this.$('#app-side-panel').show();
			this.appSidePanel.show(mainLayout);

		},

		closeSidePanel : function() {
			this.appSidePanel.close();
			this.$('#app-side-panel').hide();
		},

		showWelcome : function() {
			var welcomeLayout = new A.app.Welcome();

			this.$('#app-side-panel').show();
			this.appSidePanel.show(welcomeLayout);
		},

		onShow: function() {

			A.map = L.map(this.$("#app-map")[0], { loadingControl: true,  zoomControl: false }).setView([0, -80.00], 4);

			L.tileLayer('http://{s}.tiles.mapbox.com/v3/conveyal.hml987j0/{z}/{x}/{y}.png', {
					attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
					maxZoom: 18
				}).addTo(A.map);

			new L.control.scale({position: 'bottomleft', metric: true, imperial: true}).addTo(A.map);

			new L.control.zoom({position: 'bottomleft'}).addTo(A.map);

			A.map.on("moveend", function(evt) {

				if(A.map.getCenter().lng != -80 && A.map.getCenter().lat != 0)
					A.app.controller.setMap(A.map.getCenter().lng, A.map.getCenter().lat, A.map.getZoom());
			});
		}
	});

	A.app.Nav = Marionette.Layout.extend({

		template: Handlebars.getTemplate('app', 'app-nav'),

		regions : {
			projectDropdown: "#projectDropdown",
			userDropdown: "#userDropdown",
		},

		events : {
			'click #transportDataTab' : 'clickTransportData',
			'click #spatialDataTabShapefilesListItem' : 'clickSpatialDataTabShapefilesListItem',
			'click #spatialDataTabPointSetsListItem' : 'clickSpatialDataTabPointSetsListItem',
			'click #analysisTabSinglePoint' : 'clickAnalysisTabSinglePoint',
			'click #analysisTabRegional' : 'clickAnalysisTabRegional',
			'click #projectSettingsTab' : 'clickProjectSettings',
			'click #userDropdownManageUsers' : 'clickManageUsers'
		},

		initialize : function() {

			var _this = this;
			A.app.instance.vent.on("setSelectedProject", function(){
			  _this.render();
			});

			A.app.instance.vent.on("setSelectedTab", function(tab){
			_this.activeTab = tab;
			_this.render();
			});
		},

		onRender : function() {

			// Get rid of that pesky wrapping-div.
			// Assumes 1 child element present in template.
			this.$el = this.$el.children();

			this.$el.unwrap();
			this.setElement(this.$el);

			var projectDropdownView = new A.app.ProjectListView({collection: A.app.projects});

			var userDropdownView = new A.app.UserMenuView({model: A.app.user});

			this.projectDropdown.show(projectDropdownView);
			this.userDropdown.show(userDropdownView);

		},

		clickTransportData : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("transport-data");
		},

		clickSpatialDataTabShapefilesListItem : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("spatial-data-shapefiles");
		},

		clickSpatialDataTabPointSetsListItem : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("spatial-data-pointsets");
		},

		clickAnalysisTabSinglePoint : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("analysis-single");
		},

		clickAnalysisTabRegional : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("analysis-regional");
		},

		clickProjectSettings : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("project-settings");
		},

		clickManageUsers : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("manage-users");
		},

		templateHelpers: {
			selectedProject : function () {
				if(A.app.selectedProject != null)
					return true;
				else
					return false;
			},
			transportDataActive : function () {
					if(this.activeTab == "transport-data")
						return true;
					else
						return false;
			},
			spatialDataActive : function () {
					if(this.activeTab == "spatial-data-shapefiles" || this.activeTab == "spatial-data-pointsets")
						return true;
					else
						return false;
			},
			analysisActive : function () {
					if(this.activeTab == "analysis-single" ||  this.activeTab == "analysis-regional")
						return true;
					else
						return false;
			},
			settingsActive : function () {
					if(this.activeTab == "project-settings")
						return true;
					else
						return false;
			},
			settingsActive : function () {
					if(this.activeTab == "manage-users")
						return true;
					else
						return false;
			},
		}
	});

	A.app.UserMenuView = Backbone.Marionette.ItemView.extend({

		template: Handlebars.getTemplate('app', 'app-user-menu'),
		tagName: 'li',

		initialize: function () {

			this.model.on('change', this.render);
		},

		onRender : function() {
			// Get rid of that pesky wrapping-div.
			// Assumes 1 child element present in template.
			this.$el = this.$el.children();

			this.$el.unwrap();
			this.setElement(this.$el);
		}

	});

	A.app.ManageUsersListItem = Backbone.Marionette.ItemView.extend({

		template: Handlebars.getTemplate('app', 'app-manage-users-list-item'),
		tagName: 'li',

		initialize: function () {

			this.model.on('change', this.render);
		},

		onRender: function () {
		// Get rid of that pesky wrapping-div
		// Assumes 1 child element present in template.
		this.$el = this.$el.children();
		// Unwrap the element to prevent infinitely
		// nesting elements during re-render.
		this.$el.unwrap();
		this.setElement(this.$el);
	}

	});

	A.app.ManageUsersView = Backbone.Marionette.CompositeView.extend({

		template: Handlebars.getTemplate('app', 'app-manage-users'),
		itemView: A.app.ManageUsersListItem,

		initialize: function () {

			this.collection = new A.models.Users();
			this.collection.fetch();
		}

	});

	A.app.ProjectListItemView = Backbone.Marionette.ItemView.extend({

		template: Handlebars.getTemplate('project', 'project-list-item-template'),
		tagName: 'li',

		initialize: function () {

			this.model.on('change', this.render);
		}

	});

	A.app.ProjectListView = Backbone.Marionette.CompositeView.extend({

		template: Handlebars.getTemplate('project', 'project-list-template'),
		itemView: A.app.ProjectListItemView,

		events : {
			'click .selectProject': 'selectProject',
			'click #createNewProject' : 'createNewProject'
		},

		initialize : function() {
		},

		templateHelpers: {
			selectedProject : function () {
				var selectedProject = this.collection.get(A.app.selectedProject);
				if(selectedProject != null)
					return selectedProject.get("name");
				else
					return false;
			}
		},

		onRender : function() {
			// Get rid of that pesky wrapping-div.
			// Assumes 1 child element present in template.
			this.$el = this.$el.children();

			this.$el.unwrap();
			this.setElement(this.$el);
		},

		selectProject : function(evt) {
			evt.preventDefault();
			var id = $(evt.target).data("id");
			A.app.controller.setProject(id);
		},

		createNewProject : function(evt) {
			evt.preventDefault();
			A.app.controller.setTab("create-project");
		},

		appendHtml: function(collectionView, itemView){
			collectionView.$("#projectList").prepend(itemView.el);
		}
	});

	A.app.SidePanel = Marionette.Layout.extend({

		template: Handlebars.getTemplate('app', 'app-side-panel'),

		regions: {
			main : '#main'
		},

		initialize : function (options) {

			this.mainLayout = options.mainLayout;
		},

		onShow : function() {

			this.main.show(this.mainLayout);

		}
	});

	A.app.Welcome = Marionette.Layout.extend({

		template: Handlebars.getTemplate('docs', 'docs-welcome', 'en'),

		events : {
			'click #startTour': 'startTour'
		},

		startTour : function(evt) {
			A.app.tour = new Tour({

			steps: [ {
					element: "#transportDataTab",
					title: "Build Transport Scenarios",
					content: "Create a transport scenario by clicking \"Add\" above and uploading a GTFS feed, or create a GTFS feed using TransitMix or TransitWand."
				}, {
					element: "#spatialDataTab",
					title: "Manage Spatial Data",
					content: "Spatial data sets allow measurement of access to spatially distributed characteristics like population or jobs. Create one by clicking \"Add\" above and upload a Shapefile."
			}]});

			// Initialize the tour
			A.app.tour.init();

			// Start the tour
			A.app.tour.start(true);
		}

	});

})(Analyst, jQuery);

$(document).ready(function() {

	Analyst.app.instance.start();

});
<|endoftext|>