<commit_before>// require('newrelic');
var log4js = require('log4js');
var _ = require('underscore');
var util = require('util');
var fs = require('fs');
var http = require('http');
var path = require('path');
var express = require('express');
var session = require('express-session');
var mongoStore = require('connect-mongo')(session);
var bodyParser = require('body-parser');
var multer = require('multer');
var app = express();
var nodemailer = require('nodemailer');

log4js.configure(path.join(__dirname,'config/log4js.json'));
var logger = log4js.getLogger('server');
logger.setLevel('INFO');

//create an http server
app.server = http.createServer(app);
app.randomHex = function(){
	return new Date().getTime();
};

//import the data layer
var mongoose = require('mongoose');

var config = {
		server: require('./config/server'),
		mail: require('./config/mail'),
		db: require('./config/db')
	};

//import the models
var models = {
		Account: require('./models/Account')(mongoose),
		PlatformApp: require('./models/PlatformApp')(mongoose),
		PlatformSession: require('./models/PlatformSession')(mongoose),
		PlatformFeature: require('./models/PlatformFeature')(mongoose),
		PlatformRole: require('./models/PlatformRole')(mongoose),

		Customer: require('./models/CustomerEntity')(mongoose),
		ProductDirect: require('./models/ProductDirect')(mongoose),
		ProductCard: require('./models/ProductCard')(mongoose),
		ProductPhone: require('./models/ProductPhone')(mongoose),
		Media: require('./models/Media')(mongoose),
		Order: require('./models/Order')(mongoose),
		// OrderCard: require('./models/OrderCard')(mongoose),

		DictPhonePackage: require('./models/DictPhonePackage')(mongoose),
		DictCardPackage: require('./models/DictCardPackage')(mongoose),

		AccountActivity: require('./models/AccountActivity')(mongoose),
		ChannelCategory: require('./models/ChannelCategory')(mongoose),
		ChannelDepartment: require('./models/ChannelDepartment')(mongoose),
		ChannelGrid: require('./models/ChannelGrid')(mongoose),
		ChannelEntity: require('./models/ChannelEntity')(mongoose),
		PageRecommend: require('./models/PageRecommend')(mongoose),
		PromoteEvent: require('./models/PromoteEvent')(mongoose),
		// WoOrder: require('./models/WoOrder')(mongoose),
		WoRevenue: require('./models/WoRevenue')(mongoose),
		GoodsEntity: require('./models/GoodsEntity')(mongoose),
	};

mongoose.connect(config.db.URI,function onMongooseError(err){
	if(err) {
		logger.error('Error: can not open Mongodb.');
		throw err;
	}
});

//express configure
app.set('view engine', 'jade');
app.set('views', __dirname +'/views');

//show origin cookie
// app.use(function(req,res,next){
// 	logger.info('req.cookies:' + JSON.stringify(req.headers.cookie));
// 	next();
// });

app.use(express.static(__dirname + '/public'));
// app.use(express.limit('1mb'));
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(multer()); // for parsing multipart/form-data

//app session
app.sessionSecret = 'it is mime.';
app.sessionStore = new mongoStore({
			url: config.db.URI,
			collection: 'sessions'
		});
app.use(session({
		secret: app.sessionSecret,
		key: 'beyond.sid',
		store: app.sessionStore,
		saveUninitialized: false,
        resave: true
    }));

app.get('/', function(req,res){
	res.render('index.jade',{layout: false});
});

// app.get('/download/:name', function(req,res){
// 	var filename = req.params.name;
// 	if(!fs.existsSync(path.join(__dirname,'public/downloads',filename))){
// 		res.sendStatus(404);
// 		return;
// 	}
// 	var file = path.join(__dirname,'public/downloads',filename);
// 	res.download(file);
// });

//是否登录
app.isLogin = function(req,res,next){
	var grant = req.session.grant;
	if(!_.isEmpty(grant)) return next();
	res.status(401).end();
};

//授权判断中间件
app.grant = function(req,res,next){
	logger.debug('session(grant):' + JSON.stringify(req.session));
	logger.debug('req.path(grant): ' + util.inspect(req.path));
	logger.debug('req.params.id(grant): ' + util.inspect(req.params.id));
	logger.debug('req.method(grant): ' + req.method);
	var path = req.path;
	if((req.method == 'PUT' ||
		req.method == 'DELETE' ||
		req.method == 'GET') && req.params.id){
		var id = path.lastIndexOf('/');
		logger.debug('path.lastIndexOf "/"(grant): ' + id);
		if(id != -1) path = path.slice(0, id);
	}
	logger.debug('route(grant):' + path);

	var grant = req.session.grant || {};
	var features = _.values(grant);
	logger.debug('features(grant): ' + JSON.stringify(features));
	var feature = (_.where(features,{route: path}))[0];
	if(_.isUndefined(feature)) return res.status(401).end();
	logger.debug('current feature(grant):' + JSON.stringify(feature));

	var regexp_path = new RegExp(path,'i');
	logger.debug('regexp_path(grant):' + regexp_path);
	if(regexp_path.test(feature.route)){
		if(req.method == 'POST' && feature.add) return next();
		if(req.method == 'PUT' && feature.update) return next();
		if(req.method == 'DELETE' && feature.remove) return next();
		if(req.method == 'GET' && req.params.id && feature.getOne) return next();
		if(req.method == 'GET' && !(req.parmas && req.params.id) && feature.getMore) return next();
	}
	return res.status(401).end();
};

//设置跨域访问
app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "http://localhost:8000");
    res.header("Access-Control-Allow-Credentials","true");
    res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Set-Cookie");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

//import the routes
fs.readdirSync(path.join(__dirname, 'routes')).forEach(function(file){
	// var routeName = file.substr(0,file.indexOf('.'));
	var routeName = file.substr(0,file.length-3);
	require('./routes/' + routeName)(app,models);
});

app.server.listen(config.server.PORT,function(){
	logger.info(config.server.NAME + ' App is running at '+ config.server.PORT + ' now.');
});<commit_msg>update unicom project .<commit_after>// require('newrelic');
var log4js = require('log4js');
var _ = require('underscore');
var util = require('util');
var fs = require('fs');
var http = require('http');
var path = require('path');
var express = require('express');
var session = require('express-session');
var mongoStore = require('connect-mongo')(session);
var bodyParser = require('body-parser');
var multer = require('multer');
var app = express();
var nodemailer = require('nodemailer');

log4js.configure(path.join(__dirname,'config/log4js.json'));
var logger = log4js.getLogger('server');
logger.setLevel('INFO');

//create an http server
app.server = http.createServer(app);
app.randomHex = function(){
	return new Date().getTime();
};

//import the data layer
var mongoose = require('mongoose');

var config = {
		server: require('./config/server'),
		mail: require('./config/mail'),
		db: require('./config/db')
	};

//import the models
var models = {
		Account: require('./models/Account')(mongoose),
		PlatformApp: require('./models/PlatformApp')(mongoose),
		PlatformSession: require('./models/PlatformSession')(mongoose),
		PlatformFeature: require('./models/PlatformFeature')(mongoose),
		PlatformRole: require('./models/PlatformRole')(mongoose),

		Customer: require('./models/CustomerEntity')(mongoose),
		ProductDirect: require('./models/ProductDirect')(mongoose),
		ProductCard: require('./models/ProductCard')(mongoose),
		ProductPhone: require('./models/ProductPhone')(mongoose),
		Media: require('./models/Media')(mongoose),
		Order: require('./models/Order')(mongoose),
		// OrderCard: require('./models/OrderCard')(mongoose),

		DictPhonePackage: require('./models/DictPhonePackage')(mongoose),
		DictCardPackage: require('./models/DictCardPackage')(mongoose),

		AccountActivity: require('./models/AccountActivity')(mongoose),
		ChannelCategory: require('./models/ChannelCategory')(mongoose),
		ChannelDepartment: require('./models/ChannelDepartment')(mongoose),
		ChannelGrid: require('./models/ChannelGrid')(mongoose),
		ChannelEntity: require('./models/ChannelEntity')(mongoose),
		PageRecommend: require('./models/PageRecommend')(mongoose),
		PromoteEvent: require('./models/PromoteEvent')(mongoose),
		// WoOrder: require('./models/WoOrder')(mongoose),
		WoRevenue: require('./models/WoRevenue')(mongoose),
		GoodsEntity: require('./models/GoodsEntity')(mongoose),
	};

mongoose.connect(config.db.URI,function onMongooseError(err){
	if(err) {
		logger.error('Error: can not open Mongodb.');
		throw err;
	}
});

//express configure
app.set('view engine', 'jade');
app.set('views', __dirname +'/views');

//show origin cookie
// app.use(function(req,res,next){
// 	logger.info('req.cookies:' + JSON.stringify(req.headers.cookie));
// 	next();
// });

app.use(log4js.connectLogger(logger,{level:log4js.levels.INFO, format: ':remote-addr :response-time - [:date] ":method :url HTTP/:http-version" :status :content-length ":referrer" ":user-agent"'}));
app.use(express.static(__dirname + '/public'));
// app.use(express.limit('1mb'));
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(multer()); // for parsing multipart/form-data

