<commit_before>/* ------------------------------------------------
 * Dependencies
 * ------------------------------------------------ */
const app = require('app');
const BrowserWindow = require('browser-window');
const crashReporter = require('crash-reporter');
const ipc = require('ipc');
const path = require('path');

const appConfig = require('src/config/appConfig');

/* ------------------------------------------------
 * App initialization
 * ------------------------------------------------ */
var mainWindow;

crashReporter.start(); // Report crashes to our server.

ipc.on('set-title', function(event, title) {
  mainWindow.setTitle(title || 'Mongotron');
});

ipc.on('quit', function() {
  app.quit();
});

app.on('window-all-closed', function() {
  // Quit when all windows are closed.
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('ready', function() {
  mainWindow = new BrowserWindow({});

  mainWindow.maximize();

  mainWindow.setMinimumSize(770, 400);

  mainWindow.loadUrl(path.join('file://', __dirname, '../ui/index.html'));

  if (appConfig.ENV !== 'production') mainWindow.openDevTools();

  mainWindow.webContents.on('did-finish-load', function() {
    mainWindow.setTitle('Mongotron');
  });

  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
});
<commit_msg>quit app when main window is closed<commit_after>/* ------------------------------------------------
 * Dependencies
 * ------------------------------------------------ */
const app = require('app');
const BrowserWindow = require('browser-window');
const crashReporter = require('crash-reporter');
const ipc = require('ipc');
const path = require('path');

const appConfig = require('src/config/appConfig');

/* ------------------------------------------------
 * App initialization
 * ------------------------------------------------ */
var mainWindow;

crashReporter.start(); // Report crashes to our server.

ipc.on('set-title', function(event, title) {
  mainWindow.setTitle(title || 'Mongotron');
});

ipc.on('quit', function() {
  app.quit();
});

app.on('window-all-closed', function() {
  // Quit when all windows are closed.
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('ready', function() {
  mainWindow = new BrowserWindow({});

  mainWindow.maximize();

  mainWindow.setMinimumSize(770, 400);

  mainWindow.loadUrl(path.join('file://', __dirname, '../ui/index.html'));

  if (appConfig.ENV !== 'production') mainWindow.openDevTools();

  mainWindow.webContents.on('did-finish-load', function() {
    mainWindow.setTitle('Mongotron');
  });

  mainWindow.on('close', function() {
    app.quit();
  });

  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
});
<|endoftext|>


<commit_before>(function () {

var $banner;

function queue_roll(bit) {
	var n = this.allRolls.sent++;
	var info = this.allRolls[n];
	if (!info)
		info = this.allRolls[n] = {};
	info.bit = bit;
	info.$tag = $(this.callback(safe('')));
	this.strong = true;
	this.callback(info.dice ? readable_dice(bit, info.dice) : bit);
	this.strong = false;
	this.callback(safe(''));
}

oneeSama.hook('imouto', function (imouto) {
	imouto.dice = GAME_BOARDS.indexOf(BOARD) >= 0;
	imouto.queueRoll = queue_roll;
	imouto.allRolls = {sent: 0, seen: 0};
});

oneeSama.hook('insertOwnPost', function (extra) {
	if (!postForm || !postForm.imouto || !extra || !extra.dice)
		return;
	var rolls = postForm.imouto.allRolls;
	for (var i = 0; i < extra.dice.length; i++) {
		var n = rolls.seen++;
		var info = rolls[n];
		if (!info)
			info = rolls[n] = {};
		info.dice = extra.dice[i];
		if (info.$tag)
			info.$tag.text(readable_dice(info.bit, info.dice));
	}
});

function write_bannerTop(){
    document.getElementById('bannerTop').innerHTML = '' + config.CUSTOM_BANNER_TOP + '';
}
setInterval(config.CUSTOM_BANNER_TOP ? write_bannerTop() : null, 10000);

var bannerExtra = config.CUSTOM_BANNER_BOTTOM ? $.parseHTML(''+config.CUSTOM_BANNER_BOTTOM+'') : null;

if (!$banner && bannerExtra) {
	var dest;
	if (THREAD){
		dest = $('#lock');
		$banner = $('').insertAfter(dest);
		$banner.empty().append(bannerExtra);
	}
}

dispatcher[UPDATE_BANNER] = function (msg, op) {
	msg = msg[0];
	if (!$banner) {
		var dest;
		if (THREAD == op)
			dest = '#lock';
		else {
			var $s = $('#' + op);
			if ($s.is('section'))
				dest = $s.children('header');
		}
		if (dest)
			$banner = $('').insertAfter(dest);
	}
	if ($banner) {
		if (Array.isArray(msg)) {
			construct_banner(msg);
			// if (bannerExtra)
			// 	$banner.append(' / ', bannerExtra);
		}
		else if (msg) {
			$banner.text(msg);
			// if (bannerExtra)
			// 	$banner.append(' / ', bannerExtra);
		}
		else if (bannerExtra && THREAD) {
			$banner.empty().append(bannerExtra);
		}
		else {
			$banner.remove();
			$banner = null;
		}
	}
};

function construct_banner(parts) {
	$banner.empty();
	parts.forEach(function (part) {
		if (part.href)
			$('', _.extend({target: '_blank'}, part)
					).appendTo($banner);
		else
			$banner.append(document.createTextNode(part));
	});
}

dispatcher[EXECUTE_JS] = function (msg, op) {
	if (THREAD != op)
		return;
	try {
		eval(msg[0]);
	}
	catch (e) {
		/* fgsfds */
	}
};

})();
<commit_msg>pointless bit in bannerTop<commit_after>(function () {

var $banner;

function queue_roll(bit) {
	var n = this.allRolls.sent++;
	var info = this.allRolls[n];
	if (!info)
		info = this.allRolls[n] = {};
	info.bit = bit;
	info.$tag = $(this.callback(safe('')));
	this.strong = true;
	this.callback(info.dice ? readable_dice(bit, info.dice) : bit);
	this.strong = false;
	this.callback(safe(''));
}

oneeSama.hook('imouto', function (imouto) {
	imouto.dice = GAME_BOARDS.indexOf(BOARD) >= 0;
	imouto.queueRoll = queue_roll;
	imouto.allRolls = {sent: 0, seen: 0};
});

oneeSama.hook('insertOwnPost', function (extra) {
	if (!postForm || !postForm.imouto || !extra || !extra.dice)
		return;
	var rolls = postForm.imouto.allRolls;
	for (var i = 0; i < extra.dice.length; i++) {
		var n = rolls.seen++;
		var info = rolls[n];
		if (!info)
			info = rolls[n] = {};
		info.dice = extra.dice[i];
		if (info.$tag)
			info.$tag.text(readable_dice(info.bit, info.dice));
	}
});

if (config.CUSTOM_BANNER_TOP) {
    document.getElementById('bannerTop').innerHTML = '' + config.CUSTOM_BANNER_TOP + '';
}

var bannerExtra = config.CUSTOM_BANNER_BOTTOM ? $.parseHTML(''+config.CUSTOM_BANNER_BOTTOM+'') : null;

if (!$banner && bannerExtra) {
	var dest;
	if (THREAD){
		dest = $('#lock');
		$banner = $('').insertAfter(dest);
		$banner.empty().append(bannerExtra);
	}
}

dispatcher[UPDATE_BANNER] = function (msg, op) {
	msg = msg[0];
	if (!$banner) {
		var dest;
		if (THREAD == op)
			dest = '#lock';
		else {
			var $s = $('#' + op);
			if ($s.is('section'))
				dest = $s.children('header');
		}
		if (dest)
			$banner = $('').insertAfter(dest);
	}
	if ($banner) {
		if (Array.isArray(msg)) {
			construct_banner(msg);
			// if (bannerExtra)
			// 	$banner.append(' / ', bannerExtra);
		}
		else if (msg) {
			$banner.text(msg);
			// if (bannerExtra)
			// 	$banner.append(' / ', bannerExtra);
		}
		else if (bannerExtra && THREAD) {
			$banner.empty().append(bannerExtra);
		}
		else {
			$banner.remove();
			$banner = null;
		}
	}
};

function construct_banner(parts) {
	$banner.empty();
	parts.forEach(function (part) {
		if (part.href)
			$('', _.extend({target: '_blank'}, part)
					).appendTo($banner);
		else
			$banner.append(document.createTextNode(part));
	});
}

dispatcher[EXECUTE_JS] = function (msg, op) {
	if (THREAD != op)
		return;
	try {
		eval(msg[0]);
	}
	catch (e) {
		/* fgsfds */
	}
};

})();
<|endoftext|>


<commit_before>define([
  'gui/GuiTR',
  'editor/Remesh',
  'render/shaders/ShaderBase'
], function (TR, Remesh, ShaderBase) {

  'use strict';

  var GuiScene = function (guiParent, ctrlGui) {
    this._main = ctrlGui._main; // main application
    this._hideMeshes = [];
    this._cbToggleShowHide = this.toggleShowHide.bind(this, true);
    this.init(guiParent);
  };

  GuiScene.prototype = {
    /** Initialize */
    init: function (guiParent) {
      var menu = guiParent.addMenu(TR('sceneTitle'));

      // scene
      menu.addButton(TR('sceneReset'), this._main, 'clearScene' /*, 'CTRL+ALT+N'*/ );
      menu.addButton(TR('sceneAddSphere'), this._main, 'addSphere');
      menu.addButton(TR('sceneAddCube'), this._main, 'addCube');

      // selection stuffs
      menu.addTitle(TR('sceneSelection'));
      menu.addCheckbox(TR('contourShow'), this._main._showContour, this.onShowContour.bind(this));
      this._ctrlIsolate = menu.addCheckbox(TR('renderingIsolate'), false, this.showHide.bind(this));
      this._ctrlIsolate.setVisibility(false);
      this._ctrlMerge = menu.addButton(TR('sceneMerge'), this, 'merge');
      this._ctrlMerge.setVisibility(false);

      // extra
      menu.addTitle(TR('renderingExtra'));
      menu.addCheckbox(TR('renderingGrid'), this._main._showGrid, this.onShowGrid.bind(this));
      menu.addCheckbox(TR('renderingSymmetryLine'), ShaderBase.showSymmetryLine, this.onShowSymmetryLine.bind(this));

      this.addEvents();
    },
    updateMesh: function () {
      var nbMeshes = this._main.getMeshes().length;
      var nbSelected = this._main.getSelectedMeshes().length;
      this._ctrlIsolate.setVisibility(nbMeshes !== nbSelected && nbSelected >= 1);
      this._ctrlMerge.setVisibility(nbSelected > 1);
    },
    merge: function () {
      var main = this._main;
      var selMeshes = main.getSelectedMeshes();
      if (selMeshes.length < 2) return;

      var newMesh = Remesh.mergeMeshes(selMeshes, main.getMesh() || selMeshes[0]);
      main.removeMeshes(selMeshes);
      main.getStates().pushStateAddRemove(newMesh, selMeshes.slice());
      main.getMeshes().push(newMesh);
      main.setMesh(newMesh);
    },
    addEvents: function () {
      var cbKeyDown = this.onKeyDown.bind(this);
      window.addEventListener('keydown', cbKeyDown, false);
      this.removeCallback = function () {
        window.removeEventListener('keydown', cbKeyDown, false);
      };
    },
    removeEvents: function () {
      if (this.removeCallback) this.removeCallback();
    },
    onKeyDown: function (event) {
      if (event.handled === true)
        return;
      event.stopPropagation();
      if (!this._main._focusGui)
        event.preventDefault();
      var key = event.which;
      if (key === 73) { // I
        this.toggleShowHide();
        event.handled = true;
      }
    },
    toggleShowHide: function (ignoreCB) {
      this._ctrlIsolate.setValue(!this._ctrlIsolate.getValue(), !!ignoreCB);
    },
    showHide: function (bool) {
      if (bool) this.isolate();
      else this.showAll();
    },
    isolate: function () {
      var main = this._main;
      var selMeshes = main.getSelectedMeshes();
      var meshes = main.getMeshes();
      if (meshes.length === selMeshes.length || meshes.length < 2) {
        this._ctrlIsolate.setValue(false, true);
        return;
      }

      var hMeshes = this._hideMeshes;
      hMeshes.length = 0;
      for (var i = 0; i < meshes.length; ++i) {
        var id = main.getIndexSelectMesh(meshes[i]);
        if (id < 0) {
          hMeshes.push(meshes[i]);
          meshes.splice(i--, 1);
        }
      }

      main.getStates().pushStateRemove(hMeshes.slice());
      main.getStates().pushStateCustom(this._cbToggleShowHide, this._cbToggleShowHide, true);
    },
    showAll: function () {
      var main = this._main;
      var meshes = main.getMeshes();
      var hMeshes = this._hideMeshes;
      for (var i = 0, nbAdd = hMeshes.length; i < nbAdd; ++i) {
        meshes.push(hMeshes[i]);
      }
      main.getStates().pushStateAdd(hMeshes.slice());
      main.getStates().pushStateCustom(this._cbToggleShowHide, this._cbToggleShowHide, true);
      hMeshes.length = 0;
    },
    onShowSymmetryLine: function (val) {
      ShaderBase.showSymmetryLine = val;
      this._main.render();
    },
    onShowGrid: function (bool) {
      var main = this._main;
      main._showGrid = bool;
      main.render();
    },
    onShowContour: function (bool) {
      var main = this._main;
      main._showContour = bool;
      main.render();
    }
  };

  return GuiScene;
});
<commit_msg>Fixes isolate display button<commit_after>define([
  'gui/GuiTR',
  'editor/Remesh',
  'render/shaders/ShaderBase'
], function (TR, Remesh, ShaderBase) {

  'use strict';

  var GuiScene = function (guiParent, ctrlGui) {
    this._main = ctrlGui._main; // main application
    this._hideMeshes = [];
    this._cbToggleShowHide = this.toggleShowHide.bind(this, true);
    this.init(guiParent);
  };

  GuiScene.prototype = {
    /** Initialize */
    init: function (guiParent) {
      var menu = guiParent.addMenu(TR('sceneTitle'));

      // scene
      menu.addButton(TR('sceneReset'), this._main, 'clearScene' /*, 'CTRL+ALT+N'*/ );
      menu.addButton(TR('sceneAddSphere'), this._main, 'addSphere');
      menu.addButton(TR('sceneAddCube'), this._main, 'addCube');

      // selection stuffs
      menu.addTitle(TR('sceneSelection'));
      menu.addCheckbox(TR('contourShow'), this._main._showContour, this.onShowContour.bind(this));
      this._ctrlIsolate = menu.addCheckbox(TR('renderingIsolate'), false, this.showHide.bind(this));
      this._ctrlIsolate.setVisibility(false);
      this._ctrlMerge = menu.addButton(TR('sceneMerge'), this, 'merge');
      this._ctrlMerge.setVisibility(false);

      // extra
      menu.addTitle(TR('renderingExtra'));
      menu.addCheckbox(TR('renderingGrid'), this._main._showGrid, this.onShowGrid.bind(this));
      menu.addCheckbox(TR('renderingSymmetryLine'), ShaderBase.showSymmetryLine, this.onShowSymmetryLine.bind(this));

      this.addEvents();
    },
    updateMesh: function () {
      var nbMeshes = this._main.getMeshes().length;
      var nbSelected = this._main.getSelectedMeshes().length;
      this._ctrlIsolate.setVisibility(this._hideMeshes.length > 0 || (nbMeshes !== nbSelected && nbSelected >= 1));
      this._ctrlMerge.setVisibility(nbSelected > 1);
    },
    merge: function () {
      var main = this._main;
      var selMeshes = main.getSelectedMeshes();
      if (selMeshes.length < 2) return;

      var newMesh = Remesh.mergeMeshes(selMeshes, main.getMesh() || selMeshes[0]);
      main.removeMeshes(selMeshes);
      main.getStates().pushStateAddRemove(newMesh, selMeshes.slice());
      main.getMeshes().push(newMesh);
      main.setMesh(newMesh);
    },
    addEvents: function () {
      var cbKeyDown = this.onKeyDown.bind(this);
      window.addEventListener('keydown', cbKeyDown, false);
      this.removeCallback = function () {
        window.removeEventListener('keydown', cbKeyDown, false);
      };
    },
    removeEvents: function () {
      if (this.removeCallback) this.removeCallback();
    },
    onKeyDown: function (event) {
      if (event.handled === true)
        return;
      event.stopPropagation();
      if (!this._main._focusGui)
        event.preventDefault();
      var key = event.which;
      if (key === 73) { // I
        this.toggleShowHide();
        event.handled = true;
      }
    },
    toggleShowHide: function (ignoreCB) {
      this._ctrlIsolate.setValue(!this._ctrlIsolate.getValue(), !!ignoreCB);
    },
    showHide: function (bool) {
      if (bool) this.isolate();
      else this.showAll();
      this.updateMesh();
    },
    isolate: function () {
      var main = this._main;
      var selMeshes = main.getSelectedMeshes();
      var meshes = main.getMeshes();
      if (meshes.length === selMeshes.length || meshes.length < 2) {
        this._ctrlIsolate.setValue(false, true);
        return;
      }

      var hMeshes = this._hideMeshes;
      hMeshes.length = 0;
      for (var i = 0; i < meshes.length; ++i) {
        var id = main.getIndexSelectMesh(meshes[i]);
        if (id < 0) {
          hMeshes.push(meshes[i]);
          meshes.splice(i--, 1);
        }
      }

      main.getStates().pushStateRemove(hMeshes.slice());
      main.getStates().pushStateCustom(this._cbToggleShowHide, this._cbToggleShowHide, true);
      main.render();
    },
    showAll: function () {
      var main = this._main;
      var meshes = main.getMeshes();
      var hMeshes = this._hideMeshes;
      for (var i = 0, nbAdd = hMeshes.length; i < nbAdd; ++i) {
        meshes.push(hMeshes[i]);
      }
      main.getStates().pushStateAdd(hMeshes.slice());
      main.getStates().pushStateCustom(this._cbToggleShowHide, this._cbToggleShowHide, true);
      hMeshes.length = 0;
      main.render();
    },
    onShowSymmetryLine: function (val) {
      ShaderBase.showSymmetryLine = val;
      this._main.render();
    },
    onShowGrid: function (bool) {
      var main = this._main;
      main._showGrid = bool;
      main.render();
    },
    onShowContour: function (bool) {
      var main = this._main;
      main._showContour = bool;
      main.render();
    }
  };

  return GuiScene;
});<|endoftext|>


<commit_before><commit_msg>fixed serve_uber<commit_after><|endoftext|>


<commit_before>// Load data tiles using the JQuery ajax function
L.TileLayer.Ajax = L.TileLayer.extend({
    _requests: [],
    _data: [],
    data: function () {
        for (var t in this._tiles) {
            var tile = this._tiles[t];
            if (!tile.processed) {
                this._data = this._data.concat(tile.datum);
                tile.processed = true;
            }
        }
        return this._data;
    },
    _addTile: function(tilePoint, container) {
        var tile = { datum: null, processed: false };
        this._tiles[tilePoint.x + ':' + tilePoint.y] = tile;
        this._loadTile(tile, tilePoint);
    },
    _loadTile: function (tile, tilePoint) {
        var layer = this;
        this._requests.push($.ajax({
            url: this.getTileUrl(tilePoint),
            dataType: 'json',
            success: function(datum) {
                tile.datum = datum;
                layer._tileLoaded();
            },
            error: function() {
                layer._tileLoaded();
            }
        }));
    },
    _resetCallback: function() {
        this._data = [];
        L.TileLayer.prototype._resetCallback.apply(this, arguments);
        for (var i in this._requests) {
            this._requests[i].abort();
        }
        this._requests = [];
    },
    _update: function() {
        if (this._map._panTransition && this._map._panTransition._inProgress) { return; }
        L.TileLayer.prototype._update.apply(this, arguments);
    }
});

L.TileLayer.GeoJSON = L.TileLayer.Ajax.extend({
    _geojson: {"type":"FeatureCollection","features":[]},
    initialize: function (url, options, geojsonOptions) {
        L.TileLayer.Ajax.prototype.initialize.call(this, url, options);
        this.geojsonLayer = new L.GeoJSON(this._geojson, geojsonOptions);
        this.geojsonOptions = geojsonOptions;
    },
    onAdd: function (map) {
        this._map = map;
        L.TileLayer.Ajax.prototype.onAdd.call(this, map);
        this.on('load', this._tilesLoaded);
        map.addLayer(this.geojsonLayer);
    },
    onRemove: function (map) {
        map.removeLayer(this.geojsonLayer);
        this.off('load', this._tilesLoaded);
        L.TileLayer.Ajax.prototype.onRemove.call(this, map);
    },
    groupByKey: function (items, keyCallback) {
        var groups = {};
        for (var i in items) {
            var item = items[i];
            var key = keyCallback(item);
            if (!groups.hasOwnProperty(key)) {
                groups[key] = [];
            }
            groups[key].push(item);
        }
        return groups;
    },
    data: function () {
        this._geojson.features = [];
        if (this.options.unique) {
            this._uniqueKeys = {};
        }
        var tileData = L.TileLayer.Ajax.prototype.data.call(this);
        for (var t in tileData) {
            var tileDatum = tileData[t];
            if (tileDatum && tileDatum.features) {

                // deduplicate features by using the string result of the unique function
                if (this.options.unique) {
                    for (var f in tileDatum.features) {
                        var featureKey = this.options.unique(tileDatum.features[f]);
                        if (this._uniqueKeys.hasOwnProperty(featureKey)) {
                            delete tileDatum.features[f];
                        }
                        else {
                            this._uniqueKeys[featureKey] = featureKey;
                        }
                    }
                }
                this._geojson.features =
                    this._geojson.features.concat(tileDatum.features);
            }
        }
        return this._geojson;
    },
    _resetCallback: function () {
        this._geojson.features = [];
        L.TileLayer.Ajax.prototype._resetCallback.apply(this, arguments);
    },
    _tilesLoaded: function (evt) {
        this.geojsonLayer.clearLayers().addData(this.data());
    }
});<commit_msg>Removed groupByKey function, accidentally leaked from another branch.<commit_after>// Load data tiles using the JQuery ajax function
L.TileLayer.Ajax = L.TileLayer.extend({
    _requests: [],
    _data: [],
    data: function () {
        for (var t in this._tiles) {
            var tile = this._tiles[t];
            if (!tile.processed) {
                this._data = this._data.concat(tile.datum);
                tile.processed = true;
            }
        }
        return this._data;
    },
    _addTile: function(tilePoint, container) {
        var tile = { datum: null, processed: false };
        this._tiles[tilePoint.x + ':' + tilePoint.y] = tile;
        this._loadTile(tile, tilePoint);
    },
    _loadTile: function (tile, tilePoint) {
        var layer = this;
        this._requests.push($.ajax({
            url: this.getTileUrl(tilePoint),
            dataType: 'json',
            success: function(datum) {
                tile.datum = datum;
                layer._tileLoaded();
            },
            error: function() {
                layer._tileLoaded();
            }
        }));
    },
    _resetCallback: function() {
        this._data = [];
        L.TileLayer.prototype._resetCallback.apply(this, arguments);
        for (var i in this._requests) {
            this._requests[i].abort();
        }
        this._requests = [];
    },
    _update: function() {
        if (this._map._panTransition && this._map._panTransition._inProgress) { return; }
        L.TileLayer.prototype._update.apply(this, arguments);
    }
});

L.TileLayer.GeoJSON = L.TileLayer.Ajax.extend({
    _geojson: {"type":"FeatureCollection","features":[]},
    initialize: function (url, options, geojsonOptions) {
        L.TileLayer.Ajax.prototype.initialize.call(this, url, options);
        this.geojsonLayer = new L.GeoJSON(this._geojson, geojsonOptions);
        this.geojsonOptions = geojsonOptions;
    },
    onAdd: function (map) {
        this._map = map;
        L.TileLayer.Ajax.prototype.onAdd.call(this, map);
        this.on('load', this._tilesLoaded);
        map.addLayer(this.geojsonLayer);
    },
    onRemove: function (map) {
        map.removeLayer(this.geojsonLayer);
        this.off('load', this._tilesLoaded);
        L.TileLayer.Ajax.prototype.onRemove.call(this, map);
    },
    data: function () {
        this._geojson.features = [];
        if (this.options.unique) {
            this._uniqueKeys = {};
        }
        var tileData = L.TileLayer.Ajax.prototype.data.call(this);
        for (var t in tileData) {
            var tileDatum = tileData[t];
            if (tileDatum && tileDatum.features) {

                // deduplicate features by using the string result of the unique function
                if (this.options.unique) {
                    for (var f in tileDatum.features) {
                        var featureKey = this.options.unique(tileDatum.features[f]);
                        if (this._uniqueKeys.hasOwnProperty(featureKey)) {
                            delete tileDatum.features[f];
                        }
                        else {
                            this._uniqueKeys[featureKey] = featureKey;
                        }
                    }
                }
                this._geojson.features =
                    this._geojson.features.concat(tileDatum.features);
            }
        }
        return this._geojson;
    },
    _resetCallback: function () {
        this._geojson.features = [];
        L.TileLayer.Ajax.prototype._resetCallback.apply(this, arguments);
    },
    _tilesLoaded: function (evt) {
        this.geojsonLayer.clearLayers().addData(this.data());
    }
});<|endoftext|>


<commit_before>var postcss = require('postcss')
var EventEmitter = require('events')

var inherits = require('util').inherits
inherits(Result, EventEmitter)

module.exports = Result

function Result(opts) {
  opts = opts || {}
  this.from = opts.file
  this._source = opts.source
  this._root = null

  Object.defineProperty(this, 'root', {
    get: function () {
      if (this._root) {
        return this._root
      }
      this._root = postcss.parse(this._source)
      return this._root
    },
    set: function (rt) {
      this._root = rt
    },
  })

  Object.defineProperty(this, 'css', {
    get: function () {
      if (!this._root) {
        return this._source
      }
      // a little expensive to get this property
      // but everytime `this.root` changes,
      // it invalidates `this.source`
      return postcss().process(this.root, { from: this.from }).css
    },
    set: function (src) {
      this._root = null
      this._source = src
    },
  })

}

<commit_msg>**Fix**: pass the `from` option when parse `result.root`<commit_after>var postcss = require('postcss')
var EventEmitter = require('events')

var inherits = require('util').inherits
inherits(Result, EventEmitter)

module.exports = Result

function Result(opts) {
  opts = opts || {}
  this.from = opts.file
  this._source = opts.source
  this._root = null

  Object.defineProperty(this, 'root', {
    get: function () {
      if (this._root) {
        return this._root
      }
      this._root = postcss.parse(this._source, { from: this.from })
      return this._root
    },
    set: function (rt) {
      this._root = rt
    },
  })

  Object.defineProperty(this, 'css', {
    get: function () {
      if (!this._root) {
        return this._source
      }
      // a little expensive to get this property
      // but everytime `this.root` changes,
      // it invalidates `this.source`
      return postcss().process(this.root, { from: this.from }).css
    },
    set: function (src) {
      this._root = null
      this._source = src
    },
  })

}

<|endoftext|>


<commit_before>var util = require('util');

function BufferObject(data, getUpdate, maxAge) {
    if (typeof getUpdate != 'function') {
        throw new Error('BufferObject requires a update function');
    }

    maxAge = maxAge || 6e4;

    //noinspection JSUnusedGlobalSymbols
    return {
        lastUpdate: data ? Date.now() : 0,
        data: data || null,
        set: function(data) {
            this.data = data;
            this.lastUpdate = Date.now();
        },
        get: function(callback) {
            if (this.data != null) {
                if (maxAge < 0 || this.lastUpdate >= Date.now() - maxAge) {
                    callback(this.data);
                    return;
                }
            }

            var that = this;
            getUpdate(function(err, data) {
                if (err) {
                    that.get();
                    return;
                }
                that.set(data);
                callback(data);
            });
        },
        push: function(data) {
            // Be sure the data is loaded
            this.get();

            if (util.isArray(this.data)) {
                this.data.push(data);
            }
        },
        remove: function(data) {
            this.get();

            for (var i in this.data) {
                if (!this.data.hasOwnProperty(i)) continue;
                if (this.data[i] == data) {
                    this.data.splice(i, 1);
                    return;
                }
            }
        },
        removeAt: function(index) {
            // Be sure the data is loaded
            this.get();

            if (util.isArray(this.data) && index < this.data.length) {
                this.data.splice(index, 1);
            }
        }
    };
}

module.exports = BufferObject;<commit_msg>Make callback optional for BufferObject.get<commit_after>var util = require('util');

function BufferObject(data, getUpdate, maxAge) {
    if (typeof getUpdate != 'function') {
        throw new Error('BufferObject requires a update function');
    }

    maxAge = maxAge || 6e4;

    //noinspection JSUnusedGlobalSymbols
    return {
        lastUpdate: data ? Date.now() : 0,
        data: data || null,
        set: function(data) {
            this.data = data;
            this.lastUpdate = Date.now();
        },
        get: function(callback) {
            if (this.data != null) {
                if (maxAge < 0 || this.lastUpdate >= Date.now() - maxAge) {
                    if (typeof callback == 'function')
                        callback(this.data);
                    return;
                }
            }

            var that = this;
            getUpdate(function(err, data) {
                if (err) {
                    that.get();
                    return;
                }
                that.set(data);
                if (typeof callback == 'function')
                    callback(data);
            });
        },
        push: function(data) {
            // Be sure the data is loaded
            this.get();

            if (util.isArray(this.data)) {
                this.data.push(data);
            }
        },
        remove: function(data) {
            this.get();

            for (var i in this.data) {
                if (!this.data.hasOwnProperty(i)) continue;
                if (this.data[i] == data) {
                    this.data.splice(i, 1);
                    return;
                }
            }
        },
        removeAt: function(index) {
            // Be sure the data is loaded
            this.get();

            if (util.isArray(this.data) && index < this.data.length) {
                this.data.splice(index, 1);
            }
        }
    };
}

module.exports = BufferObject;<|endoftext|>


<commit_before><commit_msg>updated gulp file with mocha error handling<commit_after><|endoftext|>


<commit_before><commit_msg>Pruned unused build deps<commit_after><|endoftext|>


<commit_before>Router.route('index', {
  path: '/',
  controller: 'IndexController'
});

/*
Router.route('eventSignin', {
  path: '/54c978d1276ac7f9fa6f9cb8',
  controller: 'EventSigninController'
})
*/

Router.route('ndaSignin', {
  path: '/54d13d2419570ac30ca9d7e9',
  where: 'server'
}).post(function() {
  var pawprint = this.request.body.pawprint;

  this.response.setHeader('Access-Control-Allow-Origin','*');
  this.response.write('success');
  this.response.end();

  Meteor.call('addMember',"","",pawprint,"54d13d2419570ac30ca9d7e9");
})

Router.onBeforeAction(function() {
  if(this.ready()) {
    //Meteor.call('addLog',this.request);
    this.next();
  }
})<commit_msg>updating routes<commit_after>Router.route('index', {
  path: '/',
  controller: 'IndexController'
});

/*
Router.route('eventSignin', {
  path: '/54c978d1276ac7f9fa6f9cb8',
  controller: 'EventSigninController'
})
*/

Router.route('ndaSignin', {
  path: '/54d1430c64d4f4a5444cdab0',
  where: 'server'
}).post(function() {
  var pawprint = this.request.body.pawprint;

  this.response.setHeader('Access-Control-Allow-Origin','*');
  this.response.write('success');
  this.response.end();

  Meteor.call('addMember',"","",pawprint,"54d1430c64d4f4a5444cdab0");
})

Router.onBeforeAction(function() {
  if(this.ready()) {
    //Meteor.call('addLog',this.request);
    this.next();
  }
})<|endoftext|>


<commit_before><commit_msg>:Wrench: BrowserSync<commit_after><|endoftext|>


<commit_before>/* eslint no-shadow: 0 */

// External
import * as d3 from 'd3';
import isFunction from '../../../node_modules/lodash-es/isFunction';

// Internal
import { ExtendableError } from './error';
import { mergeSelections } from './d3-utils';

export class LimitsUnsupportedFormat extends ExtendableError {
  constructor (message) {
    super(message || 'The limits are wrongly formatted. Please provide an ' +
      'object of the following format: `{ x: { min: 0, max: 1 }, y: { min: ' +
      '0, max: 1 } }`'
    );
  }
}

/**
 * Drap and drop event handler that works via translation.
 *
 * @method  onDragDrop
 * @author  Fritz Lekschas
 * @date    2016-04-04
 * @param   {Object}  selection        D3 selection to listen for the drag
 *   event.
 * @param   {Object}           dragMoveHandler         Handler for drag-move.
 * @param   {Object}           dropHandler             Handler for drag-end,
 *   i.e. drop.
 * @param   {Array}            elsToBeDragged          Array of D3 selections to
 *   be moved according to the drag event. If empty or undefined `selection`
 *   will be used.
 * @param   {String}           orientation             Can either be
 *   "horizontal", "vertical" or `undefined`, i.e. both directions.
 * @param   {Object|Function}  limits                  X and Y drag limits. E.g.
 *   `{ x: { min: 0, max: 10 } }`.
 * @param   {Array}             noDraggingWhenTrue     List if function
 *   returning a Boolean value which should prevent the dragMoveHandler from
 *   working.
 */
export function onDragDrop (
  selection, dragStartHandler, dragMoveHandler, dropHandler, elsToBeDragged,
  orientation, limits, noDraggingWhenTrue, dragData
) {
  const drag = d3.drag();
  const checkWhenDragging = isFunction(noDraggingWhenTrue);

  let appliedLimits = limits || {};  // eslint-disable-line no-param-reassign

  drag.on('start', () => {
    if (checkWhenDragging && noDraggingWhenTrue()) {
      return;
    }
    if (typeof limits === 'function') {
      appliedLimits = limits();
    }
  });

  if (dragMoveHandler) {
    drag.on('drag', function (data) {
      if (checkWhenDragging && noDraggingWhenTrue()) {
        return;
      }
      d3.event.sourceEvent.preventDefault();
      dragStartHandler();
      dragMoveHandler.call(
        this, data, elsToBeDragged, orientation, appliedLimits
      );
    });
  }

  if (dropHandler) {
    drag.on('end', dropHandler);
  }

  selection.each(function (data) {
    const el = d3.select(this);

    // Set default data if not available.
    if (!data) {
      data = { drag: dragData };  // eslint-disable-line no-param-reassign
      el.datum(data);
    }

    // Add drag event handler
    el.call(drag);
  });
}

export function dragMoveHandler (
  data, elsToBeDragged, orientation, limits
) {
  let els = d3.select(this);

  if (elsToBeDragged && elsToBeDragged.length) {
    els = mergeSelections(elsToBeDragged);
  }

  function withinLimits (value, applyingLimits) {
    let restrictedValue;

    if (applyingLimits) {
      try {
        restrictedValue = Math.min(
          applyingLimits.max,
          Math.max(
            applyingLimits.min,
            value
          )
        );
      } catch (e) {
        throw new LimitsUnsupportedFormat();
      }
    }
    return restrictedValue;
  }

  if (orientation === 'horizontal' || orientation === 'vertical') {
    if (orientation === 'horizontal') {
      data.drag.x += d3.event.dx;
      data.drag.x = withinLimits(data.drag.x + d3.event.dx, limits.x);
      els.style('transform', 'translateX(' + data.drag.x + 'px)');
    }
    if (orientation === 'vertical') {
      data.drag.y += d3.event.dy;
      data.drag.x = withinLimits(data.drag.y + d3.event.dy, limits.y);
      els.style('transform', 'translateY(' + data.drag.y + 'px)');
    }
  } else {
    data.drag.x += d3.event.dx;
    data.drag.y += d3.event.dy;
    els.style(
      'transform', 'translate(' + data.drag.x + 'px,' + data.drag.y + 'px)'
    );
  }
}
<commit_msg>Use new filter function to avoid dragging the whole graph while dragging the scrollbar.<commit_after>/* eslint no-shadow: 0 */

// External
import * as d3 from 'd3';
import isFunction from '../../../node_modules/lodash-es/isFunction';

// Internal
import { ExtendableError } from './error';
import { mergeSelections } from './d3-utils';

export class LimitsUnsupportedFormat extends ExtendableError {
  constructor (message) {
    super(message || 'The limits are wrongly formatted. Please provide an ' +
      'object of the following format: `{ x: { min: 0, max: 1 }, y: { min: ' +
      '0, max: 1 } }`'
    );
  }
}

/**
 * Drap and drop event handler that works via translation.
 *
 * @method  onDragDrop
 * @author  Fritz Lekschas
 * @date    2016-04-04
 * @param   {Object}  selection        D3 selection to listen for the drag
 *   event.
 * @param   {Object}           dragMoveHandler         Handler for drag-move.
 * @param   {Object}           dropHandler             Handler for drag-end,
 *   i.e. drop.
 * @param   {Array}            elsToBeDragged          Array of D3 selections to
 *   be moved according to the drag event. If empty or undefined `selection`
 *   will be used.
 * @param   {String}           orientation             Can either be
 *   "horizontal", "vertical" or `undefined`, i.e. both directions.
 * @param   {Object|Function}  limits                  X and Y drag limits. E.g.
 *   `{ x: { min: 0, max: 10 } }`.
 * @param   {Array}             noDraggingWhenTrue     List if function
 *   returning a Boolean value which should prevent the dragMoveHandler from
 *   working.
 */
export function onDragDrop (
  selection, dragStartHandler, dragMoveHandler, dropHandler, elsToBeDragged,
  orientation, limits, noDraggingWhenTrue, dragData
) {
  const drag = d3.drag();
  const checkWhenDragging = isFunction(noDraggingWhenTrue);

  let appliedLimits = limits || {};  // eslint-disable-line no-param-reassign

  const filter = function filter () {
    return !(checkWhenDragging && noDraggingWhenTrue());
  };

  drag.filter(filter);

  drag.on('start', () => {
    if (typeof limits === 'function') {
      appliedLimits = limits();
    }
  });

  if (dragMoveHandler) {
    drag.on('drag', function (data) {
      if (checkWhenDragging && noDraggingWhenTrue()) {
        return;
      }
      d3.event.sourceEvent.preventDefault();
      dragStartHandler();
      dragMoveHandler.call(
        this, data, elsToBeDragged, orientation, appliedLimits
      );
    });
  }

  if (dropHandler) {
    drag.on('end', dropHandler);
  }

  selection.each(function (data) {
    const el = d3.select(this);

    // Set default data if not available.
    if (!data) {
      data = { drag: dragData };  // eslint-disable-line no-param-reassign
      el.datum(data);
    }

    // Add drag event handler
    el.call(drag);
  });
}

export function dragMoveHandler (
  data, elsToBeDragged, orientation, limits
) {
  let els = d3.select(this);

  if (elsToBeDragged && elsToBeDragged.length) {
    els = mergeSelections(elsToBeDragged);
  }

  function withinLimits (value, applyingLimits) {
    let restrictedValue;

    if (applyingLimits) {
      try {
        restrictedValue = Math.min(
          applyingLimits.max,
          Math.max(
            applyingLimits.min,
            value
          )
        );
      } catch (e) {
        throw new LimitsUnsupportedFormat();
      }
    }
    return restrictedValue;
  }

  if (orientation === 'horizontal' || orientation === 'vertical') {
    if (orientation === 'horizontal') {
      data.drag.x += d3.event.dx;
      data.drag.x = withinLimits(data.drag.x + d3.event.dx, limits.x);
      els.style('transform', 'translateX(' + data.drag.x + 'px)');
    }
    if (orientation === 'vertical') {
      data.drag.y += d3.event.dy;
      data.drag.x = withinLimits(data.drag.y + d3.event.dy, limits.y);
      els.style('transform', 'translateY(' + data.drag.y + 'px)');
    }
  } else {
    data.drag.x += d3.event.dx;
    data.drag.y += d3.event.dy;
    els.style(
      'transform', 'translate(' + data.drag.x + 'px,' + data.drag.y + 'px)'
    );
  }
}
<|endoftext|>


<commit_before>(function() {
  "use strict";

  // Save a reference to the global object ('window' in the browser, ,'exports'
  // on the server.
  var root = this,

      // Allow use of jQuery, Zepto or ender with Xively.js in the style of Backbone
      $ = root.jQuery || root.Zepto || root.ender || root.$;

  var XivelyClient = function() {

    // private stuff
    var version = "1.0.4-alpha",

        apiEndpoint = "https://api.xively.com/v2",

        wsEndpoint = "ws://api.xively.com:8080",

        sockjsEndpoint = "https://api.xively.com:8093/sockjs",

        cacheRequest = false,

        apiKey,

        // var which will hold the public API we are going to expose
        methods,

        execute = function ( arr ) {
          if ( typeof arr === "function" ) {
            arr.apply( this, Array.prototype.slice.call( arguments, 1 ));
          }
          else if ( Object.prototype.toString.apply(arr) === '[object Array]' ) {
            var x = arr.length;
            while (x--) {
              arr[x].apply( this, Array.prototype.slice.call( arguments, 1 ));
            }
          }
        },

        // log helper method that doesn't break in environments
        log = function(msg) {
          if (window.console && window.console.log) {
            window.console.log( msg );
          }
        },

        // Ajax request
        request = function(options) {
          var settings = $.extend({
                type      : 'get'
              }, options);

          if ( !apiKey ) {
            return log( "(xivelyJS) ::: No API key ::: Set your API key first with xively.setKey( YOUR_API_KEY ) before using any methods. Check docs for more info." );
          }

          if ( !settings.url ) { return; }
          settings.type = settings.type.toUpperCase();

          if ( settings.type === "PUT" || settings.type === "POST" ) {
            if ( !settings.data || typeof settings.data !== 'object' ) {
              return;
            }
            else {
              settings.data = JSON.stringify(settings.data);
            }
          }

          $.ajax({
            url         : settings.url,
            type        : settings.type,
            headers     : {
              "X-ApiKey" : apiKey
            },
            data        : settings.data,
            crossDomain : true,
            dataType    : 'json',
            cache       : cacheRequest
          })
          .done(settings.done)
          .fail(settings.fail)
          .always(settings.always);
        },

        ws = {
          socket: false,
          socketReady: false,
          queue: [],
          resources: [],
          connect: function(callback) {
            var SocketProvider = (window.SockJS || window.MozWebSocket || window.WebSocket),
                socketEndpoint;

            if ( !ws.socket && SocketProvider ) {
              if ( window.SockJS ) {
                socketEndpoint = sockjsEndpoint;
              } else {
                socketEndpoint = wsEndpoint;
              }

              ws.socket = new SocketProvider(socketEndpoint);

              ws.socket.onerror = function( e ) {
                if ( ws.error ) { ws.error( e, this ); }
                ws.connect();
              };

              ws.socket.onclose = function( e ) {
                if ( ws.close ) { ws.close( e, this ); }
                ws.connect();
              };

              ws.socket.onopen = function( e ) {
                ws.socketReady = true;
                if ( ws.open )         { ws.open( e, this ); }
                if ( ws.queue.length )  { execute( ws.queue ); }
                if ( callback )         { callback( this ); }
              };

              ws.socket.onmessage = function( e ) {
                var data      = e.data,
                    response  = JSON.parse( data );
                if ( response.body ) {
                  $('body').trigger( "xively."+ response.resource, response.body );
                }
              };
            }
          },
          subscribe: function(resource, callback) {
            var request  = '{"headers":{"X-ApiKey":"' + apiKey + '"}, "method":"subscribe", "resource":"'+ resource +'"}';

            if ( !apiKey ) {
              return log( "(xivelyJS) ::: No API key ::: Set your API key first with xively.setKey( YOUR_API_KEY ) before using any methods. Check docs for more info." );
            }

            if ( ws.resources.indexOf(resource) < 0 ) {
              ws.resources.push( resource );

              if ( !ws.socketReady ) {
                ws.connect();
                ws.queue.push(function() {
                  ws.socket.send( request );
                });
              }
              else {
                ws.socket.send( request );
              }
            }

            if ( callback && typeof callback === "function" ) {
              $( document ).on( "xively."+ resource, callback );
            }
          },
          unsubscribe: function(resource) {
            var index = ws.resources.indexOf(resource);

            if (index >= 0) {
              ws.resources.splice(index, 1);
            }

            var request  = '{"headers":{"X-ApiKey":"' + apiKey + '"}, "method":"unsubscribe", "resource":"'+ resource +'"}';

            if ( !apiKey ) {
              return log( "(xivelyJS) ::: No API key ::: Set your API key first with xively.setKey( YOUR_API_KEY ) before using any methods. Check docs for more info." );
            }

            if ( ws.socket ) {
              ws.socket.send( request );
            }
          }
        };

    // disable caching
    $.ajaxSetup ({
      cache: cacheRequest
    });

    this.version = function() {
      return version;
    };

    // ---------------------------------
    // Set api credentials and endpoints
    //
    this.setKey = function(newKey) {
      apiKey = newKey;
    };

    this.setApiEndpoint = function(endpoint) {
      apiEndpoint = endpoint;
    };

    this.setWsEndpoint = function(endpoint) {
      wsEndpoint = endpoint;
    };

    this.setSockJSEndpoint = function(endpoint) {
      sockjsEndpoint = endpoint;
    };

    // ---------------------------------
    // Expose api endpoint
    //
    this.apiEndpoint = apiEndpoint;

    // ---------------------------------
    // General API interaction functions
    //
    this.request = request;

    this.subscribe = ws.subscribe.bind(ws);

    this.unsubscribe = ws.unsubscribe.bind(ws);

    this.live = function ( selector, resource ) {
      var callback = function ( event, data ) {
        var response = event.current_value ? event : data;
        if ( response.current_value ) {
          $( selector ).each(function() {
            $( this ).html( response.current_value ).attr( 'data-xively-resource', resource );
          });
        }
      };
      request({
        url    : apiEndpoint + resource,
        always : callback
      });
      ws.subscribe( resource, callback );
    };

    this.stop = function ( selector ) {
      ws.unsubscribe( $( selector ).first().attr( 'data-xively-resource' ) );
    };

    // ---------------------------------
    // Feed module
    //
    this.feed = {
      get: function(id, callback) {
        request({
          url: apiEndpoint + "/feeds/" + id,
          always: callback
        });
      },

      update: function(id, data, callback) {
        request({
          type    : "put",
          url     : apiEndpoint +"/feeds/"+ id +".json",
          data    : data,
          always  : callback
        });
      },

      'new': function(data, callback) {
        request({
          type    : "post",
          url     : apiEndpoint +"/feeds",
          data    : data,
          always  : callback
        });
      },

      'delete' : function ( id, callback ) {
        request({
          type    : "delete",
          url     : apiEndpoint +"/feeds/"+ id,
          always  : callback
        });
      },

      history : function ( id, options, callback ) {
        request({
          url     : apiEndpoint +"/feeds/"+ id +".json",
          data    : options,
          always  : callback
        });
      },

      list : function ( options, callback ) {
        request({
          url     : apiEndpoint +"/feeds",
          data    : options,
          always  : callback
        });
      },

      subscribe: function(id, callback) {
        if (id) {
          ws.subscribe("/feeds/" + id, callback);
        }
      },

      unsubscribe : function ( id, callback ) {
        if ( id ) {
          ws.unsubscribe( "/feeds/"+ id );
        }
      }
    };

    // ---------------------------------
    // Datastream module
    //
    this.datastream = {
      get : function ( feed_id, datastream_id, callback ) {
        request({
          url    : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +".json",
          always : callback
        });
      },

      update : function ( feed_id, datastream_id, data, callback ) {
        request({
          type    : "put",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +".json",
          data    : data,
          always  : callback
        });
      },

      'new' : function ( feed_id, data, callback ) {
        request({
          type    : "post",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams",
          data    : data,
          always  : callback
        });
      },

      'delete' : function ( feed_id, datastream_id, callback ) {
        request({
          type    : "delete",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id,
          always  : callback
        });
      },

      history : function ( feed_id, datastream_id, options, callback ) {
        request({
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +".json",
          data    : options,
          always  : callback
        });
      },

      list : function ( feed_id, callback ) {
        request({
          url     : apiEndpoint +"/feeds/"+ feed_id +".json",
          always  : function ( data ) {
            callback.call( this, data.datastreams );
          }
        });
      },

      subscribe : function ( feed_id, datastream_id, callback ) {
        if ( feed_id && datastream_id ) {
          ws.subscribe( "/feeds/"+ feed_id +"/datastreams/"+ datastream_id, callback );
        }
      },

      unsubscribe : function ( feed_id, datastream_id, callback ) {
        if ( feed_id && datastream_id ) {
          ws.unsubscribe( "/feeds/"+ feed_id +"/datastreams/"+ datastream_id );
        }
      },

      live : function ( element, feed_id, datastream_id ) {
        if ( element && feed_id && datastream_id ) {
          this.live( element, "/feeds/"+ feed_id +"/datastreams/"+ datastream_id );
        }
      },

      stop : function ( element ) {
        if ( element ) {
          this.stop( element );
        }
      }

    };

    // ---------------------------------
    // Datapoint module
    //
    this.datapoint = {
      get : function ( feed_id, datastream_id, timestamp, callback ) {
        request({
          url    : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints/"+ timestamp,
          always : callback
        });
      },

      update : function ( feed_id, datastream_id, timestamp, value, callback ) {
        request({
          type    : "put",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints/"+ timestamp,
          data    : {
            "value": value
          },
          always  : callback
        });
      },

      'new' : function ( feed_id, datastream_id, data, callback ) {
        request({
          type    : "post",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints",
          data    : data,
          always  : callback
        });
      },

      'delete' : function ( feed_id, datastream_id, timestamp, callback ) {
        var req_options = {
          type   : "delete",
          always : callback
        };

        if ( typeof timestamp === "object" ) {
          req_options.url  = apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints";
          req_options.data = timestamp;
        }
        else {
          req_options.url = apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints/"+ timestamp;
        }

        request( req_options );
      },

      history : function ( feed_id, datastream_id, options, callback ) {
        request({
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +".json",
          data    : options,
          always  : function ( data ) {
            callback.call( this, data.datapoints );
          }
        });
      }
    };

    this._settings = function() {
      return {
        apiKey: apiKey,
        apiEndpoint: apiEndpoint,
        wsEndpoint: wsEndpoint,
        sockjsEndpoint: sockjsEndpoint,
        cacheRequest: cacheRequest
      };
    };

    return this;
  };

  root.XivelyClient = XivelyClient;
  root.xively = root.Xively = new XivelyClient();

}).call(this);
<commit_msg>Set up the subscribe/unsubscribe callbacks explicitly.<commit_after>(function() {
  "use strict";

  // Save a reference to the global object
  var root = this,

      // Allow use of jQuery, Zepto or ender with Xively.js in the style of Backbone
      $ = root.jQuery || root.Zepto || root.ender || root.$;

  var XivelyClient = function() {

    // private stuff
    var version = "1.0.4-alpha",

        apiEndpoint = "https://api.xively.com/v2",

        wsEndpoint = "ws://api.xively.com:8080",

        sockjsEndpoint = "https://api.xively.com:8093/sockjs",

        cacheRequest = false,

        apiKey,

        // var which will hold the public API we are going to expose
        methods,

        execute = function ( arr ) {
          if ( typeof arr === "function" ) {
            arr.apply( this, Array.prototype.slice.call( arguments, 1 ));
          }
          else if ( Object.prototype.toString.apply(arr) === '[object Array]' ) {
            var x = arr.length;
            while (x--) {
              arr[x].apply( this, Array.prototype.slice.call( arguments, 1 ));
            }
          }
        },

        // log helper method that doesn't break in environments
        log = function(msg) {
          if (window.console && window.console.log) {
            window.console.log( msg );
          }
        },

        // Ajax request
        request = function(options) {
          var settings = $.extend({
                type      : 'get'
              }, options);

          if ( !apiKey ) {
            return log( "(xivelyJS) ::: No API key ::: Set your API key first with xively.setKey( YOUR_API_KEY ) before using any methods. Check docs for more info." );
          }

          if ( !settings.url ) { return; }
          settings.type = settings.type.toUpperCase();

          if ( settings.type === "PUT" || settings.type === "POST" ) {
            if ( !settings.data || typeof settings.data !== 'object' ) {
              return;
            }
            else {
              settings.data = JSON.stringify(settings.data);
            }
          }

          $.ajax({
            url         : settings.url,
            type        : settings.type,
            headers     : {
              "X-ApiKey" : apiKey
            },
            data        : settings.data,
            crossDomain : true,
            dataType    : 'json',
            cache       : cacheRequest
          })
          .done(settings.done)
          .fail(settings.fail)
          .always(settings.always);
        },

        ws = {
          socket: false,
          socketReady: false,
          queue: [],
          resources: [],
          connect: function(callback) {
            var SocketProvider = (window.SockJS || window.MozWebSocket || window.WebSocket),
                socketEndpoint;

            if ( !ws.socket && SocketProvider ) {
              if ( window.SockJS ) {
                socketEndpoint = sockjsEndpoint;
              } else {
                socketEndpoint = wsEndpoint;
              }

              ws.socket = new SocketProvider(socketEndpoint);

              ws.socket.onerror = function( e ) {
                if ( ws.error ) { ws.error( e, this ); }
                ws.connect();
              };

              ws.socket.onclose = function( e ) {
                if ( ws.close ) { ws.close( e, this ); }
                ws.connect();
              };

              ws.socket.onopen = function( e ) {
                ws.socketReady = true;
                if ( ws.open )         { ws.open( e, this ); }
                if ( ws.queue.length )  { execute( ws.queue ); }
                if ( callback )         { callback( this ); }
              };

              ws.socket.onmessage = function( e ) {
                var data      = e.data,
                    response  = JSON.parse( data );
                if ( response.body ) {
                  $('body').trigger( "xively."+ response.resource, response.body );
                }
              };
            }
          },
          subscribe: function(resource, callback) {
            var request  = '{"headers":{"X-ApiKey":"' + apiKey + '"}, "method":"subscribe", "resource":"'+ resource +'"}';

            if ( !apiKey ) {
              return log( "(xivelyJS) ::: No API key ::: Set your API key first with xively.setKey( YOUR_API_KEY ) before using any methods. Check docs for more info." );
            }

            if ( ws.resources.indexOf(resource) < 0 ) {
              ws.resources.push( resource );

              if ( !ws.socketReady ) {
                ws.connect();
                ws.queue.push(function() {
                  ws.socket.send( request );
                });
              }
              else {
                ws.socket.send( request );
              }
            }

            if ( callback && typeof callback === "function" ) {
              $( document ).on( "xively."+ resource, callback );
            }
          },
          unsubscribe: function(resource) {
            var index = ws.resources.indexOf(resource);

            if (index >= 0) {
              ws.resources.splice(index, 1);
            }

            var request  = '{"headers":{"X-ApiKey":"' + apiKey + '"}, "method":"unsubscribe", "resource":"'+ resource +'"}';

            if ( !apiKey ) {
              return log( "(xivelyJS) ::: No API key ::: Set your API key first with xively.setKey( YOUR_API_KEY ) before using any methods. Check docs for more info." );
            }

            if ( ws.socket ) {
              ws.socket.send( request );
            }
          }
        };

    // disable caching
    $.ajaxSetup ({
      cache: cacheRequest
    });

    this.version = function() {
      return version;
    };

    // ---------------------------------
    // Set api credentials and endpoints
    //
    this.setKey = function(newKey) {
      apiKey = newKey;
    };

    this.setApiEndpoint = function(endpoint) {
      apiEndpoint = endpoint;
    };

    this.setWsEndpoint = function(endpoint) {
      wsEndpoint = endpoint;
    };

    this.setSockJSEndpoint = function(endpoint) {
      sockjsEndpoint = endpoint;
    };

    // ---------------------------------
    // Expose api endpoint
    //
    this.apiEndpoint = apiEndpoint;

    // ---------------------------------
    // General API interaction functions
    //
    this.request = request;

    // this.subscribe = ws.subscribe.bind(ws);
    this.subscribe = function(resource, callback) {
      ws.subscribe(resource, callback);
    };

    this.unsubscribe = function(resource) {
      ws.unsubscribe(resource);
    };

    this.live = function (selector, resource) {
      var callback = function ( event, data ) {
        var response = event.current_value ? event : data;
        if ( response.current_value ) {
          $( selector ).each(function() {
            $( this ).html( response.current_value ).attr( 'data-xively-resource', resource );
          });
        }
      };
      request({
        url    : apiEndpoint + resource,
        always : callback
      });
      ws.subscribe( resource, callback );
    };

    this.stop = function ( selector ) {
      ws.unsubscribe( $( selector ).first().attr( 'data-xively-resource' ) );
    };

    // ---------------------------------
    // Feed module
    //
    this.feed = {
      get: function(id, callback) {
        request({
          url: apiEndpoint + "/feeds/" + id,
          always: callback
        });
      },

      update: function(id, data, callback) {
        request({
          type    : "put",
          url     : apiEndpoint +"/feeds/"+ id +".json",
          data    : data,
          always  : callback
        });
      },

      'new': function(data, callback) {
        request({
          type    : "post",
          url     : apiEndpoint +"/feeds",
          data    : data,
          always  : callback
        });
      },

      'delete' : function ( id, callback ) {
        request({
          type    : "delete",
          url     : apiEndpoint +"/feeds/"+ id,
          always  : callback
        });
      },

      history : function ( id, options, callback ) {
        request({
          url     : apiEndpoint +"/feeds/"+ id +".json",
          data    : options,
          always  : callback
        });
      },

      list : function ( options, callback ) {
        request({
          url     : apiEndpoint +"/feeds",
          data    : options,
          always  : callback
        });
      },

      subscribe: function(id, callback) {
        if (id) {
          ws.subscribe("/feeds/" + id, callback);
        }
      },

      unsubscribe : function ( id, callback ) {
        if ( id ) {
          ws.unsubscribe( "/feeds/"+ id );
        }
      }
    };

    // ---------------------------------
    // Datastream module
    //
    this.datastream = {
      get : function ( feed_id, datastream_id, callback ) {
        request({
          url    : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +".json",
          always : callback
        });
      },

      update : function ( feed_id, datastream_id, data, callback ) {
        request({
          type    : "put",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +".json",
          data    : data,
          always  : callback
        });
      },

      'new' : function ( feed_id, data, callback ) {
        request({
          type    : "post",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams",
          data    : data,
          always  : callback
        });
      },

      'delete' : function ( feed_id, datastream_id, callback ) {
        request({
          type    : "delete",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id,
          always  : callback
        });
      },

      history : function ( feed_id, datastream_id, options, callback ) {
        request({
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +".json",
          data    : options,
          always  : callback
        });
      },

      list : function ( feed_id, callback ) {
        request({
          url     : apiEndpoint +"/feeds/"+ feed_id +".json",
          always  : function ( data ) {
            callback.call( this, data.datastreams );
          }
        });
      },

      subscribe : function ( feed_id, datastream_id, callback ) {
        if ( feed_id && datastream_id ) {
          ws.subscribe( "/feeds/"+ feed_id +"/datastreams/"+ datastream_id, callback );
        }
      },

      unsubscribe : function ( feed_id, datastream_id, callback ) {
        if ( feed_id && datastream_id ) {
          ws.unsubscribe( "/feeds/"+ feed_id +"/datastreams/"+ datastream_id );
        }
      },

      live : function ( element, feed_id, datastream_id ) {
        if ( element && feed_id && datastream_id ) {
          this.live( element, "/feeds/"+ feed_id +"/datastreams/"+ datastream_id );
        }
      },

      stop : function ( element ) {
        if ( element ) {
          this.stop( element );
        }
      }

    };

    // ---------------------------------
    // Datapoint module
    //
    this.datapoint = {
      get : function ( feed_id, datastream_id, timestamp, callback ) {
        request({
          url    : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints/"+ timestamp,
          always : callback
        });
      },

      update : function ( feed_id, datastream_id, timestamp, value, callback ) {
        request({
          type    : "put",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints/"+ timestamp,
          data    : {
            "value": value
          },
          always  : callback
        });
      },

      'new' : function ( feed_id, datastream_id, data, callback ) {
        request({
          type    : "post",
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints",
          data    : data,
          always  : callback
        });
      },

      'delete' : function ( feed_id, datastream_id, timestamp, callback ) {
        var req_options = {
          type   : "delete",
          always : callback
        };

        if ( typeof timestamp === "object" ) {
          req_options.url  = apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints";
          req_options.data = timestamp;
        }
        else {
          req_options.url = apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +"/datapoints/"+ timestamp;
        }

        request( req_options );
      },

      history : function ( feed_id, datastream_id, options, callback ) {
        request({
          url     : apiEndpoint +"/feeds/"+ feed_id +"/datastreams/"+ datastream_id +".json",
          data    : options,
          always  : function ( data ) {
            callback.call( this, data.datapoints );
          }
        });
      }
    };

    this._settings = function() {
      return {
        apiKey: apiKey,
        apiEndpoint: apiEndpoint,
        wsEndpoint: wsEndpoint,
        sockjsEndpoint: sockjsEndpoint,
        cacheRequest: cacheRequest
      };
    };

    return this;
  };

  root.XivelyClient = XivelyClient;
  root.xively = root.Xively = new XivelyClient();

}).call(this);
<|endoftext|>


<commit_before>// fix Promise Problem on JSContext of iOS7~8
// @see https://bugs.webkit.org/show_bug.cgi?id=135866
const { WXEnvironment } = global
if (WXEnvironment && WXEnvironment.platform === 'iOS') {
  global.Promise = null
}
import 'core-js/modules/es6.object.to-string'
import 'core-js/modules/es6.string.iterator'
import 'core-js/modules/web.dom.iterable'
import 'core-js/modules/es6.promise'
<commit_msg>* [jsfm] adapted Promise polyfill with Vue 2.0<commit_after>// fix Promise Problem on JSContext of iOS7~8
// @see https://bugs.webkit.org/show_bug.cgi?id=135866
const { WXEnvironment } = global
if (WXEnvironment && WXEnvironment.platform === 'iOS') {
  global.Promise = undefined
}
import 'core-js/modules/es6.object.to-string'
import 'core-js/modules/es6.string.iterator'
import 'core-js/modules/web.dom.iterable'
import 'core-js/modules/es6.promise'
<|endoftext|>


<commit_before><commit_msg>changed directory structure<commit_after><|endoftext|>


<commit_before>$(document).ready(function () {
    var $range = $('.js-search-criteria-range');
    var $multi = $('.js-search-criteria-multi');
    var $must = $('.js-search-criteria-must');
    var $all = $multi.add($must);
    var $search = $('.js-search-criteria-fulltext');
    var $hint = $('#js-count-hint');
    var $loader = $('.js-count-loader', $hint);
    var $count = $('.js-count-result', $hint);
    var $empty = $('.js-empty', $hint);
    var $submit = $('.js-submit', $hint);
    var $container = $('.js-container');

    function getCriteria() {
        var criteria = [];

        $all.each(function () {
            var $this = $(this);
            var list = [];
            $('input:checked', $this).each(function () {
                list.push($(this).attr('data-alias'));
            });
            if (list.length) {
                criteria.push($this.attr('data-param') + '=' + list.join());
            }
        });

        $range.each(function () {
            var $this = $(this);

            criteria.push($this.attr('data-param') + '=' + $('.js-range-from', $this).val() + '-' + $('.js-range-to', $this).val());
        });

        criteria.push('search' + '=' + $search.val());

        return '?' + criteria.join('&');
    }

    function search() {
        window.location.href = '/developers' + getCriteria();
    }

    function setCountOffset(top) {
        $hint.css('top', top);
    }

    function showCount(props) {
        $hint.toggleClass('shown', props.shown);
        $loader.toggleClass('loader', props.loaded);
        $count.html(props.count);
        $empty.toggle(props.empty);
        $submit.toggle(props.submit);
    }

    function showConcreteCountMap($map, map) {
        var param = $map.attr('data-param');
        $('input', $map).each(function () {
            var $input = $(this);
            var alias = $input.attr('data-alias');
            var count = map[param][alias] || 0;
            $input.next('label').find('span.badge').html(count);
        });
    }

    function showCountMap(response) {
        showConcreteCountMap($multi, response.multi);
        showConcreteCountMap($must, response.must);
    }

    function getCount() {
        showCount({
            shown: true,
            loaded: true,
            submit: true,
            empty: false,
            count: ''
        });
        $.ajax({
            url: '/api/v1/developers/count.json' + getCriteria(),
            success: function (response) {
                showCount({
                    shown: true,
                    loaded: false,
                    submit: response.count > 0,
                    empty: response.count === 0,
                    count: response.count
                });
                showCountMap(response);
            }
        });
    }

    $(document).on('click', '.js-search-submit', search);
    $submit.on('click', search);
    $('input', $all).on('change', function () {
        setCountOffset($(this).offset().top - $container.offset().top);
        getCount();
    });
    $hint.on('click', '.js-close', function () {
        showCount({
            shown: false,
            loaded: false,
            submit: true,
            empty: false,
            count: '',
        });
    });
    $search.add($range).on('keyup', function (event) {
        if (event.keyCode === 0b1101) {
            search();
        }
    });
});<commit_msg>Update experience & salary range from API Count map #63<commit_after>$(document).ready(function () {
    var $range = $('.js-search-criteria-range');
    var $multi = $('.js-search-criteria-multi');
    var $must = $('.js-search-criteria-must');
    var $all = $multi.add($must);
    var $search = $('.js-search-criteria-fulltext');
    var $hint = $('#js-count-hint');
    var $loader = $('.js-count-loader', $hint);
    var $count = $('.js-count-result', $hint);
    var $empty = $('.js-empty', $hint);
    var $submit = $('.js-submit', $hint);
    var $container = $('.js-container');

    function getCriteria() {
        var criteria = [];

        $all.each(function () {
            var $this = $(this);
            var list = [];
            $('input:checked', $this).each(function () {
                list.push($(this).attr('data-alias'));
            });
            if (list.length) {
                criteria.push($this.attr('data-param') + '=' + list.join());
            }
        });

        $range.each(function () {
            var $this = $(this);

            criteria.push($this.attr('data-param') + '=' + $('.js-range-from', $this).val() + '-' + $('.js-range-to', $this).val());
        });

        criteria.push('search' + '=' + $search.val());

        return '?' + criteria.join('&');
    }

    function search() {
        window.location.href = '/developers' + getCriteria();
    }

    function setCountOffset(top) {
        $hint.css('top', top);
    }

    function showCount(props) {
        $hint.toggleClass('shown', props.shown);
        $loader.toggleClass('loader', props.loaded);
        $count.html(props.count);
        $empty.toggle(props.empty);
        $submit.toggle(props.submit);
    }

    function showConcreteCountMap($map, map) {
        var param = $map.attr('data-param');
        $('input', $map).each(function () {
            var $input = $(this);
            var alias = $input.attr('data-alias');
            var count = map[param][alias] || 0;
            $input.next('label').find('span.badge').html(count);
        });
    }

    function updateCountMap(response) {
        showConcreteCountMap($multi, response.multi);
        showConcreteCountMap($must, response.must);
    }

    function updateRange(response) {
        $range.each(function () {
            var $this = $(this);
            var param = $this.attr('data-param');

            if (response.range.hasOwnProperty(param)) {
                var range = response.range[param];

                $('.js-range-from', $this).attr('placeholder', range.from);
                $('.js-range-to', $this).attr('placeholder', range.to);
            }
        });
    }

    function getCount() {
        showCount({
            shown: true,
            loaded: true,
            submit: true,
            empty: false,
            count: ''
        });
        $.ajax({
            url: '/api/v1/developers/count.json' + getCriteria(),
            success: function (response) {
                showCount({
                    shown: true,
                    loaded: false,
                    submit: response.count > 0,
                    empty: response.count === 0,
                    count: response.count
                });
                updateCountMap(response);
                updateRange(response);
            }
        });
    }

    $(document).on('click', '.js-search-submit', search);
    $submit.on('click', search);
    $('input', $all).on('change', function () {
        setCountOffset($(this).offset().top - $container.offset().top);
        getCount();
    });
    $hint.on('click', '.js-close', function () {
        showCount({
            shown: false,
            loaded: false,
            submit: true,
            empty: false,
            count: '',
        });
    });
    $search.add($range).on('keyup', function (event) {
        if (event.keyCode === 0b1101) {
            search();
        }
    });
});<|endoftext|>


<commit_before>'use strict';

var BearerToken = require('./bearer');
var Inflector = require('inflected');
var Mutation = require('./mutation');

var REST = {
  index: { endpoint: '/', method: 'get' },
  new: { endpoint: '/', method: 'post' },
  show: { endpoint: '/:id', method: 'get' },
  update: { endpoint: '/:id', method: 'put' },
  delete: { endpoint: '/:id', method: 'delete' }
};

var Routes = function(express, DS) {
  var Builder = { express: express };
  var middleware = [];
  var controllers = [];
  var DS = {};
  var Scopes = {};
  var Instance = {};

  Builder.mount = function(models, instanceObj) {
    DS = models;
    Instance = instanceObj;

    for (var i = 0; i < controllers.length; i++) {
      Builder.route(controllers[i](DS, Mutation(DS, Instance)));
    }
  };

  Builder.addController = function(controller) {
    controllers.push(controller);
  };

  Builder.registerMiddleware = function(func) {
    middleware.push(func);
  };

  Builder.mixInController = function(spec, action) {
    return function(req, res, next) {
      var resource = Inflector.singularize(Inflector.camelize(req.route.path.split('/')[1]));

      req.controller = {
        spec: spec,
        action: action,
        permissions: Instance.scope[resource],
        model: resource
      };

      next();
    };
  };

  Builder.runMiddlewares = function(req, res, next) {
    if (middleware.length < 1) return next();

    for (var i = 0; i < middleware.length; i++) {
      middleware[i](req, res, next);
    }
  };

  // Sets an individual route
  Builder.route = function(controller) {
    controller._expose.forEach(function(el, i, arr) {
      if (typeof el === 'object') Builder.customRoute(controller._verb, el, controller[el.name]);
      if (typeof el === 'string') Builder.restRoute(controller._verb, el, controller[el]);
    });
  };

  // Handles a non-RESTful controller method
  Builder.customRoute = function(verb, spec, action) {
    if (!spec || !action) return;

    var method = spec.method;
    var endpoint = '/' + verb;

    if (spec.endpoint !== '/') endpoint += '/' + spec.endpoint;

    express[method](
      endpoint,
      Builder.mixInController(spec, action),
      BearerToken.serialize,
      Builder.findUser,
      Builder.catchScope,
      Builder.runMiddlewares,
      action.responder
    );
  };

  // Handles a RESTful controller method
  Builder.restRoute = function(verb, name, action) {
    if (!REST[name] || !action) return;

    var method = REST[name].method;
    var endpoint = '/' + verb;

    if (REST[name].endpoint !== '/') endpoint += REST[name].endpoint;

    express[method](
      endpoint,
      Builder.mixInController({ verb: verb, name: name }, action),
      BearerToken.serialize,
      Builder.findUser,
      Builder.resourceQuery,
      Builder.runQuery,
      Builder.catchScope,
      Builder.filterAllowedFields,
      Builder.runMiddlewares,
      action.responder
    );
  };

  Builder.findUser = function(req, res, next) {
    if (!req.bearerToken) return next();

    var User = DS[Instance.scopable.model];
    var query = User.findOne({ _id: req.bearerToken.user });

    query.lean().exec(function(err, user) {
      if (err) return res.status(500).send({ error: err });

      req.user = user;
      return next();
    });
  };

  Builder.catchScope = function(req, res, next) {
    var ownership = false;
    var permissions = req.controller.permissions.read;

    req.caughtScope = '*';

    if (req.user) {
      var userScopes = req.user[Instance.scopable.field];
      ownership = Builder._checkForOwnership(req);
      req.caughtScope = (ownership) ? 'owner' : Builder._highestScope(permissions, userScopes);
    }

    if (permissions === true || permissions[req.caughtScope] === true) {
      req.allowedFields = true;
      return next();
    } else if (Array.isArray(permissions)) {
      req.allowedFields = permissions;
      return next();
    } else if (Array.isArray(permissions[req.caughtScope])) {
      req.allowedFields = permissions[req.caughtScope];
      return next();
    }

    // The user is not authorized to see this resource
    return res.status(401).send({ error: 'Insufficient permission for that' });
  };

  Builder.resourceQuery = function(req, res, next) {
    req.searchParams = {};

    if (!req.params.id && req.controller.permissions.searchableBy) {
      var allowed = req.controller.permissions.searchableBy;

      for (var i = 0; i < allowed.length; i++) {
        if (req.query[allowed[i]]) req.searchParams[allowed[i]] = req.query[allowed[i]];
      }
    }

    return next();
  };

  Builder.runQuery = function(req, res, next) {
    var Model = DS[req.controller.model];
    req.rawResources = {};

    if (req.params.id) {
      var q = Model.findById(req.params.id);

      q.exec(function(err, result) {
        req.rawResources = result;
        return next();
      });
    } else if (!req.params.id && req.method === 'GET') {
      var q = Model.find(req.searchParams).limit(req.query.limit || 20);

      q.exec(function(err, result) {
        req.rawResources = result;
        return next();
      });
    } else {
      return next();
    }
  };

  Builder.filterAllowedFields = function(req, res, next) {
    if (req.allowedFields !== true) req.allowedFields.push('_id');

    if (Array.isArray(req.rawResources)) {
      req.resource = [];
      for (var i = 0; i < req.rawResources.length; i++) {
        req.resource.push(Builder.filterFromResource(req.rawResources[i], req.allowedFields));
      }
    } else {
      req.resource = Builder.filterFromResource(req.rawResources, req.allowedFields);
    }

    next();
  };

  Builder.filterFromResource = function(resource, allowed) {
    if (allowed === true) return resource;
    var safeResource = {};

    for (var i = 0; i < allowed.length; i++) {
      safeResource[allowed[i]] = resource[allowed[i]];
    }

    return safeResource;
  };

  Builder._checkForOwnership = function(req) {
    var model = req.controller.model;
    var permissions = req.controller.permissions;

    if (!permissions.owners || permissions.owners.length < 1) return false;
    if (Array.isArray(req.rawResources)) return false;
    if (!req.user) return false;

    for (var i = 0; i < permissions.owners.length; i++) {
      if (req.rawResources[permissions.owners[i]].toString() === req.user._id.toString()) return true;
    }

    return false;
  };

  Builder._highestScope = function(permissions, scopes) {
    if (typeof permissions === 'undefined') return '*';

    var highest = 0;
    var fieldCount = 0;

    scopes.unshift('*');

    for (var i = 0; i < scopes.length; i++) {
      if (permissions === true || Array.isArray(permissions)) {
        return '*';
      } else if (permissions[scopes[i]] === true) {
        return scopes[i];
      } else if (Array.isArray(permissions[scopes[i]]) && (fieldCount < permissions[scopes[i]].length)) {
        highest = i;
        fieldCount = permissions[scopes[i]].length;
      }
    }

    return scopes[highest];
  };

  return Builder;

};

module.exports = Routes;
<commit_msg>added a test for REST or custom spec<commit_after>'use strict';

var BearerToken = require('./bearer');
var Inflector = require('inflected');
var Mutation = require('./mutation');

var REST = {
  index: { endpoint: '/', method: 'get' },
  new: { endpoint: '/', method: 'post' },
  show: { endpoint: '/:id', method: 'get' },
  update: { endpoint: '/:id', method: 'put' },
  delete: { endpoint: '/:id', method: 'delete' }
};

var Routes = function(express, DS) {
  var Builder = { express: express };
  var middleware = [];
  var controllers = [];
  var DS = {};
  var Scopes = {};
  var Instance = {};

  Builder.mount = function(models, instanceObj) {
    DS = models;
    Instance = instanceObj;

    for (var i = 0; i < controllers.length; i++) {
      Builder.route(controllers[i](DS, Mutation(DS, Instance)));
    }
  };

  Builder.addController = function(controller) {
    controllers.push(controller);
  };

  Builder.registerMiddleware = function(func) {
    middleware.push(func);
  };

  Builder.mixInController = function(spec, action, rest) {
    return function(req, res, next) {
      var resource = Inflector.singularize(Inflector.camelize(req.route.path.split('/')[1]));

      req.controller = {
        spec: spec,
        action: action,
        permissions: Instance.scope[resource],
        model: resource,
        _rest: rest
      };

      next();
    };
  };

  Builder.runMiddlewares = function(req, res, next) {
    if (middleware.length < 1) return next();

    for (var i = 0; i < middleware.length; i++) {
      middleware[i](req, res, next);
    }
  };

  // Sets an individual route
  Builder.route = function(controller) {
    controller._expose.forEach(function(el, i, arr) {
      if (typeof el === 'object') Builder.customRoute(controller._verb, el, controller[el.name]);
      if (typeof el === 'string') Builder.restRoute(controller._verb, el, controller[el]);
    });
  };

  // Handles a non-RESTful controller method
  Builder.customRoute = function(verb, spec, action) {
    if (!spec || !action) return;

    var method = spec.method;
    var endpoint = '/' + verb;

    if (spec.endpoint !== '/') endpoint += '/' + spec.endpoint;

    express[method](
      endpoint,
      Builder.mixInController(spec, action, false),
      BearerToken.serialize,
      Builder.findUser,
      Builder.catchScope,
      Builder.runMiddlewares,
      action.responder
    );
  };

  // Handles a RESTful controller method
  Builder.restRoute = function(verb, name, action) {
    if (!REST[name] || !action) return;

    var method = REST[name].method;
    var endpoint = '/' + verb;

    if (REST[name].endpoint !== '/') endpoint += REST[name].endpoint;

    express[method](
      endpoint,
      Builder.mixInController({ verb: verb, name: name }, action, true),
      BearerToken.serialize,
      Builder.findUser,
      Builder.resourceQuery,
      Builder.runQuery,
      Builder.catchScope,
      Builder.filterAllowedFields,
      Builder.runMiddlewares,
      action.responder
    );
  };

  Builder.findUser = function(req, res, next) {
    if (!req.bearerToken) return next();

    var User = DS[Instance.scopable.model];
    var query = User.findOne({ _id: req.bearerToken.user });

    query.lean().exec(function(err, user) {
      if (err) return res.status(500).send({ error: err });

      req.user = user;
      return next();
    });
  };

  Builder.catchScope = function(req, res, next) {
    var ownership = false;
    var permissions = req.controller.permissions.read;

    req.caughtScope = '*';

    if (req.user) {
      var userScopes = req.user[Instance.scopable.field];
      if (req.controller._rest) ownership = Builder._checkForOwnership(req);
      req.caughtScope = (ownership) ? 'owner' : Builder._highestScope(permissions, userScopes);
    }

    if (permissions === true || permissions[req.caughtScope] === true) {
      req.allowedFields = true;
      return next();
    } else if (Array.isArray(permissions)) {
      req.allowedFields = permissions;
      return next();
    } else if (Array.isArray(permissions[req.caughtScope])) {
      req.allowedFields = permissions[req.caughtScope];
      return next();
    }

    // The user is not authorized to see this resource
    return res.status(401).send({ error: 'Insufficient permission for that' });
  };

  Builder.resourceQuery = function(req, res, next) {
    req.searchParams = {};

    if (!req.params.id && req.controller.permissions.searchableBy) {
      var allowed = req.controller.permissions.searchableBy;

      for (var i = 0; i < allowed.length; i++) {
        if (req.query[allowed[i]]) req.searchParams[allowed[i]] = req.query[allowed[i]];
      }
    }

    return next();
  };

  Builder.runQuery = function(req, res, next) {
    var Model = DS[req.controller.model];
    req.rawResources = {};

    if (req.params.id) {
      var q = Model.findById(req.params.id);

      q.exec(function(err, result) {
        req.rawResources = result;
        return next();
      });
    } else if (!req.params.id && req.method === 'GET') {
      var q = Model.find(req.searchParams).limit(req.query.limit || 20);

      q.exec(function(err, result) {
        req.rawResources = result;
        return next();
      });
    } else {
      return next();
    }
  };

  Builder.filterAllowedFields = function(req, res, next) {
    if (req.allowedFields !== true) req.allowedFields.push('_id');

    if (Array.isArray(req.rawResources)) {
      req.resource = [];
      for (var i = 0; i < req.rawResources.length; i++) {
        req.resource.push(Builder.filterFromResource(req.rawResources[i], req.allowedFields));
      }
    } else {
      req.resource = Builder.filterFromResource(req.rawResources, req.allowedFields);
    }

    next();
  };

  Builder.filterFromResource = function(resource, allowed) {
    if (allowed === true) return resource;
    var safeResource = {};

    for (var i = 0; i < allowed.length; i++) {
      safeResource[allowed[i]] = resource[allowed[i]];
    }

    return safeResource;
  };

  Builder._checkForOwnership = function(req) {
    var model = req.controller.model;
    var permissions = req.controller.permissions;

    if (!permissions.owners || permissions.owners.length < 1) return false;
    if (Array.isArray(req.rawResources)) return false;
    if (!req.user) return false;

    for (var i = 0; i < permissions.owners.length; i++) {
      if (req.rawResources[permissions.owners[i]].toString() === req.user._id.toString()) return true;
    }

    return false;
  };

  Builder._highestScope = function(permissions, scopes) {
    if (typeof permissions === 'undefined') return '*';

    var highest = 0;
    var fieldCount = 0;

    scopes.unshift('*');

    for (var i = 0; i < scopes.length; i++) {
      if (permissions === true || Array.isArray(permissions)) {
        return '*';
      } else if (permissions[scopes[i]] === true) {
        return scopes[i];
      } else if (Array.isArray(permissions[scopes[i]]) && (fieldCount < permissions[scopes[i]].length)) {
        highest = i;
        fieldCount = permissions[scopes[i]].length;
      }
    }

    return scopes[highest];
  };

  return Builder;

};

module.exports = Routes;
<|endoftext|>


<commit_before>/* PLUGINS */
const gulp = require('gulp');
const sass = require('gulp-sass');
const browserSync = require('browser-sync').create();
const runSequence = require('run-sequence');
const inject = require('gulp-inject');
const angularFilesort = require('gulp-angular-filesort');
const copy = require('gulp-copy');
const del = require('del');
const es = require('event-stream');
const concat = require('gulp-concat');
const fs = require('fs');
const scp = require('gulp-scp2')

/* PATHS */
const distDir = './dist';
const distStylesDir = distDir + '/styles';
const distScriptsDir = distDir + '/scripts';
const distImagesDir = distDir + '/images';
const srcDir = './client';

gulp.task('concatVendorJs', () => {
  return gulp.src([
    'node_modules/jquery/dist/jquery.min.js',
    'node_modules/angular/angular.min.js',
    'node_modules/angular-animate/angular-animate.js',
    'node_modules/angular-route/angular-route.min.js',
    'node_modules/angular-ui-bootstrap/dist/ui-bootstrap.js',
    'node_modules/angular-ui-bootstrap/dist/ui-bootstrap-tpls.js',
    'node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js',
    'node_modules/moment/moment.js',
    'node_modules/bootstrap-daterangepicker/daterangepicker.js'
  ])
    .pipe(concat('vendor.js'))
    .pipe(gulp.dest(distScriptsDir))
});

gulp.task('concatVendorCss', () => {
  return gulp.src([
    'node_modules/bootstrap/dist/css/bootstrap.css',
    'node_modules/bootstrap-daterangepicker/daterangepicker.css'
  ])
    .pipe(concat('vendor.css'))
    .pipe(gulp.dest(distStylesDir))
});

gulp.task('copy', () => {
  return es.merge(
    /* index.html */
    gulp.src(`${srcDir}/index.html`)
      .pipe(gulp.dest(distDir)),

    /* JS */
    gulp.src(`${srcDir}/mealpler/**/*.{js,html,htm}`)
      .pipe(gulp.dest(distScriptsDir)),

    /* Images */
    gulp.src(`${srcDir}/assets/images/**/*.{png,ico,jpg}`)
      .pipe(gulp.dest(distImagesDir))
  )
});

gulp.task('clean', () => {
  return del(distDir);
});

gulp.task('sass', () => {
  return gulp.src(`${srcDir}/assets/css/*.scss`)
    .pipe(sass())
    .pipe(gulp.dest(distStylesDir))
});

gulp.task('index', () => {
  return gulp.src(`${distDir}/index.html`)
    .pipe(inject(
      gulp.src([ `${distScriptsDir}/**/*.js`, `!${distScriptsDir}/vendor.js` ]).pipe(angularFilesort()).pipe(angularFilesort()), { relative: true }
    ))
    .pipe(inject(
      gulp.src(`${distScriptsDir}/vendor.js`), { relative: true, starttag: '<!-- inject:vendor:{{ext}} -->' }
    ))
    .pipe(inject(
      gulp.src(`${distStylesDir}/vendor.css`), { relative: true, starttag: '<!-- inject:vendor:{{ext}} -->' }
    ))
    .pipe(inject(
      gulp.src([`${distStylesDir}/**/*.css`, `!${distStylesDir}/vendor.css`]), { relative: true }
    ))
    .pipe(gulp.dest(distDir))
});

gulp.task('serve', () => {
  return browserSync.init({
    server: './dist',
    files: './dist/**/*',
    reloadDebounce: 250
  })
});

gulp.task('watch', () => {
  gulp.watch(`${srcDir}/mealpler/**/*.{js,html,htm}`, () => runSequence('copy', 'index'))
  gulp.watch(`${srcDir}/index.html`, () => runSequence('copy', 'index'))
  gulp.watch(`${srcDir}/assets/css/*.scss`, [ 'sass' ])
});

gulp.task('build', () => runSequence('clean', 'copy', 'concatVendorJs', 'concatVendorCss', 'sass', 'index'))

gulp.task('deploy', () => {
  const key = fs.readFileSync('key.pem', 'utf8')

  return gulp.src('dist/**/*')
    .pipe(scp({
      host: '35.156.52.114',
      username: 'ubuntu',
      privateKey: key,
      dest: '/home/ubuntu/public'
    }))
    .on('error', (err) => console.log(err))
});

gulp.task('default', () => runSequence('clean', 'copy', 'concatVendorJs', 'concatVendorCss', 'sass', 'index', 'serve', 'watch'))<commit_msg>MP-12: updated gulpfile<commit_after>/* PLUGINS */
const gulp = require('gulp');
const sass = require('gulp-sass');
const browserSync = require('browser-sync').create();
const runSequence = require('run-sequence');
const inject = require('gulp-inject');
const angularFilesort = require('gulp-angular-filesort');
const copy = require('gulp-copy');
const del = require('del');
const es = require('event-stream');
const concat = require('gulp-concat');
const fs = require('fs');
const scp = require('gulp-scp2');

/* PATHS */
const distDir = './dist';
const distStylesDir = distDir + '/styles';
const distScriptsDir = distDir + '/scripts';
const distImagesDir = distDir + '/images';
const srcDir = './client';

gulp.task('concatVendorJs', () => {
  return gulp.src([
    'node_modules/jquery/dist/jquery.min.js',
    'node_modules/angular/angular.min.js',
    'node_modules/angular-animate/angular-animate.js',
    'node_modules/angular-route/angular-route.min.js',
    'node_modules/angular-ui-bootstrap/dist/ui-bootstrap.js',
    'node_modules/angular-ui-bootstrap/dist/ui-bootstrap-tpls.js',
    'node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js',
    'node_modules/moment/moment.js',
    'node_modules/bootstrap-daterangepicker/daterangepicker.js'
  ])
    .pipe(concat('vendor.js'))
    .pipe(gulp.dest(distScriptsDir))
});

gulp.task('concatVendorCss', () => {
  return gulp.src([
    'node_modules/bootstrap/dist/css/bootstrap.css',
    'node_modules/bootstrap-daterangepicker/daterangepicker.css'
  ])
    .pipe(concat('vendor.css'))
    .pipe(gulp.dest(distStylesDir))
});

gulp.task('copy', () => {
  return es.merge(
    /* index.html */
    gulp.src(`${srcDir}/index.html`)
      .pipe(gulp.dest(distDir)),

    /* JS */
    gulp.src(`${srcDir}/mealpler/**/*.{js,html,htm}`)
      .pipe(gulp.dest(distScriptsDir)),

    /* Images */
    gulp.src(`${srcDir}/assets/images/**/*.{png,ico,jpg}`)
      .pipe(gulp.dest(distImagesDir))
  )
});

gulp.task('clean', () => {
  return del(distDir);
});

gulp.task('sass', () => {
  return gulp.src(`${srcDir}/assets/css/*.scss`)
    .pipe(sass())
    .pipe(gulp.dest(distStylesDir))
});

gulp.task('index', () => {
  return gulp.src(`${distDir}/index.html`)
    .pipe(inject(
      gulp.src([ `${distScriptsDir}/**/*.js`, `!${distScriptsDir}/vendor.js` ]).pipe(angularFilesort()).pipe(angularFilesort()), { relative: true }
    ))
    .pipe(inject(
      gulp.src(`${distScriptsDir}/vendor.js`), { relative: true, starttag: '<!-- inject:vendor:{{ext}} -->' }
    ))
    .pipe(inject(
      gulp.src(`${distStylesDir}/vendor.css`), { relative: true, starttag: '<!-- inject:vendor:{{ext}} -->' }
    ))
    .pipe(inject(
      gulp.src([`${distStylesDir}/**/*.css`, `!${distStylesDir}/vendor.css`]), { relative: true }
    ))
    .pipe(gulp.dest(distDir))
});

gulp.task('serve', () => {
  return browserSync.init({
    server: './dist',
    files: './dist/**/*',
    reloadDebounce: 250
  })
});

gulp.task('watch', () => {
  gulp.watch(`${srcDir}/mealpler/**/*.{js,html,htm}`, () => runSequence('copy', 'index'))
  gulp.watch(`${srcDir}/index.html`, () => runSequence('copy', 'index'))
  gulp.watch(`${srcDir}/assets/css/*.scss`, [ 'sass' ])
});

gulp.task('build', () => runSequence('clean', 'copy', 'concatVendorJs', 'concatVendorCss', 'sass', 'index'))

gulp.task('deploy', () => {
  const key = fs.readFileSync('key.pem', 'utf8')

  return gulp.src('dist/**/*')
    .pipe(scp({
      host: '35.156.52.114',
      username: 'ubuntu',
      privateKey: key,
      dest: '/home/ubuntu/public'
    }))
    .on('error', (err) => console.log(err))
});

gulp.task('default', () => runSequence('clean', 'copy', 'concatVendorJs', 'concatVendorCss', 'sass', 'index', 'serve', 'watch'))<|endoftext|>