<commit_before>define(["Ti/_/css", "Ti/_/declare", "Ti/UI/View", "Ti/UI", "Ti/_/lang"],
	function(css, declare, View, UI, lang) {

	var isDef = lang.isDef,
		UI_FILL = UI.FILL,
		navGroupCss = "TiUINavigationGroup";

	return declare("Ti.UI.MobileWeb.NavigationGroup", View, {

		constructor: function(args) {
			var self = this,
				win = self.constants.window = args && args.window,
				tab = args && args._tab,
				navBarContainer = self._navBarContainer = UI.createView({
					height: 50,
					width: UI.FILL,
					layout: UI._LAYOUT_CONSTRAINING_HORIZONTAL
				});
			css.add(navBarContainer.domNode, navGroupCss);
			self.layout = UI._LAYOUT_CONSTRAINING_VERTICAL;

			// Create the nav bar content
			navBarContainer.add(self._leftContainer = Ti.UI.createView({
				width: UI.SIZE,
				height: "100%",
				left: 5,
				right: 5
			}));
			navBarContainer.add(self._centerContainer = Ti.UI.createView({
				width: UI.FILL,
				height: "100%"
			}));
			navBarContainer.add(self._rightContainer = Ti.UI.createView({
				width: UI.SIZE,
				height: "100%",
				left: 5,
				right: 5
			}));
			self._add(navBarContainer);

			// Create the content container
			self._add(self._contentContainer = UI.createView({
				width: UI_FILL,
				height: UI_FILL
			}));

			// Stylize the top
			this.navBarAtTop = true;
			navBarContainer._getBorderFromCSS();

			// Initialize the window stack and add the root window
			self._windows = [];
			win && self.open(win);
		},

		_defaultWidth: UI_FILL,

		_defaultHeight: UI_FILL,

		_updateNavBar: function() {
			var _self = this,
				windows = _self._windows,
				len = windows.length,
				activeWin = windows[len - 1],
				navBarContainer = this._navBarContainer,
				leftContainer = _self._leftContainer,
				centerContainer = _self._centerContainer,
				rightContainer = _self._rightContainer,
				leftView,
				centerView,
				rightView = activeWin.rightNavButton;

			if (activeWin.leftNavButton) {
				leftView = activeWin.leftNavButton;
			} else {
				if (!_self._backButton) {
					_self._backButton = Ti.UI.createButton({
						title: "Back"
					});
					require.on(_self._backButton, "singletap", function() {
						// Note: we can reuse activeWin or length because they may have changed by the time this event
						// listener is called due to reuse of the back button across windows.
						_self.close(windows[windows.length - 1]);
					});
				};
				len > 1 && (leftView = _self._backButton);
			}
			if (leftContainer._children[0] !== leftView) {
				leftContainer._removeAllChildren();
				leftView && leftContainer._add(leftView);
			}

			if (rightContainer._children[0] !== rightView) {
				rightContainer._removeAllChildren();
				rightView && rightContainer._add(rightView);
			}

			navBarContainer.backgroundColor = activeWin.barColor;
			navBarContainer.backgroundImage = activeWin.barImage;
			navBarContainer.opacity = activeWin.translucent ? 0.5 : 1;
			navBarContainer.height = activeWin.navBarHidden && activeWin.modal ? 0 : 50;

			if (activeWin.titleControl) {
				centerView = activeWin.titleControl;
			} else if (activeWin.titleImage) {
				centerView = activeWin._titleImageView || (activeWin._titleImageView = Ti.UI.createImageView({
					image: activeWin.titleImage
				}));
			} else {
				centerView = activeWin._titleControl || (activeWin._titleControl = Ti.UI.createLabel({
					text: activeWin._getTitle() || (this._tab && this._tab._getTitle()) || "",
					width: "100%",
					height: "100%",
					textAlign: UI.TEXT_ALIGNMENT_CENTER
				}));
			}
			if (centerContainer._children[0] !== centerView) {
				centerContainer._removeAllChildren();
				centerView && centerContainer._add(centerView);
			}
		},

		_getTopWindow: function() {
			var windows = this._windows,
				len = windows.length;
			return len ? windows[windows.length - 1] : null;
		},

		open: function(win) {
			if (!win._opened) {
				var backButton = this._backButton,
					windows = this._windows,
					tab = this._tab;

				win._navGroup = this;

				// Set a default background
				!isDef(win.backgroundColor) && !isDef(win.backgroundImage) && (win.backgroundColor = "#fff");

				~(windows.length - 1) && windows[windows.length - 1].fireEvent("blur");

				// Show the window
				tab && (win.tabGroup = (win.tab = tab)._tabGroup);
				windows.push(win);
				this._contentContainer._add(win);
				this._updateNavBar();

				win._opened || win.fireEvent("open");
				win._opened = 1;
				win.fireEvent("focus");
			}
		},

		close: function(win) {
			var windows = this._windows,
				windowIdx = windows.indexOf(win),
				self = this,
				backButton = self._backButton;

			win._navGroup = void 0;

			// make sure the window exists and it's not the root
			if (windowIdx > 0) {
				windows.splice(windowIdx, 1);
				win.fireEvent("blur");
				self._contentContainer.remove(win);
				win.fireEvent("close");
				win._opened = 0;

				this._updateNavBar();
				windows[windows.length - 1].fireEvent("focus");
			}
		},

		_reset: function() {
			var windows = this._windows,
				win,
				i = windows.length - 1,
				l = i;

			this._backButton.animate({opacity: 0, duration: 250}, function() {
				this.opacity = 0;
				this.enabled = false;
			});

			while (1) {
				win = windows[i];
				if (!i) {
					break;
				}
				i-- === l && win.fireEvent("blur");
				this._contentContainer.remove(win);
				win.fireEvent("close");
				win._opened = 0;
			}

			windows.splice(1);
			this._updateNavBar();
			win.fireEvent("focus");
		},

		constants: {
			window: void 0
		},

		properties: {
			navBarAtTop: {
				set: function (value, oldValue) {
					if (value !== oldValue) {
						var navBarContainer = this._navBarContainer,
							navBarContainerDomNode = navBarContainer.domNode;

						this._remove(navBarContainer);
						this._insertAt(navBarContainer, value ? 0 : 1);

						css.remove(navBarContainerDomNode, navGroupCss + (value ? "Top" : "Bottom"));
						css.add(navBarContainerDomNode, navGroupCss + (value ? "Bottom" : "Top"));
					}

					return value;
				}
			}
		}

	});

});<commit_msg>[TIMOB-10380] Added check to make sure there is an active window on update<commit_after>/*global define*/
define(['Ti/_/css', 'Ti/_/declare', 'Ti/UI/View', 'Ti/UI', 'Ti/_/lang'],
	function(css, declare, View, UI, lang) {

	var isDef = lang.isDef,
		UI_FILL = UI.FILL,
		navGroupCss = 'TiUINavigationGroup';

	return declare('Ti.UI.MobileWeb.NavigationGroup', View, {

		constructor: function(args) {
			var self = this,
				win = self.constants.window = args && args.window,
				navBarContainer = self._navBarContainer = UI.createView({
					height: 50,
					width: UI.FILL,
					layout: UI._LAYOUT_CONSTRAINING_HORIZONTAL
				});
			css.add(navBarContainer.domNode, navGroupCss);
			self.layout = UI._LAYOUT_CONSTRAINING_VERTICAL;

			// Create the nav bar content
			navBarContainer.add(self._leftContainer = UI.createView({
				width: UI.SIZE,
				height: '100%',
				left: 5,
				right: 5
			}));
			navBarContainer.add(self._centerContainer = UI.createView({
				width: UI.FILL,
				height: '100%'
			}));
			navBarContainer.add(self._rightContainer = UI.createView({
				width: UI.SIZE,
				height: '100%',
				left: 5,
				right: 5
			}));
			self._add(navBarContainer);

			// Create the content container
			self._add(self._contentContainer = UI.createView({
				width: UI_FILL,
				height: UI_FILL
			}));

			// Stylize the top
			this.navBarAtTop = true;
			navBarContainer._getBorderFromCSS();

			// Initialize the window stack and add the root window
			self._windows = [];
			win && self.open(win);
		},

		_defaultWidth: UI_FILL,

		_defaultHeight: UI_FILL,

		_updateNavBar: function() {
			var _self = this,
				windows = _self._windows,
				len = windows.length,
				activeWin = windows[len - 1],
				navBarContainer = this._navBarContainer,
				leftContainer = _self._leftContainer,
				centerContainer = _self._centerContainer,
				rightContainer = _self._rightContainer,
				leftView,
				centerView,
				rightView;

			if (!activeWin) {
				return;
			}
			rightView = activeWin.rightNavButton;

			if (activeWin.leftNavButton) {
				leftView = activeWin.leftNavButton;
			} else {
				if (!_self._backButton) {
					_self._backButton = UI.createButton({
						title: 'Back'
					});
					require.on(_self._backButton, 'singletap', function() {
						// Note: we can reuse activeWin or length because they may have changed by the time this event
						// listener is called due to reuse of the back button across windows.
						_self.close(windows[windows.length - 1]);
					});
				}
				len > 1 && (leftView = _self._backButton);
			}
			if (leftContainer._children[0] !== leftView) {
				leftContainer._removeAllChildren();
				leftView && leftContainer._add(leftView);
			}

			if (rightContainer._children[0] !== rightView) {
				rightContainer._removeAllChildren();
				rightView && rightContainer._add(rightView);
			}

			navBarContainer.backgroundColor = activeWin.barColor;
			navBarContainer.backgroundImage = activeWin.barImage;
			navBarContainer.opacity = activeWin.translucent ? 0.5 : 1;
			navBarContainer.height = activeWin.navBarHidden && activeWin.modal ? 0 : 50;

			if (activeWin.titleControl) {
				centerView = activeWin.titleControl;
			} else if (activeWin.titleImage) {
				centerView = activeWin._titleImageView || (activeWin._titleImageView = UI.createImageView({
					image: activeWin.titleImage
				}));
			} else {
				centerView = activeWin._titleControl || (activeWin._titleControl = UI.createLabel({
					text: activeWin._getTitle() || (this._tab && this._tab._getTitle()) || '',
					width: '100%',
					height: '100%',
					textAlign: UI.TEXT_ALIGNMENT_CENTER
				}));
			}
			if (centerContainer._children[0] !== centerView) {
				centerContainer._removeAllChildren();
				centerView && centerContainer._add(centerView);
			}
		},

		_getTopWindow: function() {
			var windows = this._windows,
				len = windows.length;
			return len ? windows[windows.length - 1] : null;
		},

		open: function(win) {
			if (!win._opened) {
				var windows = this._windows,
					tab = this._tab;

				win._navGroup = this;

				// Set a default background
				!isDef(win.backgroundColor) && !isDef(win.backgroundImage) && (win.backgroundColor = '#fff');

				~(windows.length - 1) && windows[windows.length - 1].fireEvent('blur');

				// Show the window
				tab && (win.tabGroup = (win.tab = tab)._tabGroup);
				windows.push(win);
				this._contentContainer._add(win);
				this._updateNavBar();

				win._opened || win.fireEvent('open');
				win._opened = 1;
				win.fireEvent('focus');
			}
		},

		close: function(win) {
			var windows = this._windows,
				windowIdx = windows.indexOf(win),
				self = this;

			win._navGroup = void 0;

			// make sure the window exists and it's not the root
			if (windowIdx > 0) {
				windows.splice(windowIdx, 1);
				win.fireEvent('blur');
				self._contentContainer.remove(win);
				win.fireEvent('close');
				win._opened = 0;

				this._updateNavBar();
				windows[windows.length - 1].fireEvent('focus');
			}
		},

		_reset: function() {
			var windows = this._windows,
				win,
				i = windows.length - 1,
				l = i;

			this._backButton.animate({opacity: 0, duration: 250}, function() {
				this.opacity = 0;
				this.enabled = false;
			});

			while (1) {
				win = windows[i];
				if (!i) {
					break;
				}
				i-- === l && win.fireEvent('blur');
				this._contentContainer.remove(win);
				win.fireEvent('close');
				win._opened = 0;
			}

			windows.splice(1);
			this._updateNavBar();
			win.fireEvent('focus');
		},

		constants: {
			window: void 0
		},

		properties: {
			navBarAtTop: {
				set: function (value, oldValue) {
					if (value !== oldValue) {
						var navBarContainer = this._navBarContainer,
							navBarContainerDomNode = navBarContainer.domNode;

						this._remove(navBarContainer);
						this._insertAt(navBarContainer, value ? 0 : 1);

						css.remove(navBarContainerDomNode, navGroupCss + (value ? 'Top' : 'Bottom'));
						css.add(navBarContainerDomNode, navGroupCss + (value ? 'Bottom' : 'Top'));
					}

					return value;
				}
			}
		}

	});

});<|endoftext|>