//app session
app.sessionSecret = 'it is mime.';
app.sessionStore = new mongoStore({
			url: config.db.URI,
			collection: 'sessions'
		});
app.use(session({
		secret: app.sessionSecret,
		key: 'beyond.sid',
		store: app.sessionStore,
		saveUninitialized: false,
        resave: true
    }));

app.get('/', function(req,res){
	res.render('index.jade',{layout: false});
});

// app.get('/download/:name', function(req,res){
// 	var filename = req.params.name;
// 	if(!fs.existsSync(path.join(__dirname,'public/downloads',filename))){
// 		res.sendStatus(404);
// 		return;
// 	}
// 	var file = path.join(__dirname,'public/downloads',filename);
// 	res.download(file);
// });

//是否登录
app.isLogin = function(req,res,next){
	var grant = req.session.grant;
	if(!_.isEmpty(grant)) return next();
	res.status(401).end();
};

//授权判断中间件
app.grant = function(req,res,next){
	logger.debug('session(grant):' + JSON.stringify(req.session));
	logger.debug('req.path(grant): ' + util.inspect(req.path));
	logger.debug('req.params.id(grant): ' + util.inspect(req.params.id));
	logger.debug('req.method(grant): ' + req.method);
	var path = req.path;
	if((req.method == 'PUT' ||
		req.method == 'DELETE' ||
		req.method == 'GET') && req.params.id){
		var id = path.lastIndexOf('/');
		logger.debug('path.lastIndexOf "/"(grant): ' + id);
		if(id != -1) path = path.slice(0, id);
	}
	logger.debug('route(grant):' + path);

	var grant = req.session.grant || {};
	var features = _.values(grant);
	logger.debug('features(grant): ' + JSON.stringify(features));
	var feature = (_.where(features,{route: path}))[0];
	if(_.isUndefined(feature)) return res.status(401).end();
	logger.debug('current feature(grant):' + JSON.stringify(feature));

	var regexp_path = new RegExp(path,'i');
	logger.debug('regexp_path(grant):' + regexp_path);
	if(regexp_path.test(feature.route)){
		if(req.method == 'POST' && feature.add) return next();
		if(req.method == 'PUT' && feature.update) return next();
		if(req.method == 'DELETE' && feature.remove) return next();
		if(req.method == 'GET' && req.params.id && feature.getOne) return next();
		if(req.method == 'GET' && !(req.parmas && req.params.id) && feature.getMore) return next();
	}
	return res.status(401).end();
};

//设置跨域访问
app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "http://localhost:8000");
    res.header("Access-Control-Allow-Credentials","true");
    res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Set-Cookie");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

//import the routes
fs.readdirSync(path.join(__dirname, 'routes')).forEach(function(file){
	// var routeName = file.substr(0,file.indexOf('.'));
	var routeName = file.substr(0,file.length-3);
	require('./routes/' + routeName)(app,models);
});

app.server.listen(config.server.PORT,function(){
	logger.info(config.server.NAME + ' App is running at '+ config.server.PORT + ' now.');
});<|endoftext|>


<commit_before>import React, { Component } from 'react';

import { Image,TouchableHighlight,TouchableWithoutFeedback,Modal,ScrollView } from 'react-native';
export default class Card extends Component {
  constructor() {
    super();
    this.isLikedOnModal = this.isLikedOnModal.bind(this);
    this.isMovedOnModal = this.isMovedOnModal.bind(this);
  }
  isLikedOnModal() {
    this.props.setFullCardVisible();
    this.props.isLiked();
  }
  isMovedOnModal() {
    this.props.setFullCardVisible();
    this.props.isMoved();
  }
  render() {
    return (
      <Modal visible={this.props.visible} animationType={'fade'}>
          <ScrollView style={this.props.stylesCard}>
              <Container style={styles.mainContainer}>
                <Content>
                  <View style={styles.headSection}>
                    <View style={{flexDirection: 'row'}}>
                        <Text style={styles.name}>Ivan Dorohov</Text>
                        <Text style={styles.companyName}>Ciklum</Text>
                    </View>
                    <View style={{flexDirection: 'row'}}>
                        <Text style={styles.name}></Text>
                        <Text style={styles.location}>Amosova 12</Text>
                    </View>
                  </View>
                  <View style={styles.bodySection}>
                    <View style={styles.title}>
                      <Text numberOfLines={2} style={{fontFamily: 'HelveticaNeue-Medium'}}>
                        {this.props.children.title}
                      </Text>
                    </View>
                    <View style={styles.body}>
                      <Text numberOfLines={10} style={{fontFamily: 'HelveticaNeue-Light'}}>
                        {this.props.children.body}
                      </Text>
                    </View>
                  </View>
                </Content>
              </Container>
              </ScrollView>
              <View style={{marginLeft: 10, marginRight: 10, flexDirection: 'row'}}>
                <Icon style={{flex: 0.4, color: "#4F8EF7"}} onPress={this.isLikedOnModal} name="ios-heart-outline" />
                <Icon style={{flex: 0.4, color: "#60938a"}} name="ios-chatboxes-outline" />
                <Icon style={{color: "#4F8EF7"}} onPress={this.isMovedOnModal} name="ios-paper-outline" />
              </View>
      </Modal>
    )
  }
}<commit_msg>fullcard<commit_after>import React, { Component } from 'react';

import { Image,TouchableHighlight,TouchableWithoutFeedback,Modal,ScrollView ,StyleSheet} from 'react-native';
import {
  View,
  Text,
  Container,
  Content,
  Title,
  Icon,
  Header
} from 'native-base';
export default class Card extends Component {
  constructor() {
    super();
    this.isLikedOnModal = this.isLikedOnModal.bind(this);
    this.isMovedOnModal = this.isMovedOnModal.bind(this);
  }
  isLikedOnModal() {
    this.props.setFullCardVisible();
    this.props.isLiked();
  }
  isMovedOnModal() {
    this.props.setFullCardVisible();
    this.props.isMoved();
  }
  render() {
    return (
      <Modal visible={this.props.visible} animationType={'fade'}>
          <ScrollView style={this.props.stylesCard}>
              <Container style={styles.mainContainer}>
                <Content>
                  <View style={styles.headSection}>
                    <View style={{flexDirection: 'row'}}>
                        <Text style={styles.name}>Ivan Dorohov</Text>
                        <Text style={styles.companyName}>Ciklum</Text>
                    </View>
                    <View style={{flexDirection: 'row'}}>
                        <Text style={styles.name}></Text>
                        <Text style={styles.location}>Amosova 12</Text>
                    </View>
                  </View>
                  <View style={styles.bodySection}>
                    <View style={styles.title}>
                      <Text numberOfLines={2} style={{fontFamily: 'HelveticaNeue-Medium'}}>
                        {this.props.children.title}
                      </Text>
                    </View>
                    <View style={styles.body}>
                      <Text numberOfLines={10} style={{fontFamily: 'HelveticaNeue-Light'}}>
                        {this.props.children.body}
                      </Text>
                    </View>
                  </View>
                </Content>
              </Container>
              </ScrollView>
      </Modal>
    )
  }
}
const styles = StyleSheet.create({
  mainContainer: {
    margin: 20,
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
  name: {
    flex: 0.4
  },
  companyName: {
    alignSelf: 'stretch'
  },
  location: {
    fontSize: 12,
    alignSelf: 'stretch',
    fontFamily: 'HelveticaNeue-Light'
  },
  headSection: {
    borderBottomColor: '#d6d7da',
    paddingBottom: 15,
    borderBottomWidth: 2
  },
  title: {
    marginTop: 40
  },
  body: {
    marginTop: 20
  },
  image: {
    width: 300,
    height: 300
  },
  card: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  }
})<|endoftext|>


<commit_before>/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var StackdriverErrorReporting = function() {};

StackdriverErrorReporting.prototype.init = function(config) {
  if(!config.key) {
    console.error('[Stackdriver Error Reporting] Cannot initialize: No API key provided.');
    return;
  }
  if(!config.projectId) {
    console.error('[Stackdriver Error Reporting] Cannot initialize: No Project ID provided.');
    return;
  }

  this.apiKey = config.key;
  this.projectId = config.projectId;
  this.serviceContext = config.serviceContext || {service: 'web'};
  this.onUncaughtException = config.onUncaughtException || 'report';

  // Register as global error handler if requested
  var that = this;
  if(this.onUncaughtException == 'report') {
    window.onerror = function(message, source, lineno, colno, error) {
      that.report(error);
    }
  }
};

StackdriverErrorReporting.prototype.report = function(err) {
  if(!err) {return;}

  var payload = {};
  // see https://cloud.google.com/error-reporting/docs/formatting-error-messages#json_representation for payload description
  payload.serviceContext = this.serviceContext;
  payload.context = {
    httpRequest: {
      userAgent: window.navigator.userAgent,
      url: window.location.href
    }
  }

  if (err instanceof Error) {
    payload.message = err.stack;
  } else {
    payload.message = err.toString();

    payload.context.reportLocation = {
      filePath: 'stackdriver-errors.js',
      lineNumber: 42,
      functionName: 'report'
    }

  }

  this.sendErrorPayload(payload);
}

