<commit_before>steal({
	src: "http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js.uncompressed.js",
	_skip: true
}, '../event.js').then(
	'./trigger',
	function(){

	// these are pre-loaded by steal -> no callback
	require(["dojo", "dojo/query", "plugd/trigger", "dojo/NodeList-dom"]);

	// String
	can.trim = function(s){
		return s && dojo.trim(s);
	}

	// Array
	can.makeArray = function(arr){
		array = [];
		dojo.forEach(arr, function(item){ array.push(item)});
		return array;
	};
	can.isArray = dojo.isArray;
	can.inArray = function(item,arr){
		return dojo.indexOf(arr, item);
	};
	can.map = function(arr, fn){
		return dojo.map(can.makeArray(arr||[]), fn);
	};
	can.each = function(elements, callback) {
    	var i, key;
	    if (typeof  elements.length == 'number' && elements.pop)
	      for(i = 0; i < elements.length; i++) {
	        if(callback(i, elements[i]) === false) return elements;
	      }
	    else
	      for(key in elements) {
	        if(callback(key, elements[key]) === false) return elements;
	      }
	    return elements;
  	}
	// Object
	can.extend = function(first){
		if(first === true){
			var args = can.makeArray(arguments);
			args.shift();
			return dojo.mixin.apply(dojo, args)
		}
		return dojo.mixin.apply(dojo, arguments)
	}
	can.param = function(object){
		return dojo.objectToQuery(object)
	}
	can.isEmptyObject = function(object){
		var prop;
		for(prop in object){
			break;
		}
		return prop === undefined;;
	}
	// Function
	can.proxy = function(func, context){
		return dojo.hitch(context, func)
	}
	can.isFunction = function(f){
		return dojo.isFunction(f);
	}
	/**
	 * EVENTS
	 *
	 * Dojo does not use the callback handler when unbinding.  Instead
	 * when binding (dojo.connect or dojo.on) an object with a remove
	 * method is returned.
	 *
	 * Because of this, we have to map each callback to the "remove"
	 * object to it can be passed to dojo.disconnect.
	 */

	// the id of the function to be bound, used as an expando on the function
	// so we can lookup it's "remove" object
	var id = 0,
		// takes a node list, goes through each node
		// and adds events data that has a map of events to
		// callbackId to "remove" object.  It looks like
		// {click: {5: {remove: fn}}}
		addBinding = function(nodelist, ev, cb){
			nodelist.forEach(function(node){
				var node = new dojo.NodeList(node)
				var events = can.data(node,"events");
				if(!events){
					can.data(node,"events", events = {})
				}
				if(!events[ev]){
					events[ev] = {};
				}
				if(cb.__bindingsIds === undefined) {
					cb.__bindingsIds=id++;
				}
				events[ev][cb.__bindingsIds] = node.on(ev, cb)[0]
			});
		},
		// removes a binding on a nodelist by finding
		// the remove object within the object's data
		removeBinding = function(nodelist,ev,cb){
			nodelist.forEach(function(node){
				var node = new dojo.NodeList(node),
					events = can.data(node,"events"),
					handlers = events[ev],
					handler = handlers[cb.__bindingsIds];

				dojo.disconnect(handler);
				delete handlers[cb.__bindingsIds];

				if(can.isEmptyObject(handlers)){
					delete events[ev]
				}
				if(can.isEmptyObject(events)){
					// clear data
				}
			});
		}

	can.bind = function( ev, cb){
		// if we can bind to it ...
		if(this.bind && this.bind !== can.bind){
			this.bind(ev, cb)

		// otherwise it's an element or node List
		} else if(this.on || this.nodeType){
			addBinding( new dojo.NodeList(this), ev, cb)
		} else if(this.addEvent) {
			this.addEvent(ev, cb)
		} else {
			// make it bind-able ...
			can.addEvent.call(this, ev, cb)
		}
		return this;
	}
	can.unbind = function(ev, cb){
		// if we can bind to it ...
		if(this.unbind && this.unbind !== can.unbind){
			this.unbind(ev, cb)
		}

		else if(this.on || this.nodeType) {
			removeBinding(new dojo.NodeList(this), ev, cb);
		} else {
			// make it bind-able ...
			can.removeEvent.call(this, ev, cb)
		}
		return this;
	}

	can.trigger = function(item, event, args, bubble){
		if(item.trigger){
			if(bubble === false){
				//  force stop propagation by
				// listening to On and then immediately disconnecting
				var connect = item.on(event, function(ev){
					ev.stopPropagation();
					dojo.disconnect(connect);
				})
				item.trigger(event,args)
			} else {
				item.trigger(event,args)
			}

		} else {
			if(typeof event === 'string'){
				event = {type: event}
			}
			event.data = args
			can.dispatch.call(item, event)
		}
	}

	can.delegate = function(selector, ev , cb){
		if(this.on || this.nodeType){
			addBinding( new dojo.NodeList(this), selector+":"+ev, cb)
		} else if(this.delegate) {
			this.delegate(selector, ev , cb)
		}
		return this;
	}
	can.undelegate = function(selector, ev , cb){
		if(this.on || this.nodeType){
			removeBinding(new dojo.NodeList(this), selector+":"+ev, cb);
		} else if(this.undelegate) {
			this.undelegate(selector, ev , cb)
		}

		return this;
	}

	/**
	 * Ajax
	 */
	var optionsMap = {
		type:"method",
		success : undefined,
		error: undefined
	}
	var updateDeferred = function(xhr, d){
		for(var prop in xhr){
			if(typeof d[prop] == 'function'){
				d[prop] = function(){
					xhr[prop].apply(xhr, arguments)
				}
			} else {
				d[prop] = prop[xhr]
			}
		}
	}

	can.ajax = function(options){
		var type = can.capitalize( (options.type || "get").toLowerCase() ),
			method = dojo["xhr"+type];
		var success = options.success,
			error = options.error,
			d = new can.Deferred();

		var def = method({
			url : options.url,
			handleAs : options.dataType,
			sync : !options.async,
			headers : options.headers,
			content: options.data
		})
		def.then(function(data, ioargs){
			updateDeferred(xhr, d);
			d.resolve(data,"success",xhr);
			success && success(data,"success",xhr);
		},function(data,ioargs){
			updateDeferred(xhr, d);
			d.reject(xhr,"error");
			error(xhr,"error");
		})

		var xhr = def.ioArgs.xhr;

		updateDeferred(xhr, d);
		return d;

	}
	// element ... get the wrapped helper
	can.$ = function(selector){
		if(selector === window){
			return window;
		}
		if(typeof selector === "string"){
			return dojo.query(selector)
		} else {
			return new dojo.NodeList(selector);
		}

	}
	can.buildFragment = function(frags, nodes){
		var owner = nodes.length && nodes[0].ownerDocument,
			frag = dojo.toDom(frags[0], owner );
		if(frag.nodeType !== 11){
			var tmp = document.createDocumentFragment();
			tmp.appendChild(frag)
			frag = tmp;
		}
		return {fragment: frag}
	}

	can.append = function(wrapped, html){
		return wrapped.forEach(function(node){
			dojo.place( html, node)
		});
	}

	/**
	 * can.data
	 *
	 * can.data is used to store arbitrary data on an element.
	 * Dojo does not support this, so we implement it itself.
	 *
	 * The important part is to call cleanData on any elements
	 * that are removed from the DOM.  For this to happen, we
	 * overwrite
	 *
	 *   -dojo.empty
	 *   -dojo.destroy
	 *   -dojo.place when "replace" is used TODO!!!!
	 *
	 * For can.Control, we also need to trigger a non bubbling event
	 * when an element is removed.  We do this also in cleanData.
	 */

	var data = {},
	    uuid = can.uuid = +new Date(),
	    exp  = can.expando = 'can' + uuid;

	function getData(node, name) {
	    var id = node[exp], store = id && data[id];
	    return name === undefined ? store || setData(node) :
	      (store && store[name]);
	}

	function setData(node, name, value) {
	    var id = node[exp] || (node[exp] = ++uuid),
	      store = data[id] || (data[id] = {});
	    if (name !== undefined) store[name] = value;
	    return store;
	};

	var cleanData = function(elems){
	  	can.trigger(new dojo.NodeList(elems),"destroyed",[],false)
	  	for ( var i = 0, elem;
			(elem = elems[i]) !== undefined; i++ ) {
				var id = elem[exp]
				delete data[id];
			}
	  }
	can.data = function(wrapped, name, value){
		return value === undefined ?
			wrapped.length == 0 ? undefined : getData(wrapped[0], name) :
			wrapped.forEach(function(node){
				setData(node, name, value);
			});
	};
	// overwrite dojo.destroy and dojo.empty and dojo.palce
	var empty = dojo.empty;
	dojo.empty = function(){
		for(var c; c = node.lastChild;){ // intentional assignment
			dojo.destroy(c);
		}
	}
	var destroy = dojo.destroy;
	dojo.destroy = function(node){
		node = dojo.byId(node);
		cleanData([node]);
		node.getElementsByTagName && cleanData(node.getElementsByTagName('*'))

		return destroy.apply(dojo, arguments);
	};

	can.addClass = function(wrapped, className){
		return wrapped.addClass(className);
	}
	can.remove = function(wrapped){
		// we need to remove text nodes ourselves
		wrapped.forEach(function(node){
			dojo.destroy(node)
		});
	}

	can.get = function(wrapped, index){
		return wrapped[index];
	}

	/* add pipe to dojo.Deferred */
	can.extend(dojo.Deferred.prototype, {
		pipe : function(done, fail){
			var d = new dojo.Deferred();
			this.addCallback(function(){
				d.resolve( done.apply(this, arguments) );
			});

			this.addErrback(function(){
				if(fail){
					d.reject( fail.apply(this, arguments) );
				} else {
					d.reject.apply(d, arguments);
				}
			});
			return d;
		}
	});

}).then('../deferred.js')<commit_msg>bug fix for 'Dojo/can/view: plugin in ejs'<commit_after>steal({
	src: "http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js.uncompressed.js",
	_skip: true
}, '../event.js').then(
	'./trigger',
	function(){

	// these are pre-loaded by steal -> no callback
	require(["dojo", "dojo/query", "plugd/trigger", "dojo/NodeList-dom"]);

	// String
	can.trim = function(s){
		return s && dojo.trim(s);
	}

	// Array
	can.makeArray = function(arr){
		array = [];
		dojo.forEach(arr, function(item){ array.push(item)});
		return array;
	};
	can.isArray = dojo.isArray;
	can.inArray = function(item,arr){
		return dojo.indexOf(arr, item);
	};
	can.map = function(arr, fn){
		return dojo.map(can.makeArray(arr||[]), fn);
	};
	can.each = function(elements, callback) {
    	var i, key;
	    if (typeof  elements.length == 'number' && elements.pop)
	      for(i = 0; i < elements.length; i++) {
	        if(callback(i, elements[i]) === false) return elements;
	      }
	    else
	      for(key in elements) {
	        if(callback(key, elements[key]) === false) return elements;
	      }
	    return elements;
  	}
	// Object
	can.extend = function(first){
		if(first === true){
			var args = can.makeArray(arguments);
			args.shift();
			return dojo.mixin.apply(dojo, args)
		}
		return dojo.mixin.apply(dojo, arguments)
	}
	can.param = function(object){
		return dojo.objectToQuery(object)
	}
	can.isEmptyObject = function(object){
		var prop;
		for(prop in object){
			break;
		}
		return prop === undefined;;
	}
	// Function
	can.proxy = function(func, context){
		return dojo.hitch(context, func)
	}
	can.isFunction = function(f){
		return dojo.isFunction(f);
	}
	/**
	 * EVENTS
	 *
	 * Dojo does not use the callback handler when unbinding.  Instead
	 * when binding (dojo.connect or dojo.on) an object with a remove
	 * method is returned.
	 *
	 * Because of this, we have to map each callback to the "remove"
	 * object to it can be passed to dojo.disconnect.
	 */

	// the id of the function to be bound, used as an expando on the function
	// so we can lookup it's "remove" object
	var id = 0,
		// takes a node list, goes through each node
		// and adds events data that has a map of events to
		// callbackId to "remove" object.  It looks like
		// {click: {5: {remove: fn}}}
		addBinding = function(nodelist, ev, cb){
			nodelist.forEach(function(node){
				var node = new dojo.NodeList(node)
				var events = can.data(node,"events");
				if(!events){
					can.data(node,"events", events = {})
				}
				if(!events[ev]){
					events[ev] = {};
				}
				if(cb.__bindingsIds === undefined) {
					cb.__bindingsIds=id++;
				}
				events[ev][cb.__bindingsIds] = node.on(ev, cb)[0]
			});
		},
		// removes a binding on a nodelist by finding
		// the remove object within the object's data
		removeBinding = function(nodelist,ev,cb){
			nodelist.forEach(function(node){
				var node = new dojo.NodeList(node),
					events = can.data(node,"events"),
					handlers = events[ev],
					handler = handlers[cb.__bindingsIds];

				dojo.disconnect(handler);
				delete handlers[cb.__bindingsIds];

				if(can.isEmptyObject(handlers)){
					delete events[ev]
				}
				if(can.isEmptyObject(events)){
					// clear data
				}
			});
		}

	can.bind = function( ev, cb){
		// if we can bind to it ...
		if(this.bind && this.bind !== can.bind){
			this.bind(ev, cb)

		// otherwise it's an element or node List
		} else if(this.on || this.nodeType){
			addBinding( new dojo.NodeList(this), ev, cb)
		} else if(this.addEvent) {
			this.addEvent(ev, cb)
		} else {
			// make it bind-able ...
			can.addEvent.call(this, ev, cb)
		}
		return this;
	}
	can.unbind = function(ev, cb){
		// if we can bind to it ...
		if(this.unbind && this.unbind !== can.unbind){
			this.unbind(ev, cb)
		}

		else if(this.on || this.nodeType) {
			removeBinding(new dojo.NodeList(this), ev, cb);
		} else {
			// make it bind-able ...
			can.removeEvent.call(this, ev, cb)
		}
		return this;
	}

	can.trigger = function(item, event, args, bubble){
		if(item.trigger){
			if(bubble === false){
				//  force stop propagation by
				// listening to On and then immediately disconnecting
				var connect = item.on(event, function(ev){
					ev.stopPropagation && ev.stopPropagation();
					dojo.disconnect(connect);
				})
				item.trigger(event,args)
			} else {
				item.trigger(event,args)
			}

		} else {
			if(typeof event === 'string'){
				event = {type: event}
			}
			event.data = args
			can.dispatch.call(item, event)
		}
	}

	can.delegate = function(selector, ev , cb){
		if(this.on || this.nodeType){
			addBinding( new dojo.NodeList(this), selector+":"+ev, cb)
		} else if(this.delegate) {
			this.delegate(selector, ev , cb)
		}
		return this;
	}
	can.undelegate = function(selector, ev , cb){
		if(this.on || this.nodeType){
			removeBinding(new dojo.NodeList(this), selector+":"+ev, cb);
		} else if(this.undelegate) {
			this.undelegate(selector, ev , cb)
		}

		return this;
	}

	/**
	 * Ajax
	 */
	var optionsMap = {
		type:"method",
		success : undefined,
		error: undefined
	}
	var updateDeferred = function(xhr, d){
		for(var prop in xhr){
			if(typeof d[prop] == 'function'){
				d[prop] = function(){
					xhr[prop].apply(xhr, arguments)
				}
			} else {
				d[prop] = prop[xhr]
			}
		}
	}

	can.ajax = function(options){
		var type = can.capitalize( (options.type || "get").toLowerCase() ),
			method = dojo["xhr"+type];
		var success = options.success,
			error = options.error,
			d = new can.Deferred();

		var def = method({
			url : options.url,
			handleAs : options.dataType,
			sync : !options.async,
			headers : options.headers,
			content: options.data
		})
		def.then(function(data, ioargs){
			updateDeferred(xhr, d);
			d.resolve(data,"success",xhr);
			success && success(data,"success",xhr);
		},function(data,ioargs){
			updateDeferred(xhr, d);
			d.reject(xhr,"error");
			error(xhr,"error");
		})

		var xhr = def.ioArgs.xhr;

		updateDeferred(xhr, d);
		return d;

	}
	// element ... get the wrapped helper
	can.$ = function(selector){
		if(selector === window){
			return window;
		}
		if(typeof selector === "string"){
			return dojo.query(selector)
		} else {
			return new dojo.NodeList(selector);
		}

	}
	can.buildFragment = function(frags, nodes){
		var owner = nodes.length && nodes[0].ownerDocument,
			frag = dojo.toDom(frags[0], owner );
		if(frag.nodeType !== 11){
			var tmp = document.createDocumentFragment();
			tmp.appendChild(frag)
			frag = tmp;
		}
		return {fragment: frag}
	}

	can.append = function(wrapped, html){
		return wrapped.forEach(function(node){
			dojo.place( html, node)
		});
	}

	/**
	 * can.data
	 *
	 * can.data is used to store arbitrary data on an element.
	 * Dojo does not support this, so we implement it itself.
	 *
	 * The important part is to call cleanData on any elements
	 * that are removed from the DOM.  For this to happen, we
	 * overwrite
	 *
	 *   -dojo.empty
	 *   -dojo.destroy
	 *   -dojo.place when "replace" is used TODO!!!!
	 *
	 * For can.Control, we also need to trigger a non bubbling event
	 * when an element is removed.  We do this also in cleanData.
	 */
	var data = {},
	    uuid = can.uuid = +new Date(),
	    exp  = can.expando = 'can' + uuid;

	function getData(node, name) {
	    var id = node[exp], store = id && data[id];
	    return name === undefined ? store || setData(node) :
	      (store && store[name]);
	}

	function setData(node, name, value) {
	    var id = node[exp] || (node[exp] = ++uuid),
	      store = data[id] || (data[id] = {});
	    if (name !== undefined) store[name] = value;
	    return store;
	};

	var cleanData = function(elems){
	  	can.trigger(new dojo.NodeList(elems),"destroyed",[],false)
	  	for ( var i = 0, elem;
			(elem = elems[i]) !== undefined; i++ ) {
				var id = elem[exp]
				delete data[id];
			}
	};

	can.data = function(wrapped, name, value){
		return value === undefined ?
			wrapped.length == 0 ? undefined : getData(wrapped[0], name) :
			wrapped.forEach(function(node){
				setData(node, name, value);
			});
	};

	// overwrite dojo.destroy and dojo.empty and dojo.palce
	var empty = dojo.empty;
	dojo.empty = function(){
		for(var c; c = node.lastChild;){ // intentional assignment
			dojo.destroy(c);
		}
	}

	var destroy = dojo.destroy;
	dojo.destroy = function(node){
		node = dojo.byId(node);
		cleanData([node]);
		node.getElementsByTagName && cleanData(node.getElementsByTagName('*'))

		return destroy.apply(dojo, arguments);
	};

	can.addClass = function(wrapped, className){
		return wrapped.addClass(className);
	}

	can.remove = function(wrapped){
		// we need to remove text nodes ourselves
		wrapped.forEach(dojo.destroy);
	}

	can.get = function(wrapped, index){
		return wrapped[index];
	}

	/* add pipe to dojo.Deferred */
	can.extend(dojo.Deferred.prototype, {
		pipe : function(done, fail){
			var d = new dojo.Deferred();
			this.addCallback(function(){
				d.resolve( done.apply(this, arguments) );
			});

			this.addErrback(function(){
				if(fail){
					d.reject( fail.apply(this, arguments) );
				} else {
					d.reject.apply(d, arguments);
				}
			});
			return d;
		}
	});

}).then('../deferred.js')<|endoftext|>