<commit_before>/**
 * COMMON WEBPACK CONFIGURATION
 */

const path = require('path');
const webpack = require('webpack');

module.exports = (options) => ({
  entry: options.entry,
  output: Object.assign({ // Compile into js/build.js
    path: path.resolve(process.cwd(), 'build'),
    publicPath: '/',
  }, options.output), // Merge with env dependent settings
  module: {
    loaders: [{
      test: /\.js$/, // Transform all .js files required somewhere with Babel
      loader: 'babel',
      exclude: /node_modules/,
      query: options.babelQuery,
    }, {
      // Do not transform vendor's CSS with CSS-modules
      // The point is that they remain in global scope.
      // Since we require these CSS files in our JS or CSS files,
      // they will be a part of our compilation either way.
      // So, no need for ExtractTextPlugin here.
      test: /\.css$/,
      include: /node_modules/,
      loaders: ['style-loader', 'css-loader'],
    }, {
      test: /\.(eot|svg|ttf|woff|woff2)$/,
      loader: 'file-loader',
    }, {
      test: /\.(jpg|png|gif)$/,
      loaders: [
        'file-loader',
        'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}',
      ],
    }, {
      test: /\.html$/,
      loader: 'html-loader',
    }, {
      test: /\.json$/,
      loader: 'json-loader',
    }, {
      test: /\.(mp4|webm)$/,
      loader: 'url-loader?limit=10000',
    }],
  },
  plugins: options.plugins.concat([
    new webpack.ProvidePlugin({
      // make fetch available
      fetch: 'exports?self.fetch!whatwg-fetch',
    }),

    // Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV`
    // inside your code for any environment checks; UglifyJS will automatically
    // drop any unreachable code.
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV),
      },
    }),
    new webpack.NamedModulesPlugin(),
  ]),
  resolve: {
    modules: ['app', 'node_modules'],
    extensions: [
      '.js',
      '.jsx',
      '.react.js',
    ],
    mainFields: [
      'browser',
      'jsnext:main',
      'main',
    ],
  },
  devtool: options.devtool,
  target: 'web', // Make web variables accessible to webpack, e.g. window
});
<commit_msg>feat(webpack): new query object syntax (#1198)<commit_after>/**
 * COMMON WEBPACK CONFIGURATION
 */

const path = require('path');
const webpack = require('webpack');

module.exports = (options) => ({
  entry: options.entry,
  output: Object.assign({ // Compile into js/build.js
    path: path.resolve(process.cwd(), 'build'),
    publicPath: '/',
  }, options.output), // Merge with env dependent settings
  module: {
    loaders: [{
      test: /\.js$/, // Transform all .js files required somewhere with Babel
      loader: 'babel',
      exclude: /node_modules/,
      query: options.babelQuery,
    }, {
      // Do not transform vendor's CSS with CSS-modules
      // The point is that they remain in global scope.
      // Since we require these CSS files in our JS or CSS files,
      // they will be a part of our compilation either way.
      // So, no need for ExtractTextPlugin here.
      test: /\.css$/,
      include: /node_modules/,
      loaders: ['style-loader', 'css-loader'],
    }, {
      test: /\.(eot|svg|ttf|woff|woff2)$/,
      loader: 'file-loader',
    }, {
      test: /\.(jpg|png|gif)$/,
      loaders: [
        'file-loader',
        {
          loader: 'image-webpack',
          query: {
            progressive: true,
            optimizationLevel: 7,
            interlaced: false,
            pngquant: {
              quality: '65-90',
              speed: 4,
            },
          },
        },
      ],
    }, {
      test: /\.html$/,
      loader: 'html-loader',
    }, {
      test: /\.json$/,
      loader: 'json-loader',
    }, {
      test: /\.(mp4|webm)$/,
      loader: 'url-loader',
      query: {
        limit: 10000,
      },
    }],
  },
  plugins: options.plugins.concat([
    new webpack.ProvidePlugin({
      // make fetch available
      fetch: 'exports?self.fetch!whatwg-fetch',
    }),

    // Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV`
    // inside your code for any environment checks; UglifyJS will automatically
    // drop any unreachable code.
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV),
      },
    }),
    new webpack.NamedModulesPlugin(),
  ]),
  resolve: {
    modules: ['app', 'node_modules'],
    extensions: [
      '.js',
      '.jsx',
      '.react.js',
    ],
    mainFields: [
      'browser',
      'jsnext:main',
      'main',
    ],
  },
  devtool: options.devtool,
  target: 'web', // Make web variables accessible to webpack, e.g. window
});
<|endoftext|>