StackdriverErrorReporting.prototype.sendErrorPayload = function(payload) {
  console.log('[Stackdriver Error Reporting] Sending error', payload)

  var baseUrl = "https://clouderrorreporting.googleapis.com/v1beta1/projects/";
  var url = baseUrl + this.projectId + "/events?key=" + this.apiKey;

  var xhr = new XMLHttpRequest();
  xhr.open('POST', url, true);
  xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
  xhr.send(JSON.stringify(payload));
  xhr.onloadend = function () {
    console.log('[Stackdriver Error Reporting]: Error sent');
  };
}

// Create StackdriverErrors as global variable
var StackdriverErrors = new StackdriverErrorReporting();<commit_msg>Update API endpoint<commit_after>/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var StackdriverErrorReporting = function() {};

StackdriverErrorReporting.prototype.init = function(config) {
  if(!config.key) {
    console.error('[Stackdriver Error Reporting] Cannot initialize: No API key provided.');
    return;
  }
  if(!config.projectId) {
    console.error('[Stackdriver Error Reporting] Cannot initialize: No Project ID provided.');
    return;
  }

  this.apiKey = config.key;
  this.projectId = config.projectId;
  this.serviceContext = config.serviceContext || {service: 'web'};
  this.onUncaughtException = config.onUncaughtException || 'report';

  // Register as global error handler if requested
  var that = this;
  if(this.onUncaughtException == 'report') {
    window.onerror = function(message, source, lineno, colno, error) {
      that.report(error);
    }
  }
};

StackdriverErrorReporting.prototype.report = function(err) {
  if(!err) {return;}

  var payload = {};
  // see https://cloud.google.com/error-reporting/docs/formatting-error-messages#json_representation for payload description
  payload.serviceContext = this.serviceContext;
  payload.context = {
    httpRequest: {
      userAgent: window.navigator.userAgent,
      url: window.location.href
    }
  }

  if (err instanceof Error) {
    payload.message = err.stack;
  } else {
    payload.message = err.toString();

    payload.context.reportLocation = {
      filePath: 'stackdriver-errors.js',
      lineNumber: 42,
      functionName: 'report'
    }

  }

  this.sendErrorPayload(payload);
}

StackdriverErrorReporting.prototype.sendErrorPayload = function(payload) {
  console.log('[Stackdriver Error Reporting] Sending error', payload)

  var baseUrl = "https://clouderrorreporting.googleapis.com/v1beta1/projects/";
  var url = baseUrl + this.projectId + "/events:report?key=" + this.apiKey;

  var xhr = new XMLHttpRequest();
  xhr.open('POST', url, true);
  xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
  xhr.send(JSON.stringify(payload));
  xhr.onloadend = function () {
    console.log('[Stackdriver Error Reporting]: Error sent');
  };
}

// Create StackdriverErrors as global variable
var StackdriverErrors = new StackdriverErrorReporting();
<|endoftext|>


<commit_before>angular.module('grooveboat', ["LocalStorageModule"])
    .config(["$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
        $routeProvider
            .when("/", { controller: RoomListCtrl, templateUrl: "static/templates/room_list.html"})
            .when("/room/:room", { controller: RoomCtrl, templateUrl: "static/templates/room.html"})
            .otherwise({redirect_to: "/"});

        $locationProvider.html5Mode(false).hashPrefix("!");
    }])
    .factory("currentUser", ["localStorageService", function(localStorageService) {
        return {
            nickname: localStorageService.get("user:nickname"),
            clientID: ""
        }
    }])
    .service("groove", Groove);

function RoomListCtrl($scope, $location, currentUser, groove, localStorageService) {
    var selected = -1;
    $scope.currentUser = currentUser;

    $scope.rooms = [
        { name: "Ambient Electronic", selected: false },
        { name: "Indie While You Slack", selected: false }
    ];

    $scope.clickRoom = function(i) {
        if(selected > -1) {
            $scope.rooms[selected].selected = false;
        }

        document.getElementById("join-room").disabled = false;
        $scope.rooms[i].selected = true;
        selected = i;
    }

    $scope.clickJoinRoom = function() {
        var room = $scope.rooms[selected];
        var name = room.name.replace(/\s/g, "-");
        localStorageService.set("user:nickname", currentUser.nickname);
        $location.path("/room/" + name);

        groove.joinRoom(name);
    }
}

function RoomCtrl($scope, currentUser, groove, localStorageService) {
    $scope.djs = [
        { name: "stevenleeg", active: true },
        { name: "celehner", active: false },
        { name: "rochacko", active: false },
        { name: "hankcy", active: false }
    ];

    $scope.audience = [
        { name: "manyabot" },
        { name: "omeglebot" }
    ];

    $scope.current_track = {
        title: "True Affection",
        artist: "The Blow"
    }

    $scope.chat_messages = [
        { from: "stevenleeg", text: "Hello there, world" },
        { from: "celehner", text: "Hello world" }
    ];

    $scope.currentUser = currentUser;

    $scope.newMessage = function() {
        $scope.chat_messages.push({
            from: currentUser.nickname,
            text: $scope.message_text
        });

        groove.sendChat($scope.message_text);
        $scope.message_text = "";

        var messages_div = document.getElementById("messages");
        messages_div.scrollTop = messages_div.scrollHeight + 100;
    }

    groove.on("chat", function(data) {
        $scope.$apply(function($scope) {
            $scope.chat_messages.push({
                from: data.user,
                text: data.text
            });
        });
    });
}

RoomListCtrl.$inject = ["$scope", "$location", "currentUser", "groove", "localStorageService"];
RoomCtrl.$inject = ["$scope", "currentUser", "groove", "localStorageService"];
<commit_msg>Room joins are based on URL, not the selection box<commit_after>angular.module('grooveboat', ["LocalStorageModule"])
    .config(["$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
        $routeProvider
            .when("/", { controller: RoomListCtrl, templateUrl: "static/templates/room_list.html"})
            .when("/room/:room", { controller: RoomCtrl, templateUrl: "static/templates/room.html"})
            .otherwise({redirect_to: "/"});

        $locationProvider.html5Mode(false).hashPrefix("!");
    }])
    .factory("currentUser", ["localStorageService", function(localStorageService) {
        return {
            nickname: localStorageService.get("user:nickname"),
            clientID: ""
        }
    }])
    .service("groove", Groove);

function RoomListCtrl($scope, $location, currentUser, groove, localStorageService) {
    var selected = -1;
    $scope.currentUser = currentUser;

    $scope.rooms = [
        { name: "Ambient Electronic", selected: false },
        { name: "Indie While You Slack", selected: false }
    ];

    $scope.clickRoom = function(i) {
        if(selected > -1) {
            $scope.rooms[selected].selected = false;
        }

        document.getElementById("join-room").disabled = false;
        $scope.rooms[i].selected = true;
        selected = i;
    }

    $scope.clickJoinRoom = function() {
        var room = $scope.rooms[selected];
        var name = room.name.replace(/\s/g, "-");
        localStorageService.set("user:nickname", currentUser.nickname);
        $location.path("/room/" + name);
    }
}

function RoomCtrl($scope, $routeParams, currentUser, groove, localStorageService) {
    groove.joinRoom($routeParams.room);

    $scope.djs = [
        { name: "stevenleeg", active: true },
        { name: "celehner", active: false },
        { name: "rochacko", active: false },
        { name: "hankcy", active: false }
    ];

    $scope.audience = [
        { name: "manyabot" },
        { name: "omeglebot" }
    ];

    $scope.current_track = {
        title: "True Affection",
        artist: "The Blow"
    }

    $scope.chat_messages = [
        { from: "stevenleeg", text: "Hello there, world" },
        { from: "celehner", text: "Hello world" }
    ];

    $scope.currentUser = currentUser;

    $scope.newMessage = function() {
        $scope.chat_messages.push({
            from: currentUser.nickname,
            text: $scope.message_text
        });

        groove.sendChat($scope.message_text);
        $scope.message_text = "";

        var messages_div = document.getElementById("messages");
        messages_div.scrollTop = messages_div.scrollHeight + 100;
    }

    groove.on("chat", function(data) {
        $scope.$apply(function($scope) {
            $scope.chat_messages.push({
                from: data.user,
                text: data.text
            });
        });
    });
}

RoomListCtrl.$inject = ["$scope", "$location", "currentUser", "groove", "localStorageService"];
RoomCtrl.$inject = ["$scope", "$routeParams", "currentUser", "groove", "localStorageService"];
<|endoftext|>