<commit_before>'use strict';

import express from 'express';
import OAuth2Server from 'oauth2-server';
import bodyParser from 'body-parser';
import basicAuth from 'basic-auth';
import redis from 'redis';
import _ from 'lodash';
import {log} from './utils';
import Model from './oauth/twolevel.model.js';
// import throttle from './throttle/throttle.middleware.js';
import {userEncode, userDecode} from './utils';

function createBasicApp(config) {
  var app = express();
  app.set('config', config);

  var storePasswordsInRedisOptions = (app.get('config').whoCaresAboutSecurityAnyway || {}).storePasswordsInRedis;
  if (storePasswordsInRedisOptions) {
    app.set('storePasswordsInRedisClient', redis.createClient(storePasswordsInRedisOptions));
  }

  app.disable('x-powered-by');
  app.set('json spaces', 2);

  app.use(bodyParser.urlencoded({extended: true}));
  app.use(bodyParser.json());

  app.get('/', function (req, res) {
    res.send('Helpful text about Smaug.');
  });

  app.get('/health', (req, res) => {
    var result = {};
    var ok = true;
    var stores = app.get('stores');

    var storePromises = Object.keys(stores).map((storeId) => {
      return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
        stores[storeId].ping()
          .then(() => {
            resolve('ok');
          })
          .catch((err) => {
            resolve(err);
          });
      });
    });

    Promise.all(storePromises).then((results) => {
      _.zip(Object.keys(stores), results).forEach((zipElem) => {
        let [storeId, status] = zipElem;
        if (status instanceof Error) {
          ok = false;
          result[storeId] = {error: {name: status.name, msg: status.message, stacktrace: status.stack}};
        }
        else {
          result[storeId] = status;
        }
      });
      if (!ok) {
        res.status(500);
      }
      res.json(result);
    });
  });

  return app;
}