<commit_before>/**
 * @module Rendering
 * @submodule Rendering
 * @for p5
 */

'use strict';

var p5 = require('./main');
var constants = require('../core/constants');

/**
 * Main graphics and rendering context, as well as the base API
 * implementation for p5.js "core". To be used as the superclass for
 * Renderer2D and Renderer3D classes, respecitvely.
 *
 * @class p5.Renderer
 * @constructor
 * @extends p5.Element
 * @param {String} elt DOM node that is wrapped
 * @param {p5} [pInst] pointer to p5 instance
 * @param {Boolean} [isMainCanvas] whether we're using it as main canvas
 */
p5.Renderer = function(elt, pInst, isMainCanvas) {
  p5.Element.call(this, elt, pInst);
  this.canvas = elt;
  this._pInst = pInst;
  if (isMainCanvas) {
    this._isMainCanvas = true;
    // for pixel method sharing with pimage
    this._pInst._setProperty('_curElement', this);
    this._pInst._setProperty('canvas', this.canvas);
    this._pInst._setProperty('width', this.width);
    this._pInst._setProperty('height', this.height);
  } else {
    // hide if offscreen buffer by default
    this.canvas.style.display = 'none';
    this._styles = []; // non-main elt styles stored in p5.Renderer
  }

  this._textSize = 12;
  this._textLeading = 15;
  this._textFont = 'sans-serif';
  this._textStyle = constants.NORMAL;
  this._textAscent = null;
  this._textDescent = null;

  this._rectMode = constants.CORNER;
  this._ellipseMode = constants.CENTER;
  this._curveTightness = 0;
  this._imageMode = constants.CORNER;

  this._tint = null;
  this._doStroke = true;
  this._doFill = true;
  this._strokeSet = false;
  this._fillSet = false;
};

p5.Renderer.prototype = Object.create(p5.Element.prototype);

// the renderer should return a 'style' object that it wishes to
// store on the push stack.
p5.Renderer.prototype.push = function() {
  return {
    properties: {
      _doStroke: this._doStroke,
      _strokeSet: this._strokeSet,
      _doFill: this._doFill,
      _fillSet: this._fillSet,
      _tint: this._tint,
      _imageMode: this._imageMode,
      _rectMode: this._rectMode,
      _ellipseMode: this._ellipseMode,
      _textFont: this._textFont,
      _textLeading: this._textLeading,
      _textSize: this._textSize,
      _textStyle: this._textStyle
    }
  };
};

// a pop() operation is in progress
// the renderer is passed the 'style' object that it returned
// from its push() method.
p5.Renderer.prototype.pop = function(style) {
  if (style.properties) {
    // copy the style properties back into the renderer
    Object.assign(this, style.properties);
  }
};

/**
 * Resize our canvas element.
 */
p5.Renderer.prototype.resize = function(w, h) {
  this.width = w;
  this.height = h;
  this.elt.width = w * this._pInst._pixelDensity;
  this.elt.height = h * this._pInst._pixelDensity;
  this.elt.style.width = w + 'px';
  this.elt.style.height = h + 'px';
  if (this._isMainCanvas) {
    this._pInst._setProperty('width', this.width);
    this._pInst._setProperty('height', this.height);
  }
};

p5.Renderer.prototype.textLeading = function(l) {
  if (typeof l === 'number') {
    this._setProperty('_textLeading', l);
    return this._pInst;
  }

  return this._textLeading;
};

p5.Renderer.prototype.textSize = function(s) {
  if (typeof s === 'number') {
    this._setProperty('_textSize', s);
    this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT);
    return this._applyTextProperties();
  }

  return this._textSize;
};

p5.Renderer.prototype.textStyle = function(s) {
  if (s) {
    if (
      s === constants.NORMAL ||
      s === constants.ITALIC ||
      s === constants.BOLD
    ) {
      this._setProperty('_textStyle', s);
    }

    return this._applyTextProperties();
  }

  return this._textStyle;
};

p5.Renderer.prototype.textAscent = function() {
  if (this._textAscent === null) {
    this._updateTextMetrics();
  }
  return this._textAscent;
};

p5.Renderer.prototype.textDescent = function() {
  if (this._textDescent === null) {
    this._updateTextMetrics();
  }
  return this._textDescent;
};

p5.Renderer.prototype._applyDefaults = function() {
  return this;
};

/**
 * Helper fxn to check font type (system or otf)
 */
p5.Renderer.prototype._isOpenType = function(f) {
  f = f || this._textFont;
  return typeof f === 'object' && f.font && f.font.supported;
};

p5.Renderer.prototype._updateTextMetrics = function() {
  if (this._isOpenType()) {
    this._setProperty('_textAscent', this._textFont._textAscent());
    this._setProperty('_textDescent', this._textFont._textDescent());
    return this;
  }

  // Adapted from http://stackoverflow.com/a/25355178
  var text = document.createElement('span');
  text.style.fontFamily = this._textFont;
  text.style.fontSize = this._textSize + 'px';
  text.innerHTML = 'ABCjgq|';

  var block = document.createElement('div');
  block.style.display = 'inline-block';
  block.style.width = '1px';
  block.style.height = '0px';

  var container = document.createElement('div');
  container.appendChild(text);
  container.appendChild(block);

  container.style.height = '0px';
  container.style.overflow = 'hidden';
  document.body.appendChild(container);

  block.style.verticalAlign = 'baseline';
  var blockOffset = calculateOffset(block);
  var textOffset = calculateOffset(text);
  var ascent = blockOffset[1] - textOffset[1];

  block.style.verticalAlign = 'bottom';
  blockOffset = calculateOffset(block);
  textOffset = calculateOffset(text);
  var height = blockOffset[1] - textOffset[1];
  var descent = height - ascent;

  document.body.removeChild(container);

  this._setProperty('_textAscent', ascent);
  this._setProperty('_textDescent', descent);

  return this;
};