<commit_before>angular.module('grooveboat', ["LocalStorageModule", "ngSanitize"])
    .config(["$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
        $routeProvider
            .when("/", {
                controller: RoomListCtrl,
                templateUrl: "static/templates/room_list.html"
            })
            .when("/room/:room", {
                controller: RoomCtrl,
                templateUrl: "static/templates/room.html"
            })
            .otherwise({redirect_to: "/"});

        $locationProvider.html5Mode(false).hashPrefix("!");
    }])
    .run(function($rootScope, $location) {
        $rootScope.location = $location;
    })
    .factory("groove", ["localStorageService", function(localStorageService) {
        var groove = new Groove();
        window.groove = groove;

        var name = localStorageService.get("user:name");
        var gravatar = localStorageService.get("user:gravatar");
        if (!name) {
            name = "Guest " + Math.floor(Math.random()*101);
            localStorageService.set("user:name", name);
        }
        if(gravatar) {
            groove.me.setGravatar(gravatar);
        }

        groove.me.setName(name);

        return groove;
    }])
    .directive('autoScroll', function() {
        return function(scope, elements, attrs) {
            var el = elements[0];
            function scrollToBottom() {
                el.scrollTop = el.scrollHeight;
            }
            scope.$watch("(" + attrs.autoScroll + ").length", function() {
                var lastElHeight = el.lastElementChild.offsetHeight;
                var isScrolledToBottom = (el.scrollHeight - el.scrollTop -
                    el.clientHeight - lastElHeight) < lastElHeight;
                if (isScrolledToBottom) {
                    scrollToBottom();
                    setTimeout(scrollToBottom, 10);
                }
            });
        };
    }).directive('filesBind', function() {
        return function(scope, el, attrs) {
            el.bind('change', function(e) {
                scope.$apply(function() {
                    scope[attrs.filesBind] = e.target.files;
                });
            });
        };
    }).directive('dropFiles', function() {
        function dragEnter(e) {
            e.stopPropagation();
            e.preventDefault();
            console.log("Enter");
        }

        function dragOver(e) {
            e.stopPropagation();
            e.preventDefault();
        }

        return function(scope, el, attr) {
            function drop(e) {
                e.stopPropagation();
                e.preventDefault();

                console.log("Drop");
                scope.$apply(function() {
                    scope.files = e.dataTransfer.files;
                });
            }

            el.bind("dragenter", dragEnter);
            el.bind("dragover", dragOver);
            el.bind("drop", drop);
        };
    }).filter('emoji', function() {
        var emoji = window.returnExports;
        return function(text) {
            return emoji(text, 'static/lib/emoji/pngs');
        };
    });

function MainCtrl($scope, groove, localStorageService) {
    $scope.currentUser = groove.me;
    $scope.currentOverlay = false;
    $scope.tempGravatarEmail = groove.me.gravatar;

    $scope.setOverlay = function(overlay) {
        $scope.currentOverlay = overlay;
    };

    $scope.saveName = function() {
        $scope.currentUser.setName($scope.tempUsername);
        localStorageService.set("user:name", $scope.tempUsername);
        $scope.setOverlay(false);
    };

    $scope.saveGravatarEmail = function() {
        console.log("Wat");
        if($scope.tempGravatarEmail == undefined) {
            return;
        }

        groove.me.setGravatar($scope.tempGravatarEmail);
        groove.sendGravatar();
        $scope.setOverlay(false);
        localStorageService.set("user:gravatar", groove.me.gravatar);
    };

}

function RoomListCtrl($scope, $location, groove, localStorageService) {
    /*
     * Room selection
     */
    $scope.room_selected = -1;
    $scope.creating_room = false;
    $scope.new_room_name = "";
    $scope.rooms = [];

    groove.connectToBuoy("ws://"+ window.location.hostname +":8844");

    $scope.clickRoom = function(i) {
        $scope.room_selected = i;
    }

    $scope.clickJoinRoom = function() {
        var room;
        if($scope.room_selected == $scope.rooms.length) {
            room = $scope.new_room_name;
        } else {
            room = $scope.rooms[$scope.room_selected];
        }
        room = room.replace(/\s/g, "-");
        groove.me.updateIconURL(room);
        localStorageService.set("user:name", groove.me.name);
        $location.path("/room/" + room);
    }

    /*
     * Buoy listeners
     */
    // Wait to get a welcome message
    groove.buoy.on("welcome", function(data) {
        var rooms = [];
        for(var i in data.rooms) {
            rooms.push(data.rooms[i]);
        }

        $scope.$apply(function($scope) {
            $scope.rooms = rooms;
            $scope.selecting = "room";
        });
    });

    // Listen for any new rooms being created
    groove.buoy.on("newRoom", function(data) {
        $scope.$apply(function($scope) {
            $scope.rooms.push(data.name);
        });
    });

    groove.buoy.on("deleteRoom", function(data) {
        $scope.$apply(function($scope) {
            var i = $scope.rooms.indexOf(data.name);
            if(i == -1) return;
            $scope.rooms.splice(i, 1);
        });
    });
}

function RoomCtrl($scope, $routeParams, $window, groove, localStorageService) {
    groove.joinRoom($routeParams.room);

    $scope.users = [];
    $scope.djs = [];
    $scope.currentTab = "music";
    $scope.currentOverlay = false;
    $scope.tracks = groove.playlists[groove.activePlaylist];
    $scope.files = [];

    $scope.currentTrack = null;
    $scope.votes = { yes: 0, no: 0 };
    $scope.chat_messages = [];
    $scope.newMessages = false;
    $scope.users.push(groove.me);

    var player = $window.document.createElement("audio");
    window.player = player;
    var activeTrack;
    player.addEventListener("canplay", function() {
        var track = groove.activeTrack;
        if (track == activeTrack) return;
        activeTrack = track;
        console.log("canplay", track && track.currentTime, track);
        if (track) {
            player.currentTime = track.currentTime;
            groove.canPlayTrack(player.duration);
            player.play();
        }
    }, false);

    $scope.switchTab = function(tab) {
        if(tab == "chat" && $scope.newMessages) {
            $scope.newMessages = false;
        }

        $scope.currentTab = tab;
    }

    $scope.clickUser = function(user) {
        if(user == groove.me) {
            $scope.setOverlay("change-avatar");
        }
    }

    $scope.isDJ = function(user) {
        return (user.dj == true);
    }

    $scope.isAudience = function(user) {
        return (user.dj != true);
    }

    $scope.becomeDJ = function() {
        if($scope.tracks.length == 0) {
            $scope.setOverlay("no-tracks");
            return;
        }

        if(!groove.me.dj) {
            groove.becomeDJ();
        } else {
            groove.quitDJing();
        }
    }

    $scope.vote = function(direction) {
        if(groove.activeDJ == groove.me) {
            return;
        }

        handleVote(groove.me.vote, direction);
        groove.vote(direction);
    }

    $scope.getJoinText = function() {
        if(groove.me.dj) {
            return "leave";
        } else {
            return "become a dj";
        }
    }

    function handleVote(previous, next) {
        if(previous == 1) {
            $scope.votes.yes -= 1;
        } else if(previous == -1) {
            $scope.votes.no -= 1;
        }

        if(next == 1) {
            $scope.votes.yes += 1;
        } else if(next == -1) {
            $scope.votes.no += 1;
        }
    }

    var digest = $scope.$digest.bind($scope);
    function watchUser(user) {
        user.on("name", digest);
        user.on("vote", digest);
        user.on("gravatar", digest);
        user.on("vote", function(previous, next) {
            handleVote(previous, next);
            digest();
        });
    }

    $scope.newMessage = function() {
        var text = $scope.message_text;
        var last = groove.lastChatAuthor;
        if (text && text.trim()) {
            $scope.chat_messages.push({
                from: groove.me,
                text: text,
                isContinuation: last && last == groove.me
            });
            groove.lastChatAuthor = groove.me;
            groove.sendChat(text);
        }
        $scope.message_text = "";
    };

    $scope.$watch("files", function() {

        groove.addFilesToQueue($scope.files);
    });

    $scope.$on("$destroy", function() {
        groove.leaveRoom();
    });

    groove.on("chat", function(message) {
        $scope.$apply(function($scope) {
            if($scope.currentTab != "chat") {
                $scope.newMessages = true;
            }

            var last = groove.lastChatAuthor;
            message.isContinuation = (last && last == message.from);
            groove.lastChatAuthor = message.from;
            $scope.chat_messages.push(message);
        });
    });

    groove.on("djs", function(djs) {
        $scope.$apply(function($scope) {
            $scope.djs = djs;
        });
    });

    groove.on("activeDJ", function() {
        $scope.$apply(function($scope) {
            $scope.activeDJ = groove.activeDJ;
        });
    });

    groove.on("activeTrack", function() {
        $scope.$apply(function($scope) {
            $scope.currentTrack = groove.activeTrack;
        });
    });

    groove.on("activeTrackURL", function() {
        var track = groove.activeTrack;
        var url = track && track.url;
        if (url) {
            console.log("got track url", url.length, url.substr(0, 256));
            player.src = url;
            console.log('current time', track.currentTime, track);
        } else {
            console.log("no track");
            player.pause();
        }
    });

    groove.on("emptyPlaylist", function() {
        alert("Add some music to your playlist first.");
    });

    groove.on("queueUpdate", digest);

    groove.on("peerConnected", function(user) {
        $scope.$apply(function($scope) {
            $scope.users.push(user);
            watchUser(user);
        });
    });

    groove.on("peerDisconnected", function(user) {
        $scope.$apply(function($scope) {
            var i =  $scope.users.indexOf(user);
            if(i == -1) {
                return;
            }

            $scope.users.splice(i, 1);
        });
    });
}