export function createConfigurationApp(config) {
  var app = createBasicApp(config);

  app.get('/configuration', (req, res, next) => {
    var bearerToken = req.query.token;

    app.get('stores').tokenStore.getAccessToken(bearerToken)
      .then((tokenInfo) => {
        var user = Object.assign(userDecode(tokenInfo.userId), {clientId: tokenInfo.clientId});
        var client = {id: tokenInfo.clientId};
        return app.get('stores').configStore.get(user, client)
          .then((userConfig) => {
            var storePasswordsInRedisClient = app.get('storePasswordsInRedisClient');
            if (typeof storePasswordsInRedisClient !== 'undefined') {
              storePasswordsInRedisClient.get(tokenInfo.userId, (redisErr, redisRes) => { // eslint-disable-line no-unused-vars
                if (redisErr) {
                  return next(new Error('I\'m still a teapot'));
                }

                var insecureUser = Object.assign({}, user, {secret: redisRes});
                res.json(Object.assign({}, userConfig, {user: insecureUser}));
              });
            }
            else {
              // success
              res.json(Object.assign({}, userConfig, {user: user}));
            }
          })
          .catch((err) => {
            return next(err);
          });
      })
      .catch((err) => {
        return next(err);
      });
  });

  return app;
}

export function createOAuthApp(config = {}) {
  var app = createBasicApp(config);

  app.oauth = OAuth2Server({
    model: new Model(app),
    grants: ['password'],
    debug: true,
    accessTokenLifetime: 60*60*24*30 // 30 days
  });

  // app.use(throttle());

  // Add implicit libraryId to anonymous user without libraryId, and change the password from accordingly.
  // The password must be equal to the username for an anonymous request, and userEncode(libraryId, null) returns the proper anonymous username/password for this
  app.use('/oauth/token', (req, res, next) => {
    if (req.body.username === userEncode(null, null)) {
      if (typeof config.defaultLibraryId === 'undefined') {
        log.error('No default library id. Set config.defaultLibraryId');
      }
      else {
        req.body.username += config.defaultLibraryId;
        if (req.body.password === userEncode(null, null)) {
          req.body.password += config.defaultLibraryId;
        }
      }
    }
    next();
  });
  app.post('/oauth/token', app.oauth.grant());
  app.use(app.oauth.errorHandler());

  return app;
}

export function createApp(config = {}) {
  var app = express();

  app.use(createConfigurationApp(config));
  app.use(createOAuthApp(config));

  return app;
}

export function filterClient(client) {
  var filteredClient = Object.assign({}, client);
  delete filteredClient.secret;
  return filteredClient; // eslint-disable-line no-undefined
}

export function filterClients(clients) {
  return clients.map(filterClient);
}

export function clientWithId(client, id) {
  return Object.assign({}, client, {id: id});
}