/**
 * Helper fxn to measure ascent and descent.
 * Adapted from http://stackoverflow.com/a/25355178
 */
function calculateOffset(object) {
  var currentLeft = 0,
    currentTop = 0;
  if (object.offsetParent) {
    do {
      currentLeft += object.offsetLeft;
      currentTop += object.offsetTop;
    } while ((object = object.offsetParent));
  } else {
    currentLeft += object.offsetLeft;
    currentTop += object.offsetTop;
  }
  return [currentLeft, currentTop];
}

module.exports = p5.Renderer;
<commit_msg>remove unnecessary line<commit_after>/**
 * @module Rendering
 * @submodule Rendering
 * @for p5
 */

'use strict';

var p5 = require('./main');
var constants = require('../core/constants');

/**
 * Main graphics and rendering context, as well as the base API
 * implementation for p5.js "core". To be used as the superclass for
 * Renderer2D and Renderer3D classes, respecitvely.
 *
 * @class p5.Renderer
 * @constructor
 * @extends p5.Element
 * @param {String} elt DOM node that is wrapped
 * @param {p5} [pInst] pointer to p5 instance
 * @param {Boolean} [isMainCanvas] whether we're using it as main canvas
 */
p5.Renderer = function(elt, pInst, isMainCanvas) {
  p5.Element.call(this, elt, pInst);
  this.canvas = elt;
  if (isMainCanvas) {
    this._isMainCanvas = true;
    // for pixel method sharing with pimage
    this._pInst._setProperty('_curElement', this);
    this._pInst._setProperty('canvas', this.canvas);
    this._pInst._setProperty('width', this.width);
    this._pInst._setProperty('height', this.height);
  } else {
    // hide if offscreen buffer by default
    this.canvas.style.display = 'none';
    this._styles = []; // non-main elt styles stored in p5.Renderer
  }

  this._textSize = 12;
  this._textLeading = 15;
  this._textFont = 'sans-serif';
  this._textStyle = constants.NORMAL;
  this._textAscent = null;
  this._textDescent = null;

  this._rectMode = constants.CORNER;
  this._ellipseMode = constants.CENTER;
  this._curveTightness = 0;
  this._imageMode = constants.CORNER;

  this._tint = null;
  this._doStroke = true;
  this._doFill = true;
  this._strokeSet = false;
  this._fillSet = false;
};

p5.Renderer.prototype = Object.create(p5.Element.prototype);

// the renderer should return a 'style' object that it wishes to
// store on the push stack.
p5.Renderer.prototype.push = function() {
  return {
    properties: {
      _doStroke: this._doStroke,
      _strokeSet: this._strokeSet,
      _doFill: this._doFill,
      _fillSet: this._fillSet,
      _tint: this._tint,
      _imageMode: this._imageMode,
      _rectMode: this._rectMode,
      _ellipseMode: this._ellipseMode,
      _textFont: this._textFont,
      _textLeading: this._textLeading,
      _textSize: this._textSize,
      _textStyle: this._textStyle
    }
  };
};

// a pop() operation is in progress
// the renderer is passed the 'style' object that it returned
// from its push() method.
p5.Renderer.prototype.pop = function(style) {
  if (style.properties) {
    // copy the style properties back into the renderer
    Object.assign(this, style.properties);
  }
};

/**
 * Resize our canvas element.
 */
p5.Renderer.prototype.resize = function(w, h) {
  this.width = w;
  this.height = h;
  this.elt.width = w * this._pInst._pixelDensity;
  this.elt.height = h * this._pInst._pixelDensity;
  this.elt.style.width = w + 'px';
  this.elt.style.height = h + 'px';
  if (this._isMainCanvas) {
    this._pInst._setProperty('width', this.width);
    this._pInst._setProperty('height', this.height);
  }
};

p5.Renderer.prototype.textLeading = function(l) {
  if (typeof l === 'number') {
    this._setProperty('_textLeading', l);
    return this._pInst;
  }

  return this._textLeading;
};

p5.Renderer.prototype.textSize = function(s) {
  if (typeof s === 'number') {
    this._setProperty('_textSize', s);
    this._setProperty('_textLeading', s * constants._DEFAULT_LEADMULT);
    return this._applyTextProperties();
  }

  return this._textSize;
};

p5.Renderer.prototype.textStyle = function(s) {
  if (s) {
    if (
      s === constants.NORMAL ||
      s === constants.ITALIC ||
      s === constants.BOLD
    ) {
      this._setProperty('_textStyle', s);
    }

    return this._applyTextProperties();
  }

  return this._textStyle;
};

p5.Renderer.prototype.textAscent = function() {
  if (this._textAscent === null) {
    this._updateTextMetrics();
  }
  return this._textAscent;
};

p5.Renderer.prototype.textDescent = function() {
  if (this._textDescent === null) {
    this._updateTextMetrics();
  }
  return this._textDescent;
};

p5.Renderer.prototype._applyDefaults = function() {
  return this;
};

/**
 * Helper fxn to check font type (system or otf)
 */
p5.Renderer.prototype._isOpenType = function(f) {
  f = f || this._textFont;
  return typeof f === 'object' && f.font && f.font.supported;
};

p5.Renderer.prototype._updateTextMetrics = function() {
  if (this._isOpenType()) {
    this._setProperty('_textAscent', this._textFont._textAscent());
    this._setProperty('_textDescent', this._textFont._textDescent());
    return this;
  }

  // Adapted from http://stackoverflow.com/a/25355178
  var text = document.createElement('span');
  text.style.fontFamily = this._textFont;
  text.style.fontSize = this._textSize + 'px';
  text.innerHTML = 'ABCjgq|';

  var block = document.createElement('div');
  block.style.display = 'inline-block';
  block.style.width = '1px';
  block.style.height = '0px';

  var container = document.createElement('div');
  container.appendChild(text);
  container.appendChild(block);

  container.style.height = '0px';
  container.style.overflow = 'hidden';
  document.body.appendChild(container);

  block.style.verticalAlign = 'baseline';
  var blockOffset = calculateOffset(block);
  var textOffset = calculateOffset(text);
  var ascent = blockOffset[1] - textOffset[1];

  block.style.verticalAlign = 'bottom';
  blockOffset = calculateOffset(block);
  textOffset = calculateOffset(text);
  var height = blockOffset[1] - textOffset[1];
  var descent = height - ascent;

  document.body.removeChild(container);

  this._setProperty('_textAscent', ascent);
  this._setProperty('_textDescent', descent);

  return this;
};

/**
 * Helper fxn to measure ascent and descent.
 * Adapted from http://stackoverflow.com/a/25355178
 */
function calculateOffset(object) {
  var currentLeft = 0,
    currentTop = 0;
  if (object.offsetParent) {
    do {
      currentLeft += object.offsetLeft;
      currentTop += object.offsetTop;
    } while ((object = object.offsetParent));
  } else {
    currentLeft += object.offsetLeft;
    currentTop += object.offsetTop;
  }
  return [currentLeft, currentTop];
}

module.exports = p5.Renderer;
<|endoftext|>


<commit_before>var util = require('util');
var slug = require('slug');
var uuid = require('uuid');
var request = require('request');

var async = require('async');

var config = require('../../config.json');
var talks = require('libtlks').talk;

/**
 * Route /search
 * @param req   HTTP Request object
 * @param req   HTTP Response object
 */