BuoyListCtrl.$inject = ["$scope", "$location", "groove", "localStorageService"];
RoomCtrl.$inject = ["$scope", "$routeParams", "$window", "groove",
    "localStorageService"];
<commit_msg>Little cleanup<commit_after>angular.module('grooveboat', ["LocalStorageModule", "ngSanitize"])
    .config(["$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
        $routeProvider
            .when("/", {
                controller: RoomListCtrl,
                templateUrl: "static/templates/room_list.html"
            })
            .when("/room/:room", {
                controller: RoomCtrl,
                templateUrl: "static/templates/room.html"
            })
            .otherwise({redirect_to: "/"});

        $locationProvider.html5Mode(false).hashPrefix("!");
    }])
    .run(function($rootScope, $location) {
        $rootScope.location = $location;
    })
    .factory("groove", ["localStorageService", function(localStorageService) {
        var groove = new Groove();
        window.groove = groove;

        var name = localStorageService.get("user:name");
        var gravatar = localStorageService.get("user:gravatar");
        if (!name) {
            name = "Guest " + Math.floor(Math.random()*101);
            localStorageService.set("user:name", name);
        }
        if(gravatar) {
            groove.me.setGravatar(gravatar);
        }

        groove.me.setName(name);

        return groove;
    }])
    .directive('autoScroll', function() {
        return function(scope, elements, attrs) {
            var el = elements[0];
            function scrollToBottom() {
                el.scrollTop = el.scrollHeight;
            }
            scope.$watch("(" + attrs.autoScroll + ").length", function() {
                var lastElHeight = el.lastElementChild.offsetHeight;
                var isScrolledToBottom = (el.scrollHeight - el.scrollTop -
                    el.clientHeight - lastElHeight) < lastElHeight;
                if (isScrolledToBottom) {
                    scrollToBottom();
                    setTimeout(scrollToBottom, 10);
                }
            });
        };
    }).directive('filesBind', function() {
        return function(scope, el, attrs) {
            el.bind('change', function(e) {
                scope.$apply(function() {
                    scope[attrs.filesBind] = e.target.files;
                });
            });
        };
    }).directive('dropFiles', function() {
        function dragEnter(e) {
            e.stopPropagation();
            e.preventDefault();
            console.log("Enter");
        }

        function dragOver(e) {
            e.stopPropagation();
            e.preventDefault();
        }

        return function(scope, el, attr) {
            function drop(e) {
                e.stopPropagation();
                e.preventDefault();

                console.log("Drop");
                scope.$apply(function() {
                    scope.files = e.dataTransfer.files;
                });
            }

            el.bind("dragenter", dragEnter);
            el.bind("dragover", dragOver);
            el.bind("drop", drop);
        };
    }).filter('emoji', function() {
        var emoji = window.returnExports;
        return function(text) {
            return emoji(text, 'static/lib/emoji/pngs');
        };
    });

function MainCtrl($scope, groove, localStorageService) {
    $scope.currentUser = groove.me;
    $scope.currentOverlay = false;
    $scope.tempGravatarEmail = groove.me.gravatar;

    $scope.setOverlay = function(overlay) {
        $scope.currentOverlay = overlay;
    };

    $scope.saveName = function() {
        $scope.currentUser.setName($scope.tempUsername);
        localStorageService.set("user:name", $scope.tempUsername);
        $scope.setOverlay(false);
    };

    $scope.saveGravatarEmail = function() {
        console.log("Wat");
        if($scope.tempGravatarEmail == undefined) {
            return;
        }

        groove.me.setGravatar($scope.tempGravatarEmail);
        groove.sendGravatar();
        $scope.setOverlay(false);
        localStorageService.set("user:gravatar", groove.me.gravatar);
    };

}

function RoomListCtrl($scope, $location, groove, localStorageService) {
    /*
     * Room selection
     */
    $scope.room_selected = -1;
    $scope.creating_room = false;
    $scope.new_room_name = "";
    $scope.rooms = [];

    groove.connectToBuoy("ws://"+ window.location.hostname +":8844");

    $scope.clickRoom = function(i) {
        $scope.room_selected = i;
    }

    $scope.clickJoinRoom = function() {
        var room;
        if($scope.room_selected == $scope.rooms.length) {
            room = $scope.new_room_name;
        } else {
            room = $scope.rooms[$scope.room_selected];
        }
        room = room.replace(/\s/g, "-");
        groove.me.updateIconURL(room);
        localStorageService.set("user:name", groove.me.name);
        $location.path("/room/" + room);
    }

    /*
     * Buoy listeners
     */
    // Wait to get a welcome message
    groove.buoy.on("welcome", function(data) {
        var rooms = [];
        for(var i in data.rooms) {
            rooms.push(data.rooms[i]);
        }

        $scope.$apply(function($scope) {
            $scope.rooms = rooms;
            $scope.selecting = "room";
        });
    });

    // Listen for any new rooms being created
    groove.buoy.on("newRoom", function(data) {
        $scope.$apply(function($scope) {
            $scope.rooms.push(data.name);
        });
    });

    groove.buoy.on("deleteRoom", function(data) {
        $scope.$apply(function($scope) {
            var i = $scope.rooms.indexOf(data.name);
            if(i == -1) return;
            $scope.rooms.splice(i, 1);
        });
    });
}

function RoomCtrl($scope, $routeParams, $window, groove, localStorageService) {
    /*
     * Listeners on the UI
     */
    groove.joinRoom($routeParams.room);

    $scope.users = [];
    $scope.djs = [];
    $scope.currentTab = "music";
    $scope.currentOverlay = false;
    $scope.tracks = groove.playlists[groove.activePlaylist];
    $scope.files = [];

    $scope.currentTrack = null;
    $scope.votes = { yes: 0, no: 0 };
    $scope.chat_messages = [];
    $scope.newMessages = false;
    $scope.users.push(groove.me);

    var player = $window.document.createElement("audio");
    window.player = player;
    var activeTrack;
    player.addEventListener("canplay", function() {
        var track = groove.activeTrack;
        if (track == activeTrack) return;
        activeTrack = track;
        console.log("canplay", track && track.currentTime, track);
        if (track) {
            player.currentTime = track.currentTime;
            groove.canPlayTrack(player.duration);
            player.play();
        }
    }, false);

    $scope.switchTab = function(tab) {
        if(tab == "chat" && $scope.newMessages) {
            $scope.newMessages = false;
        }

        $scope.currentTab = tab;
    }

    $scope.clickUser = function(user) {
        if(user == groove.me) {
            $scope.setOverlay("change-avatar");
        }
    }

    $scope.isDJ = function(user) {
        return (user.dj == true);
    }

    $scope.isAudience = function(user) {
        return (user.dj != true);
    }

    $scope.becomeDJ = function() {
        if($scope.tracks.length == 0) {
            $scope.setOverlay("no-tracks");
            return;
        }

        if(!groove.me.dj) {
            groove.becomeDJ();
        } else {
            groove.quitDJing();
        }
    }

    $scope.vote = function(direction) {
        if(groove.activeDJ == groove.me) {
            return;
        }

        handleVote(groove.me.vote, direction);
        groove.vote(direction);
    }

    $scope.getJoinText = function() {
        if(groove.me.dj) {
            return "leave";
        } else {
            return "become a dj";
        }
    }

    function handleVote(previous, next) {
        if(previous == 1) {
            $scope.votes.yes -= 1;
        } else if(previous == -1) {
            $scope.votes.no -= 1;
        }

        if(next == 1) {
            $scope.votes.yes += 1;
        } else if(next == -1) {
            $scope.votes.no += 1;
        }
    }

    var digest = $scope.$digest.bind($scope);
    function watchUser(user) {
        user.on("name", digest);
        user.on("vote", digest);
        user.on("gravatar", digest);
        user.on("vote", function(previous, next) {
            handleVote(previous, next);
            digest();
        });
    }

    $scope.newMessage = function() {
        var text = $scope.message_text;
        var last = groove.lastChatAuthor;
        if (text && text.trim()) {
            $scope.chat_messages.push({
                from: groove.me,
                text: text,
                isContinuation: last && last == groove.me
            });
            groove.lastChatAuthor = groove.me;
            groove.sendChat(text);
        }
        $scope.message_text = "";
    };

    $scope.$watch("files", function() {
        groove.addFilesToQueue($scope.files);
    });

    $scope.$on("$destroy", function() {
        groove.leaveRoom();
    });

    /*
     * Listeners from the buoy server
     */
    groove.on("chat", function(message) {
        $scope.$apply(function($scope) {
            if($scope.currentTab != "chat") {
                $scope.newMessages = true;
            }

            var last = groove.lastChatAuthor;
            message.isContinuation = (last && last == message.from);
            groove.lastChatAuthor = message.from;
            $scope.chat_messages.push(message);
        });
    });

    groove.on("djs", function(djs) {
        $scope.$apply(function($scope) {
            $scope.djs = djs;
        });
    });

    groove.on("activeDJ", function() {
        $scope.$apply(function($scope) {
            $scope.activeDJ = groove.activeDJ;
        });
    });

    groove.on("activeTrack", function() {
        $scope.$apply(function($scope) {
            $scope.currentTrack = groove.activeTrack;
        });
    });

    groove.on("activeTrackURL", function() {
        var track = groove.activeTrack;
        var url = track && track.url;
        if (url) {
            console.log("got track url", url.length, url.substr(0, 256));
            player.src = url;
            console.log('current time', track.currentTime, track);
        } else {
            console.log("no track");
            player.pause();
        }
    });

    groove.on("emptyPlaylist", function() {
        alert("Add some music to your playlist first.");
    });

    groove.on("queueUpdate", digest);

    groove.on("peerConnected", function(user) {
        $scope.$apply(function($scope) {
            $scope.users.push(user);
            watchUser(user);
        });
    });

    groove.on("peerDisconnected", function(user) {
        $scope.$apply(function($scope) {
            var i =  $scope.users.indexOf(user);
            if(i == -1) {
                return;
            }

            $scope.users.splice(i, 1);
        });
    });
}