export function createAdminApp(config = {}) {
  var app = createBasicApp(config);
  app.set('config', config);
  app.use((req, res, next) => {
    var credentials = basicAuth(req) || {};
    if (_.every([typeof credentials.name === 'string', typeof credentials.pass === 'string'])) {
      var users = (app.get('config').admin || {}).users || {};
      if (users[credentials.name] === credentials.pass) {
        return next();
      }
    }
    return res.sendStatus(403);
  });

  var clientEndpoint = express.Router();
  var configEndpoint = express.Router();

  clientEndpoint.use((req, res, next) => {
    next();
  });

  clientEndpoint.route('/')
    .get((req, res) => {
      // list clients
      app.get('stores').clientStore.getAll()
        .then(filterClients)
        .then((clients) => {
          res.json(clients);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .post((req, res) => {
      // create client
      var client = {
        name: req.body.name
      };

      app.get('stores').clientStore.create(client)
        .then(filterClient)
        .then((persistedClient) => {
          res.json(persistedClient);
        })
        .catch((err) => {
          res.json({err: err});
        });
    });

  clientEndpoint.route('/:clientId')
    .get((req, res) => {
      // get client
      app.get('stores').clientStore.get(req.params.clientId)
        .then(filterClient)
        .then((client) => {
          res.json(client);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .put((req, res) => {
      // update client
      var clientId = req.params.clientId;
      var client = {
        name: req.body.name
      };
      app.get('stores').clientStore.update(clientId, client)
        .then((persistedClient) => {
          res.json(persistedClient);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .delete((req, res) => {
      // delete client
      app.get('stores').clientStore.delete(req.params.clientId)
        .then(() => {
          res.json({});
        })
        .catch((err) => {
          res.json({err: err});
        });

    });

  configEndpoint.route('/')
    .get((req, res) => {
      res.json(app.get('config'));
    });

  app.use('/clients', clientEndpoint);
  app.use('/config', configEndpoint);
  return app;
}

export default createApp;
<commit_msg>remove X-Powered-By header when in combined mode<commit_after>'use strict';

import express from 'express';
import OAuth2Server from 'oauth2-server';
import bodyParser from 'body-parser';
import basicAuth from 'basic-auth';
import redis from 'redis';
import _ from 'lodash';
import {log} from './utils';
import Model from './oauth/twolevel.model.js';
// import throttle from './throttle/throttle.middleware.js';
import {userEncode, userDecode} from './utils';

function createBasicApp(config) {
  var app = express();
  app.set('config', config);

  var storePasswordsInRedisOptions = (app.get('config').whoCaresAboutSecurityAnyway || {}).storePasswordsInRedis;
  if (storePasswordsInRedisOptions) {
    app.set('storePasswordsInRedisClient', redis.createClient(storePasswordsInRedisOptions));
  }

  app.disable('x-powered-by');
  app.set('json spaces', 2);

  app.use(bodyParser.urlencoded({extended: true}));
  app.use(bodyParser.json());

  app.get('/', function (req, res) {
    res.send('Helpful text about Smaug.');
  });

  app.get('/health', (req, res) => {
    var result = {};
    var ok = true;
    var stores = app.get('stores');

    var storePromises = Object.keys(stores).map((storeId) => {
      return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
        stores[storeId].ping()
          .then(() => {
            resolve('ok');
          })
          .catch((err) => {
            resolve(err);
          });
      });
    });

    Promise.all(storePromises).then((results) => {
      _.zip(Object.keys(stores), results).forEach((zipElem) => {
        let [storeId, status] = zipElem;
        if (status instanceof Error) {
          ok = false;
          result[storeId] = {error: {name: status.name, msg: status.message, stacktrace: status.stack}};
        }
        else {
          result[storeId] = status;
        }
      });
      if (!ok) {
        res.status(500);
      }
      res.json(result);
    });
  });

  return app;
}

export function createConfigurationApp(config) {
  var app = createBasicApp(config);

  app.get('/configuration', (req, res, next) => {
    var bearerToken = req.query.token;

    app.get('stores').tokenStore.getAccessToken(bearerToken)
      .then((tokenInfo) => {
        var user = Object.assign(userDecode(tokenInfo.userId), {clientId: tokenInfo.clientId});
        var client = {id: tokenInfo.clientId};
        return app.get('stores').configStore.get(user, client)
          .then((userConfig) => {
            var storePasswordsInRedisClient = app.get('storePasswordsInRedisClient');
            if (typeof storePasswordsInRedisClient !== 'undefined') {
              storePasswordsInRedisClient.get(tokenInfo.userId, (redisErr, redisRes) => { // eslint-disable-line no-unused-vars
                if (redisErr) {
                  return next(new Error('I\'m still a teapot'));
                }

                var insecureUser = Object.assign({}, user, {secret: redisRes});
                res.json(Object.assign({}, userConfig, {user: insecureUser}));
              });
            }
            else {
              // success
              res.json(Object.assign({}, userConfig, {user: user}));
            }
          })
          .catch((err) => {
            return next(err);
          });
      })
      .catch((err) => {
        return next(err);
      });
  });

  return app;
}

export function createOAuthApp(config = {}) {
  var app = createBasicApp(config);

  app.oauth = OAuth2Server({
    model: new Model(app),
    grants: ['password'],
    debug: true,
    accessTokenLifetime: 60*60*24*30 // 30 days
  });

  // app.use(throttle());

  // Add implicit libraryId to anonymous user without libraryId, and change the password from accordingly.
  // The password must be equal to the username for an anonymous request, and userEncode(libraryId, null) returns the proper anonymous username/password for this
  app.use('/oauth/token', (req, res, next) => {
    if (req.body.username === userEncode(null, null)) {
      if (typeof config.defaultLibraryId === 'undefined') {
        log.error('No default library id. Set config.defaultLibraryId');
      }
      else {
        req.body.username += config.defaultLibraryId;
        if (req.body.password === userEncode(null, null)) {
          req.body.password += config.defaultLibraryId;
        }
      }
    }
    next();
  });
  app.post('/oauth/token', app.oauth.grant());
  app.use(app.oauth.errorHandler());

  return app;
}

export function createApp(config = {}) {
  var app = express();
  app.disable('x-powered-by');

  app.use(createConfigurationApp(config));
  app.use(createOAuthApp(config));

  return app;
}

export function filterClient(client) {
  var filteredClient = Object.assign({}, client);
  delete filteredClient.secret;
  return filteredClient; // eslint-disable-line no-undefined
}

export function filterClients(clients) {
  return clients.map(filterClient);
}

export function clientWithId(client, id) {
  return Object.assign({}, client, {id: id});
}

export function createAdminApp(config = {}) {
  var app = createBasicApp(config);
  app.set('config', config);
  app.use((req, res, next) => {
    var credentials = basicAuth(req) || {};
    if (_.every([typeof credentials.name === 'string', typeof credentials.pass === 'string'])) {
      var users = (app.get('config').admin || {}).users || {};
      if (users[credentials.name] === credentials.pass) {
        return next();
      }
    }
    return res.sendStatus(403);
  });

  var clientEndpoint = express.Router();
  var configEndpoint = express.Router();

  clientEndpoint.use((req, res, next) => {
    next();
  });

  clientEndpoint.route('/')
    .get((req, res) => {
      // list clients
      app.get('stores').clientStore.getAll()
        .then(filterClients)
        .then((clients) => {
          res.json(clients);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .post((req, res) => {
      // create client
      var client = {
        name: req.body.name
      };

      app.get('stores').clientStore.create(client)
        .then(filterClient)
        .then((persistedClient) => {
          res.json(persistedClient);
        })
        .catch((err) => {
          res.json({err: err});
        });
    });

  clientEndpoint.route('/:clientId')
    .get((req, res) => {
      // get client
      app.get('stores').clientStore.get(req.params.clientId)
        .then(filterClient)
        .then((client) => {
          res.json(client);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .put((req, res) => {
      // update client
      var clientId = req.params.clientId;
      var client = {
        name: req.body.name
      };
      app.get('stores').clientStore.update(clientId, client)
        .then((persistedClient) => {
          res.json(persistedClient);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .delete((req, res) => {
      // delete client
      app.get('stores').clientStore.delete(req.params.clientId)
        .then(() => {
          res.json({});
        })
        .catch((err) => {
          res.json({err: err});
        });

    });

  configEndpoint.route('/')
    .get((req, res) => {
      res.json(app.get('config'));
    });

  app.use('/clients', clientEndpoint);
  app.use('/config', configEndpoint);
  return app;
}

export default createApp;
<|endoftext|>


<commit_before>var Backbone = require('backbone');

module.exports = Backbone.Model.extend({
    defaults: {
        active: false,
        selected: false,
    },

    urlRoot: '/place',

    getGeoUrl: function () {
        return 'geo:' + this.get('latitude') + ',' + this.get('longitude');
    },
});
<commit_msg>GEO URL with search query, mark place in map application. #87<commit_after>var Backbone = require('backbone');

module.exports = Backbone.Model.extend({
    defaults: {
        active: false,
        selected: false,
    },

    urlRoot: '/place',

    getGeoUrl: function () {
        return 'geo:' + this.get('latitude') + ',' + this.get('longitude') + '?z=10&q=' + this.get('address');
    },
});
<|endoftext|>


<commit_before>/*
 * jQuery UI Selectmenu @VERSION
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectmenu
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 *	jquery.ui.menu.js
 *	jquery.ui.button.js
 */
(function( $, undefined ) {

$.widget( "ui.selectmenu", {
	version: "@VERSION",
	defaultElement: "<select>",
	options: {
		dropdown: true,
		iconWidth: 26,
		wrapperElement: "
",
		appendTo: "body",
		position: {
			my: "left top",
			at: "left bottom",
			collision: "none"
		},
		source: null,
		value: null,
		// callbacks
		open: null,
		focus: null,
		select: null,
		close: null,
		// change: null,
	},

	_create: function() {
		var self = this,
			options = this.options,
			tabindex = this.element.attr( 'tabindex' )
			// set a default id value, generate a new random one if not set by developer
			selectmenuId = self.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 );

		// quick array of button and menu id's
		self.ids = [ selectmenuId + '-button', selectmenuId + '-menu' ];

		// get options
		self.items = self.element.find( 'option' );

		// set options value
		options.value = self.element[0].value;

		// catch click event of the label
		self.element.bind( 'click.selectmenu',  function() {
			self.newelement.focus();
			return false;
		})
		.hide();

		// create button
		self.newelement = $( '', {
				href: '#' + selectmenuId,
				tabindex: ( tabindex ? tabindex : self.element.attr( 'disabled' ) ? 1 : 0 ),
				id: self.ids[ 0 ],
				css: {
					width: self.element.width()
				},
				'aria-owns': self.ids[ 1 ],
				'aria-haspopup': true
			})
			.addClass( self.widgetBaseClass + '-button' )
			.button({
				label: self.items.eq( this.element[0].selectedIndex ).text(),
				icons: {
					primary: ( options.dropdown ? 'ui-icon-triangle-1-s' : 'ui-icon-triangle-2-n-s' )
				}
			});

		self.newelementWrap = $( options.wrapperElement )
			.append( self.newelement )
			.insertAfter( self.element );

		self.newelement
			.bind( 'mousedown.selectmenu' , function( event ) {
				self._toggle( event );
				return false;
			})
			.bind( 'click.selectmenu' , function() {
				return false;
			})
			.bind( 'keydown.selectmenu', function( event ) {
				var ret = false;
				switch (event.keyCode) {
					case $.ui.keyCode.TAB:
					case $.ui.keyCode.ENTER:
						ret = true;
						break;
					case $.ui.keyCode.SPACE:
						self._toggle(event);
						break;
					case $.ui.keyCode.UP:
						if ( event.altKey ) {
							self._toggle( event );
						} else {
							self._previous();
						}
						break;
					case $.ui.keyCode.DOWN:
						if ( event.altKey ) {
							self._toggle( event );
						} else {
							self._next();
						}
						break;
					case $.ui.keyCode.LEFT:
						self._previous();
						break;
					case $.ui.keyCode.RIGHT:
						self._next();
						break;
					default:
						self.list.trigger( event );
				}
				return ret;
			});

		// built menu
		self.refresh();

		// document click closes menu
		$( document ).bind( 'mousedown.selectmenu', function( event ) {
			if ( self.opened && !self.hover) {
				window.setTimeout( function() {
					self.close( event );
				}, 200 );
			}
		});

	},

	refresh: function() {
		var self = this,
			options = this.options;

		// create menu portion, append to body
		self.list = $( '
', {
			'class': 'ui-widget ui-widget-content',
			'aria-hidden': true,
			'aria-labelledby': self.ids[0],
			role: 'listbox',
			id: self.ids[1],
		});

		self.listWrap = $( options.wrapperElement )
			.addClass( self.widgetBaseClass + '-menu' )
			.css( "width", ( options.dropdown ) ? self.element.width() : self.element.width() - options.iconWidth )
			.append( self.list )
			.appendTo( options.appendTo );

		self._initSource();
		self._renderMenu( self.list, options.source );

		self.list
			.data( 'element.selectelemenu', self.element )
			.menu({
				select: function( event, ui ) {
					var item = ui.item.data( "item.selectmenu" );
					self._setSelected( event, item );
					item.element = $ ( self.items[ item.index ] );
					self._trigger( "select", event, { item: item } );
					self.close( event, true);
				},
				focus: function( event, ui ) {
					var item = ui.item.data( "item.selectmenu" );
					if ( !self.opened ) self._setSelected( event, item );
					self._trigger( "focus", event, { item: item } );
				}
			})
			.bind( 'mouseenter.selectelemenu', function() {
				self.hover = true;
			})
			.bind( 'mouseleave .selectelemenu', function() {
				self.hover = false;
			});

		if ( options.dropdown ) {
			self.list
				.addClass( 'ui-corner-bottom' )
				.removeClass( 'ui-corner-all' );
		}
	},

	open: function( event ) {
		var self = this,
			options = this.options,
			currentItem = self._getSelectedItem();

		// close all other selectmenus
		$( '.' + self.widgetBaseClass + '-open' ).not( self.newelement ).each( function() {
			$( this ).children( 'ul.ui-menu' ).data( 'element.selectelemenu' ).selectmenu( 'close' );
		});

		if ( options.dropdown ) {
			self.newelement
				.addClass( 'ui-corner-top' )
				.removeClass( 'ui-corner-all' );
		}

		self.listWrap.addClass( self.widgetBaseClass + '-open' );
		self.list.focus().menu( "focus", null, currentItem );

		if ( !options.dropdown ) {
			// center current item
			if ( self.list.css("overflow") == "auto" ) {
				self.list.scrollTop( self.list.scrollTop() + currentItem.position().top - self.list.outerHeight()/2 + currentItem.outerHeight()/2 );
			}
			// calculate offset
			var _offset = (self.list.offset().top  - currentItem.offset().top + (self.newelement.outerHeight() - currentItem.outerHeight()) / 2);
			$.extend( options.position, {
				my: "left top",
				at: "left top",
				offset: "0 " + _offset
			});
		}

		self.listWrap.position( $.extend({
			of: this.newelementWrap
		}, options.position ));

		this.opened = true;
		self._trigger( "open", event );
	},

	close: function( event, focus ) {
		var self = this,
			options = this.options;

		if ( options.dropdown ) {
			self.newelement
				.addClass( 'ui-corner-all' )
				.removeClass( 'ui-corner-top' );
		}

		self.listWrap.removeClass( self.widgetBaseClass + '-open' );
		this.opened = false;

		if (focus) self.newelement.focus();

		self._trigger( "close", event );
	},

	_renderMenu: function( ul, items ) {
		var self = this,
			currentOptgroup = "";

		$.each( items, function( index, item ) {
			if ( item.optgroup != currentOptgroup ) {
				var optgroup = $( '
' + item.optgroup + '
' );
				if ( $( self.items[ item.index ] ).parent( "optgroup" ).attr( "disabled" ) ) optgroup.addClass( 'ui-state-disabled' );
				ul.append( optgroup );
				currentOptgroup = item.optgroup;
			}
			self._renderItem( ul, item );
		});
	},

	_renderItem: function( ul, item) {
		return $( "
" )
			.addClass( ( item.disabled ) ? 'ui-state-disabled' : '' )
			.data( "item.selectmenu", item )
			.append( $( "", {
					text: item.label,
					href: '#',
					click: function( event ) {
						event.preventDefault();
					}
				})
			).appendTo( ul );
	},

	_previous: function() {
		this.list.menu( "focus", null, this._getSelectedItem() );
		this.list.menu("previous");
	},

	_next: function() {
		this.list.menu( "focus", null, this._getSelectedItem() );
		this.list.menu("next");
	},

	_getSelectedItem: function() {
		return this.list.find( "li" ).not( '.ui-selectmenu-optgroup' ).eq( this.element[0].selectedIndex );
	},

	_setSelected: function( event, item ) {
		this.newelement.children( '.ui-button-text' ).text( item.label );
		this.element[0].selectedIndex = item.index;
		this.options.value = item.value;
	},

	_toggle: function( event ) {
		if ( this.opened ) {
			this.close( event );
		} else {
			this.open( event );
		}
	},

	_setOption: function( key, value ) {
		this._super( "_setOption", key, value );
		if ( key === "appendTo" ) {
			this.listWrap.appendTo( $( value || "body", this.element[0].ownerDocument )[0] );
		}
		if ( key === "value" && value) {
			this.element[0].value = value;
		}
	},

	_initSource: function() {
		if ( !$.isArray( this.options.source ) ) {
			var data = [];
			$.each( this.items, function( index, item ) {
				var option = $( item ),
					optgroup = option.parent( "optgroup" );
				data.push({
					index: index,
					value: option.attr( 'value' ),
					label: option.text(),
					optgroup: optgroup.attr("label") || false,
					disabled: optgroup.attr( "disabled" ) || option.attr( "disabled" )
				});
			});
			this.options.source = data;
		}
	},

	_destroy: function() {
	}
});

}( jQuery ));
<commit_msg>Selectmenu: added destroy method<commit_after>/*
 * jQuery UI Selectmenu @VERSION
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectmenu
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 *	jquery.ui.menu.js
 *	jquery.ui.button.js
 */
(function( $, undefined ) {

$.widget( "ui.selectmenu", {
	version: "@VERSION",
	defaultElement: "<select>",
	options: {
		dropdown: true,
		iconWidth: 26,
		wrapperElement: "
",
		appendTo: "body",
		position: {
			my: "left top",
			at: "left bottom",
			collision: "none"
		},
		source: null,
		value: null,
		// callbacks
		open: null,
		focus: null,
		select: null,
		close: null,
		// change: null,
	},

	_create: function() {
		var self = this,
			options = this.options,
			tabindex = this.element.attr( 'tabindex' )
			// set a default id value, generate a new random one if not set by developer
			selectmenuId = self.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 );

		// quick array of button and menu id's
		self.ids = [ selectmenuId + '-button', selectmenuId + '-menu' ];

		// get options
		self.items = self.element.find( 'option' );

		// set options value
		options.value = self.element[0].value;

		// catch click event of the label
		self.element.bind( 'click.selectmenu',  function() {
			self.newelement.focus();
			return false;
		})
		.hide();

		// create button
		self.newelement = $( '', {
				href: '#' + selectmenuId,
				tabindex: ( tabindex ? tabindex : self.element.attr( 'disabled' ) ? 1 : 0 ),
				id: self.ids[ 0 ],
				css: {
					width: self.element.width()
				},
				'aria-owns': self.ids[ 1 ],
				'aria-haspopup': true
			})
			.addClass( self.widgetBaseClass + '-button' )
			.button({
				label: self.items.eq( this.element[0].selectedIndex ).text(),
				icons: {
					primary: ( options.dropdown ? 'ui-icon-triangle-1-s' : 'ui-icon-triangle-2-n-s' )
				}
			});

		self.newelementWrap = $( options.wrapperElement )
			.append( self.newelement )
			.insertAfter( self.element );

		self.newelement
			.bind( 'mousedown.selectmenu' , function( event ) {
				self._toggle( event );
				return false;
			})
			.bind( 'click.selectmenu' , function() {
				return false;
			})
			.bind( 'keydown.selectmenu', function( event ) {
				var ret = false;
				switch (event.keyCode) {
					case $.ui.keyCode.TAB:
					case $.ui.keyCode.ENTER:
						ret = true;
						break;
					case $.ui.keyCode.SPACE:
						self._toggle(event);
						break;
					case $.ui.keyCode.UP:
						if ( event.altKey ) {
							self._toggle( event );
						} else {
							self._previous();
						}
						break;
					case $.ui.keyCode.DOWN:
						if ( event.altKey ) {
							self._toggle( event );
						} else {
							self._next();
						}
						break;
					case $.ui.keyCode.LEFT:
						self._previous();
						break;
					case $.ui.keyCode.RIGHT:
						self._next();
						break;
					default:
						self.list.trigger( event );
				}
				return ret;
			});

		// built menu
		self.refresh();

		// document click closes menu
		$( document ).bind( 'mousedown.selectmenu', function( event ) {
			if ( self.opened && !self.hover) {
				window.setTimeout( function() {
					self.close( event );
				}, 200 );
			}
		});

	},

	refresh: function() {
		var self = this,
			options = this.options;

		// create menu portion, append to body
		self.list = $( '
', {
			'class': 'ui-widget ui-widget-content',
			'aria-hidden': true,
			'aria-labelledby': self.ids[0],
			role: 'listbox',
			id: self.ids[1],
		});

		self.listWrap = $( options.wrapperElement )
			.addClass( self.widgetBaseClass + '-menu' )
			.css( "width", ( options.dropdown ) ? self.element.width() : self.element.width() - options.iconWidth )
			.append( self.list )
			.appendTo( options.appendTo );

		self._initSource();
		self._renderMenu( self.list, options.source );

		self.list
			.data( 'element.selectelemenu', self.element )
			.menu({
				select: function( event, ui ) {
					var item = ui.item.data( "item.selectmenu" );
					self._setSelected( event, item );
					item.element = $ ( self.items[ item.index ] );
					self._trigger( "select", event, { item: item } );
					self.close( event, true);
				},
				focus: function( event, ui ) {
					var item = ui.item.data( "item.selectmenu" );
					if ( !self.opened ) self._setSelected( event, item );
					self._trigger( "focus", event, { item: item } );
				}
			})
			.bind( 'mouseenter.selectelemenu', function() {
				self.hover = true;
			})
			.bind( 'mouseleave .selectelemenu', function() {
				self.hover = false;
			});

		if ( options.dropdown ) {
			self.list
				.addClass( 'ui-corner-bottom' )
				.removeClass( 'ui-corner-all' );
		}
	},

	open: function( event ) {
		var self = this,
			options = this.options,
			currentItem = self._getSelectedItem();

		// close all other selectmenus
		$( '.' + self.widgetBaseClass + '-open' ).not( self.newelement ).each( function() {
			$( this ).children( 'ul.ui-menu' ).data( 'element.selectelemenu' ).selectmenu( 'close' );
		});

		if ( options.dropdown ) {
			self.newelement
				.addClass( 'ui-corner-top' )
				.removeClass( 'ui-corner-all' );
		}

		self.listWrap.addClass( self.widgetBaseClass + '-open' );
		self.list.focus().menu( "focus", null, currentItem );

		if ( !options.dropdown ) {
			// center current item
			if ( self.list.css("overflow") == "auto" ) {
				self.list.scrollTop( self.list.scrollTop() + currentItem.position().top - self.list.outerHeight()/2 + currentItem.outerHeight()/2 );
			}
			// calculate offset
			var _offset = (self.list.offset().top  - currentItem.offset().top + (self.newelement.outerHeight() - currentItem.outerHeight()) / 2);
			$.extend( options.position, {
				my: "left top",
				at: "left top",
				offset: "0 " + _offset
			});
		}

		self.listWrap.position( $.extend({
			of: this.newelementWrap
		}, options.position ));

		this.opened = true;
		self._trigger( "open", event );
	},

	close: function( event, focus ) {
		var self = this,
			options = this.options;

		if ( options.dropdown ) {
			self.newelement
				.addClass( 'ui-corner-all' )
				.removeClass( 'ui-corner-top' );
		}

		self.listWrap.removeClass( self.widgetBaseClass + '-open' );
		this.opened = false;

		if (focus) self.newelement.focus();

		self._trigger( "close", event );
	},

	_renderMenu: function( ul, items ) {
		var self = this,
			currentOptgroup = "";

		$.each( items, function( index, item ) {
			if ( item.optgroup != currentOptgroup ) {
				var optgroup = $( '
' + item.optgroup + '
' );
				if ( $( self.items[ item.index ] ).parent( "optgroup" ).attr( "disabled" ) ) optgroup.addClass( 'ui-state-disabled' );
				ul.append( optgroup );
				currentOptgroup = item.optgroup;
			}
			self._renderItem( ul, item );
		});
	},

	_renderItem: function( ul, item) {
		return $( "
" )
			.addClass( ( item.disabled ) ? 'ui-state-disabled' : '' )
			.data( "item.selectmenu", item )
			.append( $( "", {
					text: item.label,
					href: '#',
					click: function( event ) {
						event.preventDefault();
					}
				})
			).appendTo( ul );
	},

	_previous: function() {
		this.list.menu( "focus", null, this._getSelectedItem() );
		this.list.menu("previous");
	},

	_next: function() {
		this.list.menu( "focus", null, this._getSelectedItem() );
		this.list.menu("next");
	},

	_getSelectedItem: function() {
		return this.list.find( "li" ).not( '.ui-selectmenu-optgroup' ).eq( this.element[0].selectedIndex );
	},

	_setSelected: function( event, item ) {
		this.newelement.children( '.ui-button-text' ).text( item.label );
		this.element[0].selectedIndex = item.index;
		this.options.value = item.value;
	},

	_toggle: function( event ) {
		if ( this.opened ) {
			this.close( event );
		} else {
			this.open( event );
		}
	},

	_setOption: function( key, value ) {
		this._super( "_setOption", key, value );
		if ( key === "appendTo" ) {
			this.listWrap.appendTo( $( value || "body", this.element[0].ownerDocument )[0] );
		}
		if ( key === "value" && value) {
			this.element[0].value = value;
		}
	},

	_initSource: function() {
		if ( !$.isArray( this.options.source ) ) {
			var data = [];
			$.each( this.items, function( index, item ) {
				var option = $( item ),
					optgroup = option.parent( "optgroup" );
				data.push({
					index: index,
					value: option.attr( 'value' ),
					label: option.text(),
					optgroup: optgroup.attr("label") || false,
					disabled: optgroup.attr( "disabled" ) || option.attr( "disabled" )
				});
			});
			this.options.source = data;
		}
	},

	_destroy: function() {
		this.listWrap.remove();
		this.newelementWrap.remove();
		this.element.show().unbind( '.selectmenu' );
		$( document ).unbind( '.selectmenu' );
	}
});

}( jQuery ));
<|endoftext|>


<commit_before>var config;
var models;
var apiModel = require('./apiModel.js');
//var logger = require('../services/logger.js');

function getRoutes(req, res) {
    var urls = [];
    var apiRoutes = apiModel.routes;
    for (var route in apiRoutes) {
        if (!apiRoutes[route]) { continue; }
        var url = {};
        url[route] = {
            'description': apiRoutes[route].description
            , 'parameters': apiRoutes[route].parameters
        };

        urls.push(url);
    }

    res.json(urls);
}

function setup(app, cfg) {
    config = cfg || require('../config.json');
    models = models || cfg.models;

    apiModel.routeRegistered.on('registeredSuccessfully', function(route) {
        if (!route.method) {
            // throw error
        } else {
            preRegisterRoute(route);
            app[route.method](route.pattern, route.handler);
        }
    });

    apiModel.routeRegisteredError.on('registrationError', function(route) {
        throw new Error('Unable to register route:', route);
    });

    setupRoutes();
}

function preRegisterRoute(route) {
    var tempRoute = route;

    if (config.logRouteRegistration) {
        logger.info(JSON.stringify(tempRoute));
    }
}

function setupRoutes() {
    for (var prop in models) {
        if (models[prop]) {
            models[prop].init(apiModel);
        }
    }
    //Not sure if these should be in this class
    //apiModel.registerPublicRoute('get', 'displayCurrentVersion', '', currentVersion, null, 'Gets the current API version information.');
    apiModel.registerPublicRoute('get', 'displayAvailableRoutes', '/routes/', getRoutes, null, 'Displays the available routes.');
}

exports.setup = setup;
exports.models = models;<commit_msg>Error handling is handled in apiModel<commit_after>var config;
var models;
var apiModel = require('./apiModel.js');
//var logger = require('../services/logger.js');

function getRoutes(req, res) {
    var urls = [];
    var apiRoutes = apiModel.routes;
    for (var route in apiRoutes) {
        if (!apiRoutes[route]) { continue; }
        var url = {};
        url[route] = {
            'description': apiRoutes[route].description
            , 'parameters': apiRoutes[route].parameters
        };

        urls.push(url);
    }

    res.json(urls);
}

function setup(app, cfg) {
    config = cfg || require('../config.json');
    models = models || cfg.models;

    apiModel.routeRegistered.on('registeredSuccessfully', function(route) {
        preRegisterRoute(route);
        app[route.method](route.pattern, route.handler);
    });

    apiModel.routeRegisteredError.on('registrationError', function(route) {
        throw new Error('Unable to register route:', route);
    });

    setupRoutes();
}

function preRegisterRoute(route) {
    var tempRoute = route;

    if (config.logRouteRegistration) {
        logger.info(JSON.stringify(tempRoute));
    }
}

function setupRoutes() {
    for (var prop in models) {
        if (models[prop]) {
            models[prop].init(apiModel);
        }
    }
    //Not sure if these should be in this class
    //apiModel.registerPublicRoute('get', 'displayCurrentVersion', '', currentVersion, null, 'Gets the current API version information.');
    apiModel.registerPublicRoute('get', 'displayAvailableRoutes', '/routes/', getRoutes, null, 'Displays the available routes.');
}

exports.setup = setup;
exports.models = models;<|endoftext|>


<commit_before>const initializeAllRSS = require('../rss/initializeall.js')
const startFeedSchedule = require('../util/startFeedSchedule.js')
const configChecks = require('../util/configCheck.js')
const sqlCmds = require('../rss/sql/commands.js')
const sqlConnect = require('../rss/sql/connect.js')
const fileOps = require('./updateJSON.js')
const fs = require('fs')

module.exports = function (bot) {

  var guildList = []
  var skippedFeeds = 0
  var initializedFeeds = 0
  var totalFeeds = 0

  var con;

  function isEmptyObject(obj) {
      for(var prop in obj) {
          if(obj.hasOwnProperty(prop))
              return false;
      }
      return JSON.stringify(obj) === JSON.stringify({});
  }

  function roleCheck (guildId, rssIndex) {
    var guildRss = require(`../sources/${guildId}.json`)
    var rssList = guildRss.sources
    var guild = bot.guilds.get(guildId)
    var changedInfo = false

    if (rssList[rssIndex].roleSubscriptions != null && rssList[rssIndex].roleSubscriptions.length !== 0) {
      var globalSubList = rssList[rssIndex].roleSubscriptions;
      for (let roleIndex in globalSubList) {
        var role = globalSubList[roleIndex]
        if (guild.roles.get(role.roleID) == null) {
          console.log(`RSS Warning: (${guild.id}, ${guild.name}) => Role (${role.roleID}, ${role.roleName}) not found.`);
          changedInfo = true;
        }
        else if (guild.roles.get(role.roleID).name !== role.roleName) {
          console.log(`RSS Info: (${guild.id}, ${guild.name}) => Role (${role.roleID}, ${role.roleName}) => Changed role name to ${guild.roles.get(role.roleID).name}`);
          role.roleName = guild.roles.get(role.roleID).name;
          changedInfo = true;
        }
      }
    }

    if (rssList[rssIndex].filters != null && rssList[rssIndex].filters.roleSubscriptions != null && !isEmptyObject(rssList[rssIndex].filters.roleSubscriptions)) {
      let filteredSubList = rssList[rssIndex].filters.roleSubscriptions
      for (let roleID in filteredSubList) {
        if (guild.roles.get(roleID) == null) {
          console.log(`RSS Warning: (${guild.id}, ${guild.name}) => Role (${role.roleID}, ${role.roleName}) not found.`);
          changedInfo = true;
        }
        else if (guild.roles.get(roleID).name !== filteredSubList[roleID].roleName) {
          console.log(`RSS Info: (${guild.id}, ${guild.name}) => Role (${role.roleID}, ${role.roleName}) => Changed role name to ${guild.roles.get(role.roleID).name}`);
          filteredSubList[roleID].roleName = guild.roles.get(roleID).name;
          changedInfo = true;
        }
      }
    }

    if (changedInfo) return fileOps.updateFile(`./sources/${guildId}.json`, guildRss, `../sources/${guildId}.json`);
    else return;

  }

  function endCon () {
    sqlCmds.end(con, function(err) {
      console.log("RSS Info: Finished initialization cycle.")
    });
    startFeedSchedule(bot);
  }

  function start () {
    console.log("RSS Info: Starting initialization cycle.")
    con = sqlConnect(startBot);
    if (con == null) throw "RSS Error: SQL type is not correctly defined in config";
  }

  function startBot () {
    for (var guildIndex in guildList) {
      let guildId = guildList[guildIndex].id
      let rssList = guildList[guildIndex].sources
      for (var rssIndex in rssList){
        roleCheck(guildId, rssIndex);
        if (configChecks.checkExists(guildId, rssIndex, true, true) && configChecks.validChannel(bot, guildId, rssIndex) !== false) {
          initializeAllRSS(con, configChecks.validChannel(bot, guildId, rssIndex), rssIndex, function() {
            initializedFeeds++;
            if (initializedFeeds + skippedFeeds == totalFeeds) endCon();
          });
        }
        else skippedFeeds++;
      }
    }
    if (skippedFeeds == totalFeeds) endCon();
  }

  fs.readdir('./sources', function(err, files) {
    if (err) throw err;
    files.forEach(function(guildRSS) {
      if (bot.guilds.get(guildRSS.replace(/.json/g, "")) != null) {
        let guild = require(`../sources/${guildRSS}`)
        guildList.push(guild);
        for (var y in guild.sources) totalFeeds++;
      }
      else if (guildRSS !== "guild_id_here.json"){
        console.log(`RSS Guild Info: ${guildRSS} was not found in bot's guild list. Skipping.`);
      }
    })
    if (totalFeeds == 0) {
      console.log("RSS Info: There are no active feeds.");
      return startFeedSchedule(bot);
    }
    else return start();
  })

}
<commit_msg>fixed crash with role checking<commit_after>const initializeAllRSS = require('../rss/initializeall.js')
const startFeedSchedule = require('../util/startFeedSchedule.js')
const configChecks = require('../util/configCheck.js')
const sqlCmds = require('../rss/sql/commands.js')
const sqlConnect = require('../rss/sql/connect.js')
const fileOps = require('./updateJSON.js')
const fs = require('fs')

module.exports = function (bot) {

  var guildList = []
  var skippedFeeds = 0
  var initializedFeeds = 0
  var totalFeeds = 0

  var con;

  function isEmptyObject(obj) {
      for(var prop in obj) {
          if(obj.hasOwnProperty(prop))
              return false;
      }
      return JSON.stringify(obj) === JSON.stringify({});
  }

  function roleCheck (guildId, rssIndex) {
    var guildRss = require(`../sources/${guildId}.json`)
    var rssList = guildRss.sources
    var guild = bot.guilds.get(guildId)
    var changedInfo = false

    if (rssList[rssIndex].roleSubscriptions != null && rssList[rssIndex].roleSubscriptions.length !== 0) {
      var globalSubList = rssList[rssIndex].roleSubscriptions;
      for (let roleIndex in globalSubList) {
        var role = globalSubList[roleIndex]
        if (guild.roles.get(role.roleID) == null) {
          console.log(`RSS Warning: (${guild.id}, ${guild.name}) => Role (${role.roleID}, ${role.roleName}) not found.`);
          changedInfo = true;
        }
        else if (guild.roles.get(role.roleID).name !== role.roleName) {
          console.log(`RSS Info: (${guild.id}, ${guild.name}) => Role (${role.roleID}, ${role.roleName}) => Changed role name to ${guild.roles.get(role.roleID).name}`);
          role.roleName = guild.roles.get(role.roleID).name;
          changedInfo = true;
        }
      }
    }

    if (rssList[rssIndex].filters != null && rssList[rssIndex].filters.roleSubscriptions != null && !isEmptyObject(rssList[rssIndex].filters.roleSubscriptions)) {
      let filteredSubList = rssList[rssIndex].filters.roleSubscriptions
      for (let roleID in filteredSubList) {
        if (guild.roles.get(roleID) == null) {
          console.log(`RSS Warning: (${guild.id}, ${guild.name}) => Role (${role.roleID}, ${role.roleName}) not found.`);
          changedInfo = true;
        }
        else if (guild.roles.get(roleID).name !== filteredSubList[roleID].roleName) {
          console.log(`RSS Info: (${guild.id}, ${guild.name}) => Role (${roleID}, ${filteredSubList[roleID].roleName}) => Changed role name to ${guild.roles.get(roleID).name}`);
          filteredSubList[roleID].roleName = guild.roles.get(roleID).name;
          changedInfo = true;
        }
      }
    }

    if (changedInfo) return fileOps.updateFile(`./sources/${guildId}.json`, guildRss, `../sources/${guildId}.json`);
    else return;

  }

  function endCon () {
    sqlCmds.end(con, function(err) {
      console.log("RSS Info: Finished initialization cycle.")
    });
    startFeedSchedule(bot);
  }

  function start () {
    console.log("RSS Info: Starting initialization cycle.")
    con = sqlConnect(startBot);
    if (con == null) throw "RSS Error: SQL type is not correctly defined in config";
  }

  function startBot () {
    for (var guildIndex in guildList) {
      let guildId = guildList[guildIndex].id
      let rssList = guildList[guildIndex].sources
      for (var rssIndex in rssList){
        roleCheck(guildId, rssIndex);
        if (configChecks.checkExists(guildId, rssIndex, true, true) && configChecks.validChannel(bot, guildId, rssIndex) !== false) {
          initializeAllRSS(con, configChecks.validChannel(bot, guildId, rssIndex), rssIndex, function() {
            initializedFeeds++;
            if (initializedFeeds + skippedFeeds == totalFeeds) endCon();
          });
        }
        else skippedFeeds++;
      }
    }
    if (skippedFeeds == totalFeeds) endCon();
  }

  fs.readdir('./sources', function(err, files) {
    if (err) throw err;
    files.forEach(function(guildRSS) {
      if (bot.guilds.get(guildRSS.replace(/.json/g, "")) != null) {
        let guild = require(`../sources/${guildRSS}`)
        guildList.push(guild);
        for (var y in guild.sources) totalFeeds++;
      }
      else if (guildRSS !== "guild_id_here.json"){
        console.log(`RSS Guild Info: ${guildRSS} was not found in bot's guild list. Skipping.`);
      }
    })
    if (totalFeeds == 0) {
      console.log("RSS Info: There are no active feeds.");
      return startFeedSchedule(bot);
    }
    else return start();
  })

}
<|endoftext|>


<commit_before>/*global $, jQuery, alert*/

function highlightAddress(markerId) {
    'use strict';
    // console.log('marker : '+markerId);
    var item = jQuery('#item-' + markerId);
    if (item.length && !item.hasClass('active')) {
        jQuery('.list-agencies .active').removeClass('active');
        item.addClass('active');
    }
}

var onMarkerClick = function () {
    'use strict';
    // console.log(this);
    highlightAddress(this.id);
    infoWindow.setContent(this.html);
    infoWindow.open(map, this);
};

// Gmaps
if (jQuery('#map').length) {
    var infoWindow = new google.maps.InfoWindow(),
        jsonData = [],
        markers = [],
        markersPoints = [],
        markersPos = [],
        noms = [],
        iterator = 0,
        mapOptions = {
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            center: new google.maps.LatLng(50.85, 4.36),
            mapTypeControl: false,
            streetViewControl: false,
            zoom: 12
        },
        markerShape = {
            coord: [0, 0, 27, 0, 27, 37, 0, 37],
            type: 'poly'
        },
        map = new google.maps.Map(document.getElementById('map'), mapOptions);

    google.maps.event.addListener(map, 'click', function () {
        'use strict';
        infoWindow.close();
    });

    jQuery.getJSON(location.search, function (data) {
        'use strict';
        var i = 0,
            coords = [];
        if (!jQuery.isArray(data)) {
            jsonData = [data];
        } else {
            jsonData = data;
        }
        for (i = 0; i < jsonData.length; i += 1) {
            if (jsonData[i].latitude > 0 && jsonData[i].longitude > 0) {
                markersPos[i] = new google.maps.LatLng(jsonData[i].latitude, jsonData[i].longitude);
                markers[i] = {};
                coords = [];
                markers[i].id = jsonData[i].id;
                markers[i].shape = jsonData[i].shape;
                markers[i].html = '
' + jsonData[i].title + '
';
                markers[i].html += '
';
                if (jsonData[i].address) { coords.push(jsonData[i].address); }
                if (jsonData[i].phone) { coords.push('T ' + jsonData[i].phone); }
                if (jsonData[i].fax) { coords.push('F ' + jsonData[i].fax); }
                if (jsonData[i].email) { coords.push('' + jsonData[i].email + ''); }
                if (jsonData[i].website) { coords.push('' + data[i].website + ''); }
                markers[i].html += coords.join('
');
                markers[i].html += '
';
            }
        }
        // console.log(markers);
        if (markers.length > 0) {
            drop();
            AutoCenter();
        }
    });

    // Search Postcode
    $('#search-cp button').click(function () {
        'use strict';

        var cp = $('#search-cp input').val(),
            geocoder;

        if (!cp.length) {
            return false;
        }

        geocoder = new google.maps.Geocoder();
        geocoder.geocode(
            {
                address: cp + ' Belgique'
            },
            function (results_array) {
                var p = results_array[0].geometry.location,
                    lat = p.lat(),
                    lng = p.lng();
                setDistancesForMarkers(lat, lng);
            }
        );

        return false;
    });

    // Compute distance between two points
    var rad = function (x) {
        'use strict';
        return x * Math.PI / 180;
    };

    function getDistance(p1_lat, p1_lng, p2_lat, p2_lng) {
        'use strict';
        var R = 6378137, // Earth’s mean radius in meter
            dLat = rad(p2_lat - p1_lat),
            dLong = rad(p2_lng - p1_lng),
            a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(rad(p1_lat)) * Math.cos(rad(p2_lat)) *
                Math.sin(dLong / 2) * Math.sin(dLong / 2),
            c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)),
            d = R * c;
        return d; // returns the distance in meter
    }

    // Get the distance between a given point and the markers
    function setDistancesForMarkers(lat, lng) {
        'use strict';
        var i = 0;
        for (i = 0; i < jsonData.length; i += 1) {
            if (jsonData[i].latitude > 0 && jsonData[i].longitude > 0) {
                jsonData[i].distance = getDistance(lat, lng, jsonData[i].latitude, jsonData[i].longitude);
                // var km = (jsonData[i].distance/1000).toFixed(1);
                // var km = (jsonData[i].distance/1000).toFixed(0);
                // $('#item-'+jsonData[i].id).data('data-distance', km);
                // $('#item-'+jsonData[i].id+' .distance').html('(' + km + ' km)');
                jsonData.sort(function (a, b) {
                    return parseFloat(a.distance) - parseFloat(b.distance);
                });
                // sortAgenciesList();
            }
        }
        openMarkerId(jsonData[0].id);
    }

    // function sortAgenciesList() {
    //     'use strict';
    //     var items = $('#list-agencies li').get();
    //     items.sort(function (a,b) {
    //       var keyA = parseFloat($(a).data('data-distance'));
    //       var keyB = parseFloat($(b).data('data-distance'));
    //       if (keyA < keyB) return -1;
    //       if (keyA > keyB) return 1;
    //       return 0;
    //     });

    //     var ul = $('#list-agencies');
    //     $.each(items, function (i, li) {
    //         ul.append(li);
    //     });
    // }

}

function getMarkerIcon(shape) {
    'use strict';
    if (!shape) {
        shape = '/img/marker.png';
    }
    return new google.maps.MarkerImage(shape,
        new google.maps.Size(34, 44),
        new google.maps.Point(0, 0),
        new google.maps.Point(14, 36));
}

function addMarker(animation) {
    'use strict';

    // decaler un marker s'il y a déjà un point à la même position
    var dedans = 0,
        i = 0,
        latLng;
    for (i = markers.length - 1; i >= 0; i -= 1) {
        // console.log(markers[iterator].lat());
        if (markersPos[iterator].lat() === markersPos[i].lat() && markersPos[iterator].lng() === markersPos[i].lng()) {
            // markers[i]['html'] += markers[iterator]['html'];
            dedans += 1;
        }
    }
    if (dedans >= 2) {
        // console.log(dedans+' '+iterator);
        // Il y a au moins deux points ayant la même position, alors on décale un des deux
        latLng = new google.maps.LatLng(markersPos[iterator].lat(), markersPos[iterator].lng() + Math.random() / 4000 + 0.00001);
    } else {
        latLng = markersPos[iterator];
    }

    markersPoints[iterator] = new google.maps.Marker({
        // icon: getMarkerIcon('/img/marker.png'),
        shape: markerShape,
        position: latLng,
        map: map,
        draggable: false,
        animation: animation
    });
    // console.log(markers[iterator]);
    markersPoints[iterator].html = markers[iterator].html;
    markersPoints[iterator].id = markers[iterator].id;
    google.maps.event.addListener(markersPoints[iterator], 'click', onMarkerClick);
    if (markers.length === 1) {
        google.maps.event.trigger(markersPoints[iterator], 'click');
    }
    iterator += 1;
}

function drop() {
    'use strict';
    var i = 0;
    if (markers.length <= 3) {
        for (i = 0; i < markers.length; i += 1) {
            setTimeout(function () {
                addMarker(google.maps.Animation.DROP);
            }, i * 200);
        }
    } else {
        for (i = 0; i < markers.length; i += 1) {
            addMarker(false);
        }
    }
}

function AutoCenter() {
    'use strict';
    var bounds = new google.maps.LatLngBounds(),
        listener;
    jQuery.each(markers, function (index) {
        bounds.extend(markersPos[index]);
    });
    map.fitBounds(bounds);
    listener = google.maps.event.addListener(map, 'idle', function () {
        if (map.getZoom() > 17) {
            map.setZoom(17);
        }
        google.maps.event.removeListener(listener);
    });
}

function openMarkerId(id) {
    'use strict';
    var i = 0,
        latLng;
    // console.log('click : '+id );
    for (i = markers.length - 1; i >= 0; i -= 1) {
        // console.log(markers[i].id );
        if (markers[i].id === id) {
            latLng = new google.maps.LatLng(markersPos[i].lat(), markersPos[i].lng());
            map.panTo(latLng);
            map.setZoom(13);
            google.maps.event.trigger(markersPoints[i], 'click');
        }
    }
    return false;
}
<commit_msg>find nearest address<commit_after>/*global $, jQuery, alert*/

function highlightAddress(markerId) {
    'use strict';
    // console.log('marker : '+markerId);
    var item = jQuery('#item-' + markerId);
    if (item.length && !item.hasClass('active')) {
        jQuery('.list-agencies .active').removeClass('active');
        item.addClass('active');
    }
}

var onMarkerClick = function () {
    'use strict';
    // console.log(this);
    highlightAddress(this.id);
    infoWindow.setContent(this.html);
    infoWindow.open(map, this);
};

// Gmaps
if (jQuery('#map').length) {
    var infoWindow = new google.maps.InfoWindow(),
        jsonData = [],
        markers = [],
        markersPoints = [],
        markersPos = [],
        noms = [],
        iterator = 0,
        mapOptions = {
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            center: new google.maps.LatLng(50.85, 4.36),
            mapTypeControl: false,
            streetViewControl: false,
            zoom: 12
        },
        markerShape = {
            coord: [0, 0, 27, 0, 27, 37, 0, 37],
            type: 'poly'
        },
        map = new google.maps.Map(document.getElementById('map'), mapOptions);

    google.maps.event.addListener(map, 'click', function () {
        'use strict';
        infoWindow.close();
    });

    jQuery.getJSON(location.search, function (data) {
        'use strict';
        var i = 0,
            coords = [];
        if (!jQuery.isArray(data)) {
            jsonData = [data];
        } else {
            jsonData = data;
        }
        for (i = 0; i < jsonData.length; i += 1) {
            if (jsonData[i].latitude > 0 && jsonData[i].longitude > 0) {
                markersPos[i] = new google.maps.LatLng(jsonData[i].latitude, jsonData[i].longitude);
                markers[i] = {};
                coords = [];
                markers[i].id = jsonData[i].id;
                markers[i].shape = jsonData[i].shape;
                markers[i].html = '
' + jsonData[i].title + '
';
                markers[i].html += '
';
                if (jsonData[i].address) { coords.push(jsonData[i].address); }
                if (jsonData[i].phone) { coords.push('T ' + jsonData[i].phone); }
                if (jsonData[i].fax) { coords.push('F ' + jsonData[i].fax); }
                if (jsonData[i].email) { coords.push('' + jsonData[i].email + ''); }
                if (jsonData[i].website) { coords.push('' + data[i].website + ''); }
                markers[i].html += coords.join('
');
                markers[i].html += '
';
            }
        }
        // console.log(markers);
        if (markers.length > 0) {
            drop();
            AutoCenter();
        }
    });

    // Search Postcode
    $('#search-nearest button').click(function () {
        'use strict';

        var address = $('#search-nearest input').val(),
            geocoder;

        if (!address.length) {
            return false;
        }

        geocoder = new google.maps.Geocoder();
        geocoder.geocode(
            {
                address: address
            },
            function (results_array) {
                var p = results_array[0].geometry.location,
                    lat = p.lat(),
                    lng = p.lng();
                setDistancesForMarkers(lat, lng);
            }
        );

        return false;
    });

    // Compute distance between two points
    var rad = function (x) {
        'use strict';
        return x * Math.PI / 180;
    };

    function getDistance(p1_lat, p1_lng, p2_lat, p2_lng) {
        'use strict';
        var R = 6378137, // Earth’s mean radius in meter
            dLat = rad(p2_lat - p1_lat),
            dLong = rad(p2_lng - p1_lng),
            a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(rad(p1_lat)) * Math.cos(rad(p2_lat)) *
                Math.sin(dLong / 2) * Math.sin(dLong / 2),
            c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)),
            d = R * c;
        return d; // returns the distance in meter
    }

    // Get the distance between a given point and the markers
    function setDistancesForMarkers(lat, lng) {
        'use strict';
        var i = 0;
        for (i = 0; i < jsonData.length; i += 1) {
            if (jsonData[i].latitude > 0 && jsonData[i].longitude > 0) {
                jsonData[i].distance = getDistance(lat, lng, jsonData[i].latitude, jsonData[i].longitude);
                // var km = (jsonData[i].distance/1000).toFixed(1);
                // var km = (jsonData[i].distance/1000).toFixed(0);
                // $('#item-'+jsonData[i].id).data('data-distance', km);
                // $('#item-'+jsonData[i].id+' .distance').html('(' + km + ' km)');
                jsonData.sort(function (a, b) {
                    return parseFloat(a.distance) - parseFloat(b.distance);
                });
                // sortAgenciesList();
            }
        }
        openMarkerId(jsonData[0].id);
    }

    // function sortAgenciesList() {
    //     'use strict';
    //     var items = $('#list-agencies li').get();
    //     items.sort(function (a,b) {
    //       var keyA = parseFloat($(a).data('data-distance'));
    //       var keyB = parseFloat($(b).data('data-distance'));
    //       if (keyA < keyB) return -1;
    //       if (keyA > keyB) return 1;
    //       return 0;
    //     });

    //     var ul = $('#list-agencies');
    //     $.each(items, function (i, li) {
    //         ul.append(li);
    //     });
    // }

}

function getMarkerIcon(shape) {
    'use strict';
    if (!shape) {
        shape = '/img/marker.png';
    }
    return new google.maps.MarkerImage(shape,
        new google.maps.Size(34, 44),
        new google.maps.Point(0, 0),
        new google.maps.Point(14, 36));
}

function addMarker(animation) {
    'use strict';

    // decaler un marker s'il y a déjà un point à la même position
    var dedans = 0,
        i = 0,
        latLng;
    for (i = markers.length - 1; i >= 0; i -= 1) {
        // console.log(markers[iterator].lat());
        if (markersPos[iterator].lat() === markersPos[i].lat() && markersPos[iterator].lng() === markersPos[i].lng()) {
            // markers[i]['html'] += markers[iterator]['html'];
            dedans += 1;
        }
    }
    if (dedans >= 2) {
        // console.log(dedans+' '+iterator);
        // Il y a au moins deux points ayant la même position, alors on décale un des deux
        latLng = new google.maps.LatLng(markersPos[iterator].lat(), markersPos[iterator].lng() + Math.random() / 4000 + 0.00001);
    } else {
        latLng = markersPos[iterator];
    }

    markersPoints[iterator] = new google.maps.Marker({
        // icon: getMarkerIcon('/img/marker.png'),
        shape: markerShape,
        position: latLng,
        map: map,
        draggable: false,
        animation: animation
    });
    // console.log(markers[iterator]);
    markersPoints[iterator].html = markers[iterator].html;
    markersPoints[iterator].id = markers[iterator].id;
    google.maps.event.addListener(markersPoints[iterator], 'click', onMarkerClick);
    if (markers.length === 1) {
        google.maps.event.trigger(markersPoints[iterator], 'click');
    }
    iterator += 1;
}

function drop() {
    'use strict';
    var i = 0;
    if (markers.length <= 3) {
        for (i = 0; i < markers.length; i += 1) {
            setTimeout(function () {
                addMarker(google.maps.Animation.DROP);
            }, i * 200);
        }
    } else {
        for (i = 0; i < markers.length; i += 1) {
            addMarker(false);
        }
    }
}

function AutoCenter() {
    'use strict';
    var bounds = new google.maps.LatLngBounds(),
        listener;
    jQuery.each(markers, function (index) {
        bounds.extend(markersPos[index]);
    });
    map.fitBounds(bounds);
    listener = google.maps.event.addListener(map, 'idle', function () {
        if (map.getZoom() > 17) {
            map.setZoom(17);
        }
        google.maps.event.removeListener(listener);
    });
}

function openMarkerId(id) {
    'use strict';
    var i = 0,
        latLng;
    // console.log('click : '+id );
    for (i = markers.length - 1; i >= 0; i -= 1) {
        // console.log(markers[i].id );
        if (markers[i].id === id) {
            latLng = new google.maps.LatLng(markersPos[i].lat(), markersPos[i].lng());
            map.panTo(latLng);
            map.setZoom(13);
            google.maps.event.trigger(markersPoints[i], 'click');
        }
    }
    return false;
}
<|endoftext|>


<commit_before>const elasticsearchClient = require('./elasticsearchClient');

const GPlookupIndexName = process.env.GPlookupIndexName;

const ES_MAPPINGS = {
  'mappings': {
    'gps': {
      'properties': {
        'openingTimes': {
          'enabled': false
        },
        'facilities': {
          'enabled': false
        },
        'services': {
          'enabled': false
        },
        'onlineServices': {
          'enabled': false
        },
        'contact': {
          'enabled': false
        },
        'acceptingNewPatients': {
          'type': 'boolean'
        },
        'address': {
          'properties': {
            'addressLines': {
              'type': 'text',
              'fields': {
                'keyword': {
                  'type': 'keyword',
                  'ignore_above': 256
                }
              }
            },
            'postcode': {
              'type': 'text',
              'fields': {
                'keyword': {
                  'type': 'keyword',
                  'ignore_above': 256
                }
              }
            }
          }
        },
        'displayName': {
          'type': 'text',
          'fields': {
            'keyword': {
              'type': 'keyword',
              'ignore_above': 256
            }
          }
        },
        'doctors': {
          'type': 'nested',
          'properties': {
            'name' : {
              'type': 'string',
              'analyzer': 'gp_name_analyzer'
            }
          }
        },
        'location' : {
          'properties' : {
            'coordinates' : {
              'type' : 'geo_point'
            }
          }
        },
        'name': {
          'type': 'text',
          'fields': {
            'keyword': {
              'type': 'keyword',
              'ignore_above': 256
            }
          }
        }
      }
    }
  }
};

let elasticsearch = {};

elasticsearch.GPlookupIndexName = GPlookupIndexName;

elasticsearch.createGPLookupSearchIndex = (next) => {
  return elasticsearchClient.indices.create({
    index: GPlookupIndexName,
    body: ES_MAPPINGS
  }, next);
};

elasticsearch.indexIsExists = (name, next) => {
  return elasticsearchClient.indices.exists({
    index: name,
  }, next);
};

elasticsearch.addToIndex = (id, type, document, next) => {
  elasticsearchClient.index({
    index: GPlookupIndexName,
    type: type,
    id: id,
    body: document,
    timestamp: new Date().getTime()
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.update = (type, document, next) => {
  elasticsearchClient.index({
    index: process.env.MAIN_INDICE,
    type: type,
    id: document.id,
    timestamp: new Date().getTime(),
    body: document
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.bulkUpdate = (items, next) => {
  elasticsearchClient.bulk({
    body: items
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.delete = (type, id, next) => {
  elasticsearchClient.delete({
    index: GPlookupIndexName,
    type: type,
    id: id.toString()
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.get = (type, id, next) => {
  elasticsearchClient.get({
    index: GPlookupIndexName,
    type: type,
    id: id.toString()
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.getAll = (type, next) => {
  elasticsearchClient.search({
    index: GPlookupIndexName,
    type: type,
    body: {
      query: {
        match_all: {}
      }
    }
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.search = (type, query, next) => {
  elasticsearchClient.search({
    index: GPlookupIndexName,
    type: type,
    body: query
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.deleteIndex = (name, next) => {
  elasticsearchClient.indices.delete({
    index: name
  }, (error, response) => {
    next(error, response);
  });
};

module.exports = elasticsearch;<commit_msg>es mapping fixes<commit_after>const elasticsearchClient = require('./elasticsearchClient');

const GPlookupIndexName = process.env.GPlookupIndexName;

const ES_MAPPINGS = {
  'mappings': {
    'gps': {
      'properties': {
        'address': {
          'properties': {
            'addressLines': {
              'type': 'text',
              'fields': {
                'keyword': {
                  'type': 'keyword',
                  'ignore_above': 256
                }
              }
            },
            'postcode': {
              'type': 'text',
              'fields': {
                'keyword': {
                  'type': 'keyword',
                  'ignore_above': 256
                }
              }
            }
          }
        },
        'displayName': {
          'type': 'text',
          'fields': {
            'keyword': {
              'type': 'keyword',
              'ignore_above': 256
            }
          }
        },
        'doctors': {
          'type': 'nested',
          'properties': {
            'name' : {
              'type': 'string',
              'analyzer': 'gp_name_analyzer'
            }
          }
        },
        'location' : {
          'properties' : {
            'coordinates' : {
              'type' : 'geo_point'
            }
          }
        },
        'name': {
          'type': 'text',
          'fields': {
            'keyword': {
              'type': 'keyword',
              'ignore_above': 256
            }
          }
        }
      }
    }
  }
};

let elasticsearch = {};

elasticsearch.GPlookupIndexName = GPlookupIndexName;

elasticsearch.createGPLookupSearchIndex = (next) => {
  return elasticsearchClient.indices.create({
    index: GPlookupIndexName,
    body: ES_MAPPINGS
  }, next);
};

elasticsearch.indexIsExists = (name, next) => {
  return elasticsearchClient.indices.exists({
    index: name,
  }, next);
};

elasticsearch.addToIndex = (id, type, document, next) => {
  elasticsearchClient.index({
    index: GPlookupIndexName,
    type: type,
    id: id,
    body: document,
    timestamp: new Date().getTime()
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.update = (type, document, next) => {
  elasticsearchClient.index({
    index: process.env.MAIN_INDICE,
    type: type,
    id: document.id,
    timestamp: new Date().getTime(),
    body: document
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.bulkUpdate = (items, next) => {
  elasticsearchClient.bulk({
    body: items
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.delete = (type, id, next) => {
  elasticsearchClient.delete({
    index: GPlookupIndexName,
    type: type,
    id: id.toString()
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.get = (type, id, next) => {
  elasticsearchClient.get({
    index: GPlookupIndexName,
    type: type,
    id: id.toString()
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.getAll = (type, next) => {
  elasticsearchClient.search({
    index: GPlookupIndexName,
    type: type,
    body: {
      query: {
        match_all: {}
      }
    }
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.search = (type, query, next) => {
  elasticsearchClient.search({
    index: GPlookupIndexName,
    type: type,
    body: query
  }, (error, response) => {
    next(error, response);
  });
};

elasticsearch.deleteIndex = (name, next) => {
  elasticsearchClient.indices.delete({
    index: name
  }, (error, response) => {
    next(error, response);
  });
};

module.exports = elasticsearch;<|endoftext|>