exports.search = function(req, res) {
    "use strict";

    var q = req.query.q;
    var user = req.session.user;
    var context = {
        title: "Tech talks by '" + q + "'" + " | tlks.io",
        description: "Tech talks by '" + q + "'" + " | tlks.io",
        user: user,
        q: q,
        talks: []
    };
    var url = config.elasticsearch + '/tlksio/talk/_search?q=' + q;
    request.get({
        url: url,
        method: 'GET',
        json: true
    }, function(error, response, body) {
        if (error) {
            context.message = util.inspect(err);
            res.status(500).render("500", context);
        }
        var hits = body.hits.hits;
        async.map(hits, function(el, callback) {
            var obj = el._source;
            obj.tags = obj.tags.split(',').map(function(el) {
                return el.trim();
            });
            talks.getBySlug(config.mongodb, obj.slug, function(err, talks) {
                if (err) {
                    context.message = util.inspect(err);
                    res.status(500).render("500", context);
                }
                callback(null, talks[0]);
            });
        }, function(err, results) {
            if (err) {
                context.message = util.inspect(err);
                res.status(500).render("500", context);
            }
            context.talks = results;
            res.render("search", context);
        });
    });
};

/**
 * Route /talk/play/:id
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.play = function(req, res) {
    "use strict";

    var slug = req.params.slug;
    talks.play(config.mongodb, slug, function(err, talk) {
        if (err) {
            var context = {
                message: util.inspect(err)
            };
            res.status(500).render("500", context);
        }
        var url = 'https://www.youtube.com/watch?v=' + talk.code;
        res.redirect(url);
    });
};

/**
 * Route /talk/upvote/:id
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.upvote = function(req, res) {
    "user strict";
    var id = req.params.id;
    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        var userid = user.id;
        talks.upvote(config.mongodb, id, userid, function(err, updated) {
            if (err) {
                var context = {
                    message: util.inspect(err)
                };
                res.status(500).render("500", context);
            }
            var result = {
                "result": updated ? true : false
            };
            res.send(result);
        });
    }
};

/**
 * Route /talk/favorite/:id
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.favorite = function(req, res) {
    "user strict";
    var id = req.params.id;
    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        var userid = user.id;
        talks.favorite(config.mongodb, id, userid, function(err, updated) {
            if (err) {
                var context = {
                    message: util.inspect(err)
                };
                res.status(500).render("500", context);
            }
            var result = {
                "result": updated ? true : false
            };
            res.send(result);
        });
    }
};

/**
 * Route /talk/unfavorite/:id
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.unfavorite = function(req, res) {
    "user strict";
    var id = req.params.id;
    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        var userid = user.id;
        talks.unfavorite(config.mongodb, id, userid, function(err, updated) {
            if (err) {
                var context = {
                    message: util.inspect(err)
                };
                res.status(500).render("500", context);
            }
            var result = {
                "result": updated ? true : false
            };
            res.send(result);
        });
    }
};

/**
 * Route /talk/:slug
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.talk = function(req, res) {
    "use strict";

    var slug = req.params.slug;
    var user = req.session.user;
    var context = {
        user: user
    };
    talks.getBySlug(config.mongodb, slug, function(err, docs) {
        var talk = docs[0];
        if (err) {
            context.message = util.inspect(err);
            res.status(500).render("500", context);
        }
        if (talk) {
            context.talk = talk;
            context.title =  talk.title + " | tlks.io";
            context.description = talk.description.substring(0,200);
            talks.related(config.mongodb, talk.id, talk.tags, 5, function(err, docs) {
                if (err) {
                    context.message = util.inspect(err);
                    res.status(500).render("500", context);
                }
                context.related = docs;
                res.render("talk", context);
            });
        } else {
            res.status(404).render("404", context);
        }
    });
};

/**
 * Route /add
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.add = function(req, res) {
    "use strict";

    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        var context = {
            title: "tlks.io : Add a new talk",
            user: user
        };
        res.render('add', context);
    }
};

/**
 * Route /save
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.save = function(req, res) {
    "use strict";

    // user
    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        // talk
        var talk = {
            id: uuid.v1(),
            code: req.body.code,
            title: req.body.title,
            slug: slug(req.body.title).toLowerCase(),
            description: req.body.description,
            author: {
                id: user.id,
                username: user.username,
                avatar: user.avatar
            },
            "viewCount": 0,
            "voteCount": 0,
            "votes": [],
            "favoriteCount": 0,
            "favorites": [],
            "tags": req.body.tags.split(',').map(function(el) {
                return el.trim().toLowerCase();
            }),
            "created": Date.now(),
            "updated": Date.now()
        };
        // create talk
        talks.createTalk(config.mongodb, talk, function(err, talk) {
            if (err) {
                var context = {
                    message: util.inspect(err)
                };
                res.status(500).render("500", context);
            }
            // render
            res.redirect('/');
        });
    }
};

/**
 * Route /popular
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.popular = function(req, res) {
    "use strict";

    var limit = 30;
    var user = req.session.user;
    var context = {
        title: 'tlks.io : Popular talks',
        user: user
    };
    talks.popular(config.mongodb, limit, function(err, talks) {
        if (err) {
            context.message = util.inspect(err);
            res.status(500).render("500", context);
        }
        context.latest = talks;
        res.render('popular', context);
    });

};

/**
 * Route /latest
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.latest = function(req, res) {
    "use strict";

    var limit = 30;
    var user = req.session.user;
    var context = {
        title: 'tlks.io : Latest talks',
        user: user
    };
    talks.latest(config.mongodb, limit, function(err, talks) {
        if (err) {
            context.message = util.inspect(err);
            res.status(500).render("500", context);
        }
        context.latest = talks;
        res.render('latest', context);
    });

};
<commit_msg>Fixed some use-strict declarations<commit_after>var util = require('util');
var slug = require('slug');
var uuid = require('uuid');
var request = require('request');

var async = require('async');

var config = require('../../config.json');
var talks = require('libtlks').talk;

/**
 * Route /search
 * @param req   HTTP Request object
 * @param req   HTTP Response object
 */
exports.search = function(req, res) {
    "use strict";

    var q = req.query.q;
    var user = req.session.user;
    var context = {
        title: "Tech talks by '" + q + "'" + " | tlks.io",
        description: "Tech talks by '" + q + "'" + " | tlks.io",
        user: user,
        q: q,
        talks: []
    };
    var url = config.elasticsearch + '/tlksio/talk/_search?q=' + q;
    request.get({
        url: url,
        method: 'GET',
        json: true
    }, function(error, response, body) {
        if (error) {
            context.message = util.inspect(err);
            res.status(500).render("500", context);
        }
        var hits = body.hits.hits;
        async.map(hits, function(el, callback) {
            var obj = el._source;
            obj.tags = obj.tags.split(',').map(function(el) {
                return el.trim();
            });
            talks.getBySlug(config.mongodb, obj.slug, function(err, talks) {
                if (err) {
                    context.message = util.inspect(err);
                    res.status(500).render("500", context);
                }
                callback(null, talks[0]);
            });
        }, function(err, results) {
            if (err) {
                context.message = util.inspect(err);
                res.status(500).render("500", context);
            }
            context.talks = results;
            res.render("search", context);
        });
    });
};