BuoyListCtrl.$inject = ["$scope", "$location", "groove", "localStorageService"];
RoomCtrl.$inject = ["$scope", "$routeParams", "$window", "groove",
    "localStorageService"];
<|endoftext|>


<commit_before>/* Dispatch area - Should be eliminate after dispatching */

var markersGroup = new L.LayerGroup();
var isDispatching = false;
var isFilterOpen = false;
var placeIcon = L.icon({
	iconUrl: '/static/icons/place_marker.png',
	iconSize: [40, 40],
	iconAnchor: [20, 40],
	popupAnchor: [0,-40]
});

var dispatchingAmbulances = {};
var numberOfDispatchingAmbulances = 0;

var currentAddress;
var currentLocation;
var currentPatients;
var newPatientIndex;

var submitDispatching = function () {

    // submit form
    $('#dispatch-form-collapse').submit();

};

var beginDispatching = function () {

    isDispatching = true;
    var filtersDiv = $('#filtersDiv');
    isFilterOpen = filtersDiv.hasClass('show');
    console.log('Begin dispatching.');

    $('#dispatchBeginButton').hide();
    $('#dispatchSubmitButton').show();
    $('#dispatchCancelButton').show();

    // open filter and available ambulances
    filtersDiv.addClass('show');
    $('#ambulance_status').addClass('show');
    $('#ambulance_AV').addClass('show');

    // Update current location
    updateCurrentLocation(mymap.getCenter());

    // Update current address
    updateCurrentAddress(currentLocation);

    // Clear current currentPatients
    currentPatients = {};
    newPatientIndex = 0;

    // Initialize patient form
    $('#patients').empty();

    // add new patient form entry
    addPatientForm(newPatientIndex);

    // invalidate map size
    mymap.invalidateSize();

    // center map
    mymap.setView(currentLocation, mymap.getZoom());

}

var endDispatching = function () {

    isDispatching = false;
    dispatchingAmbulances = {};
    console.log('End dispatching.');

    markersGroup.clearLayers();

    $('#dispatchBeginButton').show();
    $('#dispatchSubmitButton').hide();
    $('#dispatchCancelButton').hide();

    // close dispatch panel
    $('#dispatchDiv').removeClass('show');

    if (!isFilterOpen) {
        // close filter panel
        $('#filtersDiv').removeClass('show');
    }

    // invalidate map size
    mymap.invalidateSize();

}

var removeFromDispatchingList = function(ambulance) {

    // delete from dispatching list
    delete dispatchingAmbulances[ambulance.id];
    numberOfDispatchingAmbulances--;

    // show message if last button
    if (numberOfDispatchingAmbulances == 0)
        $('#ambulance-selection-message').show();

}

var addToDispatchingList = function(ambulance) {

    // quick return if null or not dispatching
    if (ambulance == null || !isDispatching)
        return;

    // add ambulance to dispatching list
    console.log('Adding ambulance ' + ambulance.identifier + ' to dispatching list');

    // already in?
    if (ambulance.id in dispatchingAmbulances) {
        console.log('Already in dispatching list, skip');
        return;
    }

    // not available?
    if (ambulance.status != STATUS_AVAILABLE) {
        console.log('Ambulance is not available');
        bsalert('Can only dispatch available ambulances!');
        return;
    }

    // hide message if first button
    if (numberOfDispatchingAmbulances == 0)
        $('#ambulance-selection-message').hide();

    // add ambulance to list of dispatching ambulances
    dispatchingAmbulances[ambulance.id] = ambulance;
    numberOfDispatchingAmbulances++;

    // add button to ambulance dispatch grid
    $('#ambulance-selection').append(
        '<button id="dispatch-button-' + ambulance.id + '"'
        + ' value="' + ambulance.id + '"'
        + ' type="button" class="btn btn-sm '+ ambulance_buttons['AV'] + '"'
        + ' style="margin: 2px 2px;"'
        + ' draggable="true">'
        + ambulance.identifier
        + '</button>'
    );
    $('#dispatch-button-' + ambulance.id)
        .on('dragstart', function (e) {
            // on start of drag, copy information and fade button
            console.log('dragstart');
            this.style.opacity = '0.4';
            e.originalEvent.dataTransfer.setData("text/plain", ambulance.id);
        })
        .on('dragend', function (e) {
            console.log('dragend');
            if (e.originalEvent.dataTransfer.dropEffect == 'none') {
                // Remove button if not dropped back
                removeFromDispatchingList(ambulance);
                // Remove button
                $(this).remove();
            } else {
                // Restore opacity if dropped back in
                this.style.opacity = '1.0';
            }
        });
}

var updateCurrentLocation = function(location) {

    console.log('Setting current location to: ' + location.lat + ', ' + location.lng);

    // set currentLocation
    currentLocation = location;

    // update coordinates on form
    $('#curr-lat').html(currentLocation.lat.toFixed(6));
    $('#curr-lng').html(currentLocation.lng.toFixed(6));

    // remove existing marker
    markersGroup.clearLayers();

    // laydown marker
    var marker = L.marker(location,
        {
            icon: placeIcon,
            draggable: true
        })
        .addTo(markersGroup);
    markersGroup.addTo(mymap);

    // pan to location
    mymap.panTo(location);

    // events
    marker.on('dragend', function(e) {

        // update current location
        updateCurrentLocation(marker.getLatLng());

        // update address?
        if ($('#update-address').prop('checked'))
            updateCurrentAddress(currentLocation);

    })

}

var updateCurrentAddress = function(location) {

    var options = {
        types: 'address',
        limit: 1
    };
    geocoder.reverse(location, options,
        function (results, status) {

        if (status != "success") {
            bsalert("Could not geocode:\nError " + status + ", " + results['error']);
            return;
        }

        // quick return if found nothing
        if (results.length == 0) {
            console.log('Got nothing from geocode');
            return;
        }

        // parse features into current address
        currentAddress = geocoder.parse_feature(results[0]);

        console.log(
            'Setting currentAddress to:'
            + '\nnumber: ' + currentAddress['number']
            + '\nstreet: ' + currentAddress['street']
            + '\nunit: ' + currentAddress['unit']
            + '\nlocation: ' + currentAddress['location']['latitude']
            + ',' + currentAddress['location']['longitude']
            + '\nneighborhood: ' + currentAddress['neighborhood']
            + '\nzipcode: ' + currentAddress['zipcode']
            + '\ncity: ' + currentAddress['city']
            + '\nstate: ' + currentAddress['state']
            + '\ncountry: ' + currentAddress['country']
        );

        // set input text
        $('#street').val(currentAddress['street_address']);

    });

}

var updateCoordinates = function() {

    // when the user changes the street address
    var address =$('#street').val();

    // quick return if no address
    if (!address)
        return;

    // otherwise geocode and update
    var options = {
        types: 'address',
        limit: 1,
        autocomplete: 'true'
    };
    geocoder.geocode(address, options,
        function (results, status) {

            if (status != "success") {
                bsalert("Could not geocode:\nError " + status + ", " + results['error']);
                return;
            }

            // quick return if found nothing
            if (results.length == 0) {
                console.log('Got nothing from geocode');
                return;
            }

            // parse features into address
            var address = geocoder.parse_feature(results[0]);

            console.log(
                'Setting currentLocation to:'
                + '\nnumber: ' + address['number']
                + '\nstreet: ' + address['street']
                + '\nunit: ' + address['unit']
                + '\nlocation: ' + address['location']['latitude']
                + ',' + address['location']['longitude']
                + '\nneighborhood: ' + address['neighborhood']
                + '\nzipcode: ' + address['zipcode']
                + '\ncity: ' + address['city']
                + '\nstate: ' + address['state']
                + '\ncountry: ' + address['country']
            );

            // set current location
            updateCurrentLocation({
                lat: address['location']['latitude'],
                lng: address['location']['longitude']
            });

        });
}

function dispatchCall() {

    var form = {};

    // call information
    var street_address = $('#street').val().trim();
    form['details'] = $('#comment').val().trim();
    form['priority'] = $('input:radio[name=priority]:checked').val();

    // checks
    if (form["priority"] === undefined) {
        bsalert("Please select the priority level.");
        return;
    }
    if (numberOfDispatchingAmbulances == 0) {
        bsalert("Please dispatch at least one ambulance.");
        return;
    }

    // address information
    form['neighborhood'] = currentAddress['neighborhood'];
    form['city'] = currentAddress['city'];
    form['state'] = currentAddress['state'];
    form['country'] = currentAddress['country'];
    form['zipcode'] = currentAddress['zipcode'];
    form['location'] = currentAddress['location'];

    // Has the user modified the street address?
    if (street_address != currentAddress['street_address']) {

        // parse street address
        var address = geocoder.parse_street_address(street_address, form['country']);

        form['number'] = address['number'];
        form['street'] = address['street'];
        form['unit'] = address['unit'];

    } else {

        form['number'] = currentAddress['number'];
        form['street'] = currentAddress['street'];
        form['unit'] = currentAddress['unit'];

    }

    // Make sure blanks are undefined
    if (form['number'] == "") {
        form['number'] = undefined;
    }

    // ambulances
    var ambulances = [];
    for (var id in dispatchingAmbulances)
        if (dispatchingAmbulances.hasOwnProperty(id))
            ambulances.push({ 'ambulance_id': id });
    form['ambulancecall_set'] = ambulances;

    // patients
    var patients = [];
    for (var index in currentPatients)
        if (currentPatients.hasOwnProperty(index)) {
            var patient = currentPatients[index];
            var obj = { 'name': patient[0] };
            if (patient[1])
                // add age
                obj['age'] = parseInt(patient[1]);
            patients.push(obj);
        }
    form['patient_set'] = patients;

    // make json call
    var postJsonUrl = APIBaseUrl + 'call/';
    console.log("Form:");
    console.log(form);
    console.log("Will post:");
    console.log(JSON.stringify(form));

    var CSRFToken = Cookies.get('csrftoken');
    console.log('csrftoken = ' + CSRFToken);

    // retrieve csrf token
    $.ajaxSetup({
        beforeSend: function (xhr, settings) {
            if (!CSRFSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", CSRFToken);
            }
        }
    });

    // make ajax call
    $.ajax({
        url: postJsonUrl,
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        data: JSON.stringify(form),
        success: function (data) {

            // Log success
            console.log("Succesfully posted new call.");

            // End dispatching
            endDispatching();

        },
        error: function (jqXHR, textStatus, errorThrown) {

            // Log failure
            console.log("Failed to post new call.");
            console.log(jqXHR.responseText);

            // Show modal
            bsalert(jqXHR.responseText, 'alert-danger', 'Failure');

            // End dispatching
            endDispatching();

        }
    });
}

// patient functions

var addPatient = function(index) {

    console.log('Adding patient index ' + index);

    var name = $('#patient-' + index + '-name').val().trim();
    var age = $('#patient-' + index + '-age').val().trim();

    // is name empty?
    if (!name) {
        bsalert('Empty name');
        return;
    }

    // add name
    currentPatients[index] = [name, age];
    newPatientIndex++;

    // change button symbol
    var symbol = $('#patient-' + index + '-symbol');
    symbol.removeClass('fa-plus');
    symbol.addClass('fa-minus');

    // change button action from add to remove
    $('#patients').find('#patient-' + index + '-button')
        .off()
        .on('click', function(e) { removePatient(index); });

    // add new form
    addPatientForm(newPatientIndex);

}

var removePatient = function(index) {

    console.log('Removing patient index ' + index);

    // remove from storage
    delete currentPatients[index];

    // remove from form
    $('#patients')
        .find('#patient-' + index + '-form')
        .remove();

}

var addPatientForm = function(index) {

    // add new patient form entry
    $('#patients').append(newPatientForm(index, 'fa-plus'));

    // bind addPatient to click
    $('#patients')
        .on('click',
            '#patient-' + index + '-button',
            function(e) { addPatient(index); });

}

var newPatientForm = function(index, symbol) {

    var html =
        '
' +
            '
' +
                '<input id="patient-' + index + '-name" ' +
                       'type="text" ' +
                       'class="form-control" ' +
                       'placeholder="Name">' +
            '
' +
            '
' +
                '<input id="patient-' + index + '-age" ' +
                       'type="number" min="0" ' +
                       'class="form-control" ' +
                       'placeholder="Age">' +
            '
' +
            '
' +
                '<button class="btn btn-default new-patient" ' +
                       ' type="button" ' +
                       ' id="patient-' + index + '-button">' +
                    '' +
                '</button>' +
            '
' +
        '
';

    // console.log('html = "' + html + '"');

    return html;

}

// Ready function
$(function() {

    // connect actions to inputs

    $("#street").change(function () {

        // update coordinates?
        if ($('#update-coordinates').prop('checked'))
            updateCoordinates();

    });

    $('#update-coordinates').change(function () {

        // update coordinates?
        if ($('#update-coordinates').prop('checked'))
            updateCoordinates();

    });

    $('#update-address').change(function () {

        // update address?
        if ($('#update-address').prop('checked'))
            updateCurrentAddress(currentLocation);

    });

    $('#dispatch-form-collapse').submit(function (e) {

        // prevent normal form submission
        e.preventDefault();

        // dispatch call
        dispatchCall();

    });

});

// CSRF functions

function CSRFSafeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}<commit_msg>New map interface.<commit_after>/* Dispatch area - Should be eliminate after dispatching */

var markersGroup = new L.LayerGroup();
var isDispatching = false;
var isFilterOpen = false;
var placeIcon = L.icon({
	iconUrl: '/static/icons/place_marker.png',
	iconSize: [40, 40],
	iconAnchor: [20, 40],
	popupAnchor: [0,-40]
});

var dispatchingAmbulances = {};
var numberOfDispatchingAmbulances = 0;

var currentAddress;
var currentLocation;
var currentPatients;
var newPatientIndex;

var submitDispatching = function () {

    // submit form
    $('#dispatch-form-collapse').submit();

};

var beginDispatching = function () {

    isDispatching = true;
    var filtersDiv = $('#filtersDiv');
    isFilterOpen = filtersDiv.hasClass('show');
    console.log('Begin dispatching.');

    $('#dispatchBeginButton').hide();
    $('#dispatchSubmitButton').show();
    $('#dispatchCancelButton').show();

    // open filter and available ambulances
    filtersDiv.addClass('show');
    $('#ambulance_status').addClass('show');
    $('#ambulance_AV').addClass('show');

    // Update current location
    updateCurrentLocation(mymap.getCenter());

    // Update current address
    updateCurrentAddress(currentLocation);

    // Clear current currentPatients
    currentPatients = {};
    newPatientIndex = 0;

    // Initialize patient form
    $('#patients').empty();

    // add new patient form entry
    addPatientForm(newPatientIndex);

    // invalidate map size
    mymap.invalidateSize();

    // center map
    mymap.setView(currentLocation, mymap.getZoom());

}

var endDispatching = function () {

    isDispatching = false;
    dispatchingAmbulances = {};
    console.log('End dispatching.');

    markersGroup.clearLayers();

    $('#dispatchBeginButton').show();
    $('#dispatchSubmitButton').hide();
    $('#dispatchCancelButton').hide();

    // close dispatch panel
    $('#dispatchDiv').removeClass('show');

    if (!isFilterOpen) {
        // close filter panel
        $('#filtersDiv').removeClass('show');
    }

    // invalidate map size
    mymap.invalidateSize();

}

var removeFromDispatchingList = function(ambulance) {

    // delete from dispatching list
    delete dispatchingAmbulances[ambulance.id];
    numberOfDispatchingAmbulances--;

    // show message if last button
    if (numberOfDispatchingAmbulances == 0)
        $('#ambulance-selection-message').show();

}

var addToDispatchingList = function(ambulance) {

    // quick return if null or not dispatching
    if (ambulance == null || !isDispatching)
        return;

    // add ambulance to dispatching list
    console.log('Adding ambulance ' + ambulance.identifier + ' to dispatching list');

    // already in?
    if (ambulance.id in dispatchingAmbulances) {
        console.log('Already in dispatching list, skip');
        return;
    }

    // not available?
    if (ambulance.status != STATUS_AVAILABLE) {
        console.log('Ambulance is not available');
        bsalert('Can only dispatch available ambulances!');
        return;
    }

    // hide message if first button
    if (numberOfDispatchingAmbulances == 0)
        $('#ambulance-selection-message').hide();

    // add ambulance to list of dispatching ambulances
    dispatchingAmbulances[ambulance.id] = ambulance;
    numberOfDispatchingAmbulances++;

    // add button to ambulance dispatch grid
    $('#ambulance-selection').append(
        '<button id="dispatch-button-' + ambulance.id + '"'
        + ' value="' + ambulance.id + '"'
        + ' type="button" class="btn btn-sm '+ ambulance_buttons['AV'] + '"'
        + ' style="margin: 2px 2px;"'
        + ' draggable="true">'
        + ambulance.identifier
        + '</button>'
    );
    $('#dispatch-button-' + ambulance.id)
        .on('dragstart', function (e) {
            // on start of drag, copy information and fade button
            console.log('dragstart');
            this.style.opacity = '0.4';
            e.originalEvent.dataTransfer.setData("text/plain", ambulance.id);
        })
        .on('dragend', function (e) {
            console.log('dragend');
            if (e.originalEvent.dataTransfer.dropEffect == 'none') {
                // Remove button if not dropped back
                removeFromDispatchingList(ambulance);
                // Remove button
                $(this).remove();
            } else {
                // Restore opacity if dropped back in
                this.style.opacity = '1.0';
            }
        });
}