/**
 * Route /talk/play/:id
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.play = function(req, res) {
    "use strict";

    var slug = req.params.slug;
    talks.play(config.mongodb, slug, function(err, talk) {
        if (err) {
            var context = {
                message: util.inspect(err)
            };
            res.status(500).render("500", context);
        }
        var url = 'https://www.youtube.com/watch?v=' + talk.code;
        res.redirect(url);
    });
};

/**
 * Route /talk/upvote/:id
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.upvote = function(req, res) {
    "use strict";
    var id = req.params.id;
    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        var userid = user.id;
        talks.upvote(config.mongodb, id, userid, function(err, updated) {
            if (err) {
                var context = {
                    message: util.inspect(err)
                };
                res.status(500).render("500", context);
            }
            var result = {
                "result": updated ? true : false
            };
            res.send(result);
        });
    }
};

/**
 * Route /talk/favorite/:id
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.favorite = function(req, res) {
    "use strict";
    var id = req.params.id;
    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        var userid = user.id;
        talks.favorite(config.mongodb, id, userid, function(err, updated) {
            if (err) {
                var context = {
                    message: util.inspect(err)
                };
                res.status(500).render("500", context);
            }
            var result = {
                "result": updated ? true : false
            };
            res.send(result);
        });
    }
};

/**
 * Route /talk/unfavorite/:id
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.unfavorite = function(req, res) {
    "use strict";
    var id = req.params.id;
    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        var userid = user.id;
        talks.unfavorite(config.mongodb, id, userid, function(err, updated) {
            if (err) {
                var context = {
                    message: util.inspect(err)
                };
                res.status(500).render("500", context);
            }
            var result = {
                "result": updated ? true : false
            };
            res.send(result);
        });
    }
};

/**
 * Route /talk/:slug
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.talk = function(req, res) {
    "use strict";

    var slug = req.params.slug;
    var user = req.session.user;
    var context = {
        user: user
    };
    talks.getBySlug(config.mongodb, slug, function(err, docs) {
        var talk = docs[0];
        if (err) {
            context.message = util.inspect(err);
            res.status(500).render("500", context);
        }
        if (talk) {
            context.talk = talk;
            context.title =  talk.title + " | tlks.io";
            context.description = talk.description.substring(0,200);
            talks.related(config.mongodb, talk.id, talk.tags, 5, function(err, docs) {
                if (err) {
                    context.message = util.inspect(err);
                    res.status(500).render("500", context);
                }
                context.related = docs;
                res.render("talk", context);
            });
        } else {
            res.status(404).render("404", context);
        }
    });
};

/**
 * Route /add
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.add = function(req, res) {
    "use strict";

    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        var context = {
            title: "tlks.io : Add a new talk",
            user: user
        };
        res.render('add', context);
    }
};

/**
 * Route /save
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.save = function(req, res) {
    "use strict";

    // user
    var user = req.session.user;
    if (user === undefined) {
        res.status(401).send("401").end();
    } else {
        // talk
        var talk = {
            id: uuid.v1(),
            code: req.body.code,
            title: req.body.title,
            slug: slug(req.body.title).toLowerCase(),
            description: req.body.description,
            author: {
                id: user.id,
                username: user.username,
                avatar: user.avatar
            },
            "viewCount": 0,
            "voteCount": 0,
            "votes": [],
            "favoriteCount": 0,
            "favorites": [],
            "tags": req.body.tags.split(',').map(function(el) {
                return el.trim().toLowerCase();
            }),
            "created": Date.now(),
            "updated": Date.now()
        };
        // create talk
        talks.createTalk(config.mongodb, talk, function(err, talk) {
            if (err) {
                var context = {
                    message: util.inspect(err)
                };
                res.status(500).render("500", context);
            }
            // render
            res.redirect('/');
        });
    }
};

/**
 * Route /popular
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.popular = function(req, res) {
    "use strict";

    var limit = 30;
    var user = req.session.user;
    var context = {
        title: 'tlks.io : Popular talks',
        user: user
    };
    talks.popular(config.mongodb, limit, function(err, talks) {
        if (err) {
            context.message = util.inspect(err);
            res.status(500).render("500", context);
        }
        context.latest = talks;
        res.render('popular', context);
    });

};

/**
 * Route /latest
 * @param req   HTTP Request object
 * @param res   HTTP Response object
 */
exports.latest = function(req, res) {
    "use strict";

    var limit = 30;
    var user = req.session.user;
    var context = {
        title: 'tlks.io : Latest talks',
        user: user
    };
    talks.latest(config.mongodb, limit, function(err, talks) {
        if (err) {
            context.message = util.inspect(err);
            res.status(500).render("500", context);
        }
        context.latest = talks;
        res.render('latest', context);
    });

};
<|endoftext|>


<commit_before>'use strict';

Figure.DEFAULT_HOST = 'api.figuredevices.com';
Figure.DEFAULT_PROTOCOL = 'https';
Figure.DEFAULT_TIMEOUT = 60000; // 1 min

var resources = {
  Photobooths: require('./resources/Photobooths.js'),
  Places: require('./resources/Places.js'),
  Events: require('./resources/Events.js'),
  TicketTemplates: require('./resources/TicketTemplates.js'),
  Texts: require('./resources/Texts.js'),
  TextVariables: require('./resources/TextVariables.js'),
  Images: require('./resources/Images.js'),
  ImageVariables: require('./resources/ImageVariables.js'),
  Portraits: require('./resources/Portraits.js'),
  PosterOrders: require('./resources/PosterOrders'),
  Users: require('./resources/Users.js'),
  Auth: require('./resources/Auth.js')
};

Figure.resources = resources;

function Figure(token){

  if (!(this instanceof Figure)) {
    return new Figure(token);
  }

  this._api = {
    token: token || null,
    host: Figure.DEFAULT_HOST,
    protocol: Figure.DEFAULT_PROTOCOL,
    basePath: '',
    timeout: Figure.DEFAULT_TIMEOUT
  }

  this._prepResources();

}

Figure.prototype = {

  setToken: function(token) {
    if (token) {
      this._setApiField(
        'token',
        token)
    }
  },

  setBasePath: function(basePath) {
    this._setApiField(
      'basePath',
      basePath);
  },

  setHost: function(host, protocol) {
    this._setApiField('host', host);
    if (protocol) {
      this.setProtocol(protocol);
    }
  },

  setProtocol: function(protocol) {
    this._setApiField('protocol', protocol);
  },

  setTimeout: function(timeout) {
    this._setApiField(
      'timeout',
      timeout == null ? Figure.DEFAULT_TIMEOUT : timeout
    );
  },

  _setApiField: function(key, value) {
    this._api[key] = value;
  },

  getApiField: function(key) {
    return this._api[key];
  },

  _prepResources: function() {
    for (var name in resources) {
      this[
        name[0].toLowerCase() + name.substring(1)
      ] = new resources[name](this);
    }
  },

}

module.exports = Figure;

<commit_msg>configuration of api in constructor<commit_after>'use strict';

Figure.DEFAULT_HOST = 'api.figuredevices.com';
Figure.DEFAULT_PROTOCOL = 'https';
Figure.DEFAULT_TIMEOUT = 60000; // 1 min

var resources = {
  Photobooths: require('./resources/Photobooths.js'),
  Places: require('./resources/Places.js'),
  Events: require('./resources/Events.js'),
  TicketTemplates: require('./resources/TicketTemplates.js'),
  Texts: require('./resources/Texts.js'),
  TextVariables: require('./resources/TextVariables.js'),
  Images: require('./resources/Images.js'),
  ImageVariables: require('./resources/ImageVariables.js'),
  Portraits: require('./resources/Portraits.js'),
  PosterOrders: require('./resources/PosterOrders'),
  Users: require('./resources/Users.js'),
  Auth: require('./resources/Auth.js')
};

Figure.resources = resources;

function Figure(options){

  let opts = typeof options === 'object' ? options : {};

  if (!(this instanceof Figure)) {
    return new Figure(opts);
  }

  this._api = {
    token: opts.token || null,
    host: opts.host || Figure.DEFAULT_HOST,
    protocol: opts.protocol || Figure.DEFAULT_PROTOCOL,
    basePath: opts.basePath || '',
    timeout: opts.timeout || Figure.DEFAULT_TIMEOUT
  }

  this._prepResources();

}