var updateCurrentLocation = function(location) {

    console.log('Setting current location to: ' + location.lat + ', ' + location.lng);

    // set currentLocation
    currentLocation = location;

    // update coordinates on form
    $('#curr-lat').html(currentLocation.lat.toFixed(6));
    $('#curr-lng').html(currentLocation.lng.toFixed(6));

    // remove existing marker
    markersGroup.clearLayers();

    // laydown marker
    var marker = L.marker(location,
        {
            icon: placeIcon,
            draggable: true
        })
        .addTo(markersGroup);
    markersGroup.addTo(mymap);

    // pan to location
    mymap.panTo(location);

    // events
    marker.on('dragend', function(e) {

        // update current location
        updateCurrentLocation(marker.getLatLng());

        // update address?
        if ($('#update-address').prop('checked'))
            updateCurrentAddress(currentLocation);

    })

}

var updateCurrentAddress = function(location) {

    var options = {
        types: 'address',
        limit: 1
    };
    geocoder.reverse(location, options,
        function (results, status) {

        if (status != "success") {
            bsalert("Could not geocode:\nError " + status + ", " + results['error']);
            return;
        }

        // quick return if found nothing
        if (results.length == 0) {
            console.log('Got nothing from geocode');
            return;
        }

        // parse features into current address
        currentAddress = geocoder.parse_feature(results[0]);

        console.log(
            'Setting currentAddress to:'
            + '\nnumber: ' + currentAddress['number']
            + '\nstreet: ' + currentAddress['street']
            + '\nunit: ' + currentAddress['unit']
            + '\nlocation: ' + currentAddress['location']['latitude']
            + ',' + currentAddress['location']['longitude']
            + '\nneighborhood: ' + currentAddress['neighborhood']
            + '\nzipcode: ' + currentAddress['zipcode']
            + '\ncity: ' + currentAddress['city']
            + '\nstate: ' + currentAddress['state']
            + '\ncountry: ' + currentAddress['country']
        );

        // set input text
        $('#street').val(currentAddress['street_address']);

    });

}

var updateCoordinates = function() {

    // when the user changes the street address
    var address =$('#street').val();

    // quick return if no address
    if (!address)
        return;

    // otherwise geocode and update
    var options = {
        types: 'address',
        limit: 1,
        autocomplete: 'true'
    };
    geocoder.geocode(address, options,
        function (results, status) {

            if (status != "success") {
                bsalert("Could not geocode:\nError " + status + ", " + results['error']);
                return;
            }

            // quick return if found nothing
            if (results.length == 0) {
                console.log('Got nothing from geocode');
                return;
            }

            // parse features into address
            var address = geocoder.parse_feature(results[0]);

            console.log(
                'Setting currentLocation to:'
                + '\nnumber: ' + address['number']
                + '\nstreet: ' + address['street']
                + '\nunit: ' + address['unit']
                + '\nlocation: ' + address['location']['latitude']
                + ',' + address['location']['longitude']
                + '\nneighborhood: ' + address['neighborhood']
                + '\nzipcode: ' + address['zipcode']
                + '\ncity: ' + address['city']
                + '\nstate: ' + address['state']
                + '\ncountry: ' + address['country']
            );

            // set current location
            updateCurrentLocation({
                lat: address['location']['latitude'],
                lng: address['location']['longitude']
            });

        });
}

function dispatchCall() {

    var form = {};

    // call information
    var street_address = $('#street').val().trim();
    form['details'] = $('#comment').val().trim();
    form['priority'] = $('input:radio[name=priority]:checked').val();

    // checks
    if (form["priority"] === undefined) {
        bsalert("Please select the priority level.");
        return;
    }
    if (numberOfDispatchingAmbulances == 0) {
        bsalert("Please dispatch at least one ambulance.");
        return;
    }

    // address information
    form['neighborhood'] = currentAddress['neighborhood'];
    form['city'] = currentAddress['city'];
    form['state'] = currentAddress['state'];
    form['country'] = currentAddress['country'];
    form['zipcode'] = currentAddress['zipcode'];
    form['location'] = currentAddress['location'];

    // Has the user modified the street address?
    if (street_address != currentAddress['street_address']) {

        // parse street address
        var address = geocoder.parse_street_address(street_address, form['country']);

        form['number'] = address['number'];
        form['street'] = address['street'];
        form['unit'] = address['unit'];

    } else {

        form['number'] = currentAddress['number'];
        form['street'] = currentAddress['street'];
        form['unit'] = currentAddress['unit'];

    }

    // Make sure blanks are undefined
    if (form['number'] == "") {
        form['number'] = undefined;
    }

    // ambulances
    var ambulances = [];
    for (var id in dispatchingAmbulances)
        if (dispatchingAmbulances.hasOwnProperty(id))
            ambulances.push({ 'ambulance_id': id });
    form['ambulancecall_set'] = ambulances;

    // patients
    var patients = [];
    for (var index in currentPatients)
        if (currentPatients.hasOwnProperty(index)) {
            var patient = currentPatients[index];
            var obj = { 'name': patient[0] };
            if (patient[1])
                // add age
                obj['age'] = parseInt(patient[1]);
            patients.push(obj);
        }
    form['patient_set'] = patients;

    // make json call
    var postJsonUrl = APIBaseUrl + 'call/';
    console.log("Form:");
    console.log(form);
    console.log("Will post:");
    console.log(JSON.stringify(form));

    var CSRFToken = Cookies.get('csrftoken');
    console.log('csrftoken = ' + CSRFToken);

    // retrieve csrf token
    $.ajaxSetup({
        beforeSend: function (xhr, settings) {
            if (!CSRFSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", CSRFToken);
            }
        }
    });

    // make ajax call
    $.ajax({
        url: postJsonUrl,
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        data: JSON.stringify(form),
        success: function (data) {

            // Log success
            console.log("Succesfully posted new call.");

            // End dispatching
            endDispatching();

        },
        error: function (jqXHR, textStatus, errorThrown) {

            // Log failure
            console.log("Failed to post new call.");
            console.log(jqXHR.responseText);

            // Show modal
            bsalert(jqXHR.responseText, 'alert-danger', 'Failure');

            // End dispatching
            endDispatching();

        }
    });
}

// patient functions

var addPatient = function(index) {

    console.log('Adding patient index ' + index);

    var name = $('#patient-' + index + '-name').val().trim();
    var age = $('#patient-' + index + '-age').val().trim();

    // is name empty?
    if (!name) {
        bsalert('Empty name');
        return;
    }

    // add name
    currentPatients[index] = [name, age];
    newPatientIndex++;

    // change button symbol
    var symbol = $('#patient-' + index + '-symbol');
    symbol.removeClass('fa-plus');
    symbol.addClass('fa-minus');

    // change button action from add to remove
    $('#patients').find('#patient-' + index + '-button')
        .off()
        .on('click', function(e) { removePatient(index); });

    // add new form
    addPatientForm(newPatientIndex);

}

var removePatient = function(index) {

    console.log('Removing patient index ' + index);

    // remove from storage
    delete currentPatients[index];

    // remove from form
    $('#patients')
        .find('#patient-' + index + '-form')
        .remove();

}

var addPatientForm = function(index) {

    // add new patient form entry
    $('#patients').append(newPatientForm(index, 'fa-plus'));

    // bind addPatient to click
    $('#patients')
        .on('click',
            '#patient-' + index + '-button',
            function(e) { addPatient(index); });

}

var newPatientForm = function(index, symbol) {

    var html =
        '
' +
            '
' +
                '<input id="patient-' + index + '-name" ' +
                       'type="text" ' +
                       'class="form-control" ' +
                       'placeholder="Name">' +
            '
' +
            '
' +
                '<input id="patient-' + index + '-age" ' +
                       'type="number" min="0" ' +
                       'class="form-control" ' +
                       'placeholder="Age">' +
            '
' +
            '
' +
                '<button class="btn btn-default new-patient" ' +
                       ' type="button" ' +
                       ' id="patient-' + index + '-button">' +
                    '' +
                '</button>' +
            '
' +
        '
';

    // console.log('html = "' + html + '"');

    return html;

}

// Ready function
$(function() {

    // connect actions to inputs

    $("#street").change(function () {

        // update coordinates?
        if ($('#update-coordinates').prop('checked'))
            updateCoordinates();

    });

    $('#update-coordinates').change(function () {

        // update coordinates?
        if ($('#update-coordinates').prop('checked'))
            updateCoordinates();

    });

    $('#update-address').change(function () {

        // update address?
        if ($('#update-address').prop('checked'))
            updateCurrentAddress(currentLocation);

    });

    $('#dispatch-form-collapse').submit(function (e) {

        // prevent normal form submission
        e.preventDefault();

        // dispatch call
        dispatchCall();

    });

});

// CSRF functions

function CSRFSafeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}<|endoftext|>