Figure.prototype = {

  setToken: function(token) {
    if (token) {
      this._setApiField(
        'token',
        token)
    }
  },

  setBasePath: function(basePath) {
    this._setApiField(
      'basePath',
      basePath);
  },

  setHost: function(host, protocol) {
    this._setApiField('host', host);
    if (protocol) {
      this.setProtocol(protocol);
    }
  },

  setProtocol: function(protocol) {
    this._setApiField('protocol', protocol);
  },

  setTimeout: function(timeout) {
    this._setApiField(
      'timeout',
      timeout == null ? Figure.DEFAULT_TIMEOUT : timeout
    );
  },

  _setApiField: function(key, value) {
    this._api[key] = value;
  },

  getApiField: function(key) {
    return this._api[key];
  },

  _prepResources: function() {
    for (var name in resources) {
      this[
        name[0].toLowerCase() + name.substring(1)
      ] = new resources[name](this);
    }
  },

}

module.exports = Figure;

<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import { Pagination } from 'react-bootstrap';
import DocumentTitle from 'react-document-title';
import Promise from 'bluebird';
import { AuthorizationApi, SearchApi, EntityDataModelApi } from 'loom-data';
import { Permission } from '../../core/permissions/Permission';
import Page from '../../components/page/Page';
import AdvancedSearchBox from './AdvancedSearchBox';
import EntitySetSearchResults from './EntitySetSearchResults';
import EntitySetUserSearchResults from './EntitySetUserSearchResults';
import AsyncContent, { ASYNC_STATUS } from '../../components/asynccontent/AsyncContent';
import { FIRST_NAMES, LAST_NAMES, DOBS } from '../../utils/Consts/StringConsts';
import styles from './styles.module.css';

const MAX_HITS = 50;

export default class AdvancedDataSearch extends React.Component {
  static contextTypes = {
    router: PropTypes.object
  };

  static propTypes = {
    params: PropTypes.shape({
      entitySetId: PropTypes.string.isRequired
    }).isRequired
  }

  constructor(props) {
    super(props);
    this.state = {
      page: 1,
      searchResults: [],
      totalHits: 0,
      title: '',
      asyncStatus: ASYNC_STATUS.PENDING,
      propertyTypes: [],
      loadError: false,
      hidePagination: false,
      searches: {}
    };
  }

  componentDidMount() {
    this.loadPropertyIds();
  }

  loadPropertyIds = () => {
    EntityDataModelApi.getEntitySet(this.props.params.entitySetId)
    .then((entitySet) => {
      EntityDataModelApi.getEntityType(entitySet.entityTypeId)
      .then((entityType) => {
        this.loadAuthorizedPropertyTypes(entitySet, entityType.properties);
      }).catch(() => {
        this.setState({ loadError: true });
      });
    }).catch(() => {
      this.setState({ loadError: true });
    });
  }

  loadAuthorizedPropertyTypes = (entitySet, propertyIds) => {
    const accessChecks = propertyIds.map((propertyId) => {
      return {
        aclKey: [this.props.params.entitySetId, propertyId],
        permissions: [Permission.READ.name]
      };
    });
    AuthorizationApi.checkAuthorizations(accessChecks)
    .then((response) => {
      const propsWithReadAccess = [];
      response.forEach((property) => {
        if (property.permissions.READ) {
          propsWithReadAccess.push(property.aclKey[1]);
        }
      });
      const propertyTypePromises = propsWithReadAccess.map((propId) => {
        return EntityDataModelApi.getPropertyType(propId);
      });
      Promise.all(propertyTypePromises)
      .then((propertyTypes) => {
        this.setState({
          propertyTypes,
          title: entitySet.title,
          loadError: false
        });
      }).catch(() => {
        this.setState({ loadError: true });
      });
    }).catch(() => {
      this.setState({ loadError: true });
    });
  }

  executeSearch = (searches, page) => {
    if (Object.keys(searches).length >= 1 && Object.values(searches).length >= 1) {
      const searchDetails = Object.values(searches).filter((search) => {
        return search.searchTerm && search.searchTerm.length;
      });
      const searchOptions = {
        searchFields: searchDetails,
        start: ((page - 1) * 50),
        maxHits: MAX_HITS
      };
      SearchApi.advancedSearchEntitySetData(this.props.params.entitySetId, searchOptions)
      .then((response) => {
        this.setState({
          searchResults: response.hits,
          totalHits: response.numHits,
          asyncStatus: ASYNC_STATUS.SUCCESS,
          searches,
          page
        });
      }).catch(() => {
        this.setState({ asyncStatus: ASYNC_STATUS.ERROR });
      });
    }
  }

  renderEntitySetTitle = () => {
    if (this.state.title.length <= 0) return '';
    return (
      : <Link
          to={`/entitysets/${this.props.params.entitySetId}`}
          className={styles.titleLink}>{this.state.title}</Link>
    );
  }

  renderErrorMessage = () => {
    if (this.state.loadError) {
      return
Unable to load entity set info.
;
    }
    return null;
  }

  handlePageSelect = (eventKey) => {
    this.setState({ page: eventKey });
    this.executeSearch(this.state.searches, eventKey);
  }

  hidePagination = (shouldHide) => {
    this.setState({ hidePagination: shouldHide });
  }

  formatValue = (rawValue) => {
    if (rawValue instanceof Array) {
      let formattedValue = '';
      if (rawValue.length > 0) formattedValue = formattedValue.concat(rawValue[0]);
      if (rawValue.length > 1) {
        for (let i = 1; i < rawValue.length; i += 1) {
          formattedValue = formattedValue.concat(', ').concat(rawValue[i]);
        }
      }
      return formattedValue;
    }
    return rawValue;
  }

  onSearchSubmit = (searches) => {
    this.executeSearch(searches, this.state.page);
    this.setState({ searches });
  }

  renderPagination = () => {
    const activePage = parseInt(this.state.page, 10);
    if (this.state.hidePagination || this.state.totalHits <= 0 || isNaN(activePage)) return null;
    const numPages = Math.ceil((1.0 * this.state.totalHits) / MAX_HITS);
    return (

        <Pagination
            prev
            next
            ellipsis
            boundaryLinks
            items={numPages}
            maxButtons={5}
            activePage={activePage}
            onSelect={this.handlePageSelect} />

    );
  }

  renderSearchResultType = () => {
    let firstName;
    let lastName;
    let dob;
    this.state.propertyTypes.forEach((propertyType) => {
      if (FIRST_NAMES.includes(propertyType.type.name.toLowerCase())) firstName = propertyType;
      else if (LAST_NAMES.includes(propertyType.type.name.toLowerCase())) lastName = propertyType;
      else if (DOBS.includes(propertyType.type.name.toLowerCase())) dob = propertyType;
    });
    if (firstName && lastName) {
      return (
        <EntitySetUserSearchResults
            results={this.state.searchResults}
            entitySetId={this.props.params.entitySetId}
            propertyTypes={this.state.propertyTypes}
            firstName={firstName}
            lastName={lastName}
            dob={dob}
            hidePaginationFn={this.hidePagination}
            formatValueFn={this.formatValue} />
      );
    }
    return (
      <EntitySetSearchResults
          results={this.state.searchResults}
          entitySetId={this.props.params.entitySetId}
          propertyTypes={this.state.propertyTypes}
          formatValueFn={this.formatValue} />
    );
  }

  renderSearchBox = () => {
    if (this.state.propertyTypes.length === 0) return null;
    return (
      <AdvancedSearchBox
          onSubmit={this.onSearchSubmit}
          propertyTypes={this.state.propertyTypes} />
    );
  }

  render() {
    const title = (this.state.title && this.state.title.length)
      ? `Advanced Search: ${this.state.title}`
      : 'Advanced Search';
    return (
      <DocumentTitle title={title}>
        <Page>
          <Page.Header>
            <Page.Title>Search entity set{this.renderEntitySetTitle()}</Page.Title>
            {this.renderSearchBox()}
            <Link to={`/search/${this.props.params.entitySetId}`} className={styles.changeSearchView}>
              Simple Search
            </Link>
          </Page.Header>
          <Page.Body>
            {this.renderErrorMessage()}
            <AsyncContent
                status={this.state.asyncStatus}
                pendingContent={
Please run a search
}
                content={this.renderSearchResultType} />
            {this.renderPagination()}

          </Page.Body>
        </Page>
      </DocumentTitle>
    );
  }

}
<commit_msg>fix advanced search pagination<commit_after>import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import { Pagination } from 'react-bootstrap';
import DocumentTitle from 'react-document-title';
import Promise from 'bluebird';
import { AuthorizationApi, SearchApi, EntityDataModelApi } from 'loom-data';
import { Permission } from '../../core/permissions/Permission';
import Page from '../../components/page/Page';
import AdvancedSearchBox from './AdvancedSearchBox';
import EntitySetSearchResults from './EntitySetSearchResults';
import EntitySetUserSearchResults from './EntitySetUserSearchResults';
import AsyncContent, { ASYNC_STATUS } from '../../components/asynccontent/AsyncContent';
import { FIRST_NAMES, LAST_NAMES, DOBS } from '../../utils/Consts/StringConsts';
import styles from './styles.module.css';

const MAX_HITS = 50;

export default class AdvancedDataSearch extends React.Component {
  static contextTypes = {
    router: PropTypes.object
  };

  static propTypes = {
    params: PropTypes.shape({
      entitySetId: PropTypes.string.isRequired
    }).isRequired
  }

  constructor(props) {
    super(props);
    this.state = {
      page: 1,
      searchResults: [],
      totalHits: 0,
      title: '',
      asyncStatus: ASYNC_STATUS.PENDING,
      propertyTypes: [],
      loadError: false,
      hidePagination: false,
      searches: {}
    };
  }

  componentDidMount() {
    this.loadPropertyIds();
  }

  loadPropertyIds = () => {
    EntityDataModelApi.getEntitySet(this.props.params.entitySetId)
    .then((entitySet) => {
      EntityDataModelApi.getEntityType(entitySet.entityTypeId)
      .then((entityType) => {
        this.loadAuthorizedPropertyTypes(entitySet, entityType.properties);
      }).catch(() => {
        this.setState({ loadError: true });
      });
    }).catch(() => {
      this.setState({ loadError: true });
    });
  }

  loadAuthorizedPropertyTypes = (entitySet, propertyIds) => {
    const accessChecks = propertyIds.map((propertyId) => {
      return {
        aclKey: [this.props.params.entitySetId, propertyId],
        permissions: [Permission.READ.name]
      };
    });
    AuthorizationApi.checkAuthorizations(accessChecks)
    .then((response) => {
      const propsWithReadAccess = [];
      response.forEach((property) => {
        if (property.permissions.READ) {
          propsWithReadAccess.push(property.aclKey[1]);
        }
      });
      const propertyTypePromises = propsWithReadAccess.map((propId) => {
        return EntityDataModelApi.getPropertyType(propId);
      });
      Promise.all(propertyTypePromises)
      .then((propertyTypes) => {
        this.setState({
          propertyTypes,
          title: entitySet.title,
          loadError: false
        });
      }).catch(() => {
        this.setState({ loadError: true });
      });
    }).catch(() => {
      this.setState({ loadError: true });
    });
  }

  executeSearch = (searches, page) => {
    if (Object.keys(searches).length >= 1 && Object.values(searches).length >= 1) {
      const searchDetails = Object.values(searches).filter((search) => {
        return search.searchTerm && search.searchTerm.length;
      });
      const searchOptions = {
        searchFields: searchDetails,
        start: ((page - 1) * 50),
        maxHits: MAX_HITS
      };
      SearchApi.advancedSearchEntitySetData(this.props.params.entitySetId, searchOptions)
      .then((response) => {
        this.setState({
          searchResults: response.hits,
          totalHits: response.numHits,
          asyncStatus: ASYNC_STATUS.SUCCESS,
          searches,
          page
        });
      }).catch(() => {
        this.setState({ asyncStatus: ASYNC_STATUS.ERROR });
      });
    }
  }

  renderEntitySetTitle = () => {
    if (this.state.title.length <= 0) return '';
    return (
      : <Link
          to={`/entitysets/${this.props.params.entitySetId}`}
          className={styles.titleLink}>{this.state.title}</Link>
    );
  }

  renderErrorMessage = () => {
    if (this.state.loadError) {
      return
Unable to load entity set info.
;
    }
    return null;
  }

  handlePageSelect = (eventKey) => {
    this.setState({ page: eventKey });
    this.executeSearch(this.state.searches, eventKey);
  }

  hidePagination = (shouldHide) => {
    this.setState({ hidePagination: shouldHide });
  }

  formatValue = (rawValue) => {
    if (rawValue instanceof Array) {
      let formattedValue = '';
      if (rawValue.length > 0) formattedValue = formattedValue.concat(rawValue[0]);
      if (rawValue.length > 1) {
        for (let i = 1; i < rawValue.length; i += 1) {
          formattedValue = formattedValue.concat(', ').concat(rawValue[i]);
        }
      }
      return formattedValue;
    }
    return rawValue;
  }

  onSearchSubmit = (searches) => {
    const page = 1;
    this.executeSearch(searches, page);
    this.setState({ searches, page });
  }

  renderPagination = () => {
    const activePage = parseInt(this.state.page, 10);
    if (this.state.hidePagination || this.state.totalHits <= 0 || isNaN(activePage)) return null;
    const numPages = Math.ceil((1.0 * this.state.totalHits) / MAX_HITS);
    return (

        <Pagination
            prev
            next
            ellipsis
            boundaryLinks
            items={numPages}
            maxButtons={5}
            activePage={activePage}
            onSelect={this.handlePageSelect} />

    );
  }

  renderSearchResultType = () => {
    let firstName;
    let lastName;
    let dob;
    this.state.propertyTypes.forEach((propertyType) => {
      if (FIRST_NAMES.includes(propertyType.type.name.toLowerCase())) firstName = propertyType;
      else if (LAST_NAMES.includes(propertyType.type.name.toLowerCase())) lastName = propertyType;
      else if (DOBS.includes(propertyType.type.name.toLowerCase())) dob = propertyType;
    });
    if (firstName && lastName) {
      return (
        <EntitySetUserSearchResults
            results={this.state.searchResults}
            entitySetId={this.props.params.entitySetId}
            propertyTypes={this.state.propertyTypes}
            firstName={firstName}
            lastName={lastName}
            dob={dob}
            hidePaginationFn={this.hidePagination}
            formatValueFn={this.formatValue} />
      );
    }
    return (
      <EntitySetSearchResults
          results={this.state.searchResults}
          entitySetId={this.props.params.entitySetId}
          propertyTypes={this.state.propertyTypes}
          formatValueFn={this.formatValue} />
    );
  }

  renderSearchBox = () => {
    if (this.state.propertyTypes.length === 0) return null;
    return (
      <AdvancedSearchBox
          onSubmit={this.onSearchSubmit}
          propertyTypes={this.state.propertyTypes} />
    );
  }

  render() {
    const title = (this.state.title && this.state.title.length)
      ? `Advanced Search: ${this.state.title}`
      : 'Advanced Search';
    return (
      <DocumentTitle title={title}>
        <Page>
          <Page.Header>
            <Page.Title>Search entity set{this.renderEntitySetTitle()}</Page.Title>
            {this.renderSearchBox()}
            <Link to={`/search/${this.props.params.entitySetId}`} className={styles.changeSearchView}>
              Simple Search
            </Link>
          </Page.Header>
          <Page.Body>
            {this.renderErrorMessage()}
            <AsyncContent
                status={this.state.asyncStatus}
                pendingContent={
Please run a search
}
                content={this.renderSearchResultType} />
            {this.renderPagination()}

          </Page.Body>
        </Page>
      </DocumentTitle>
    );
  }

}
<|endoftext|>