<commit_before>var express = require('express')
var path = require('path')
var webpack = require('webpack')
var config = require('./webpack.config.development')
var app = express()
var compiler = webpack(config)
var db = require('./models');

var middleware = require('webpack-dev-middleware')(compiler, {
  publicPath: config.output.publicPath,
  contentBase: 'src',
  stats: {
    colors: true,
    hash: false,
    timings: true,
    chunks: false,
    chunkModules: false,
    modules: false
  }
});

app.use(middleware);
app.use(require('webpack-hot-middleware')(compiler, {
  log: console.log
}));

// app.get('*', function response(req, res) {
//   res.write(middleware.fileSystem.readFileSync(path.join(__dirname, 'dist/index.html')));
//   res.end();
// });

app.use(express.static(path.join(__dirname, '/dist')))

require('./controllers/categories')

app.listen(config._hotPort, 'localhost', function (err) {
  if (err) {
    console.log(err)
  }
  db.sequelize.sync();
  console.info('==> Listening on port %s. Open up http://localhost:%s/ in your browser.', config._hotPort, config._hotPort)
})
<commit_msg>Removed broken sequelize models<commit_after>var express = require('express')
var path = require('path')
var webpack = require('webpack')
var config = require('./webpack.config.development')
var app = express()
var compiler = webpack(config)
// var db = require('./models');

var middleware = require('webpack-dev-middleware')(compiler, {
  publicPath: config.output.publicPath,
  contentBase: 'src',
  stats: {
    colors: true,
    hash: false,
    timings: true,
    chunks: false,
    chunkModules: false,
    modules: false
  }
});

app.use(middleware);
app.use(require('webpack-hot-middleware')(compiler, {
  log: console.log
}));

// app.get('*', function response(req, res) {
//   res.write(middleware.fileSystem.readFileSync(path.join(__dirname, 'dist/index.html')));
//   res.end();
// });

app.use(express.static(path.join(__dirname, '/dist')))

require('./controllers/categories')

app.listen(config._hotPort, 'localhost', function (err) {
  if (err) {
    console.log(err)
  }
  // db.sequelize.sync();
  console.info('==> Listening on port %s. Open up http://localhost:%s/ in your browser.', config._hotPort, config._hotPort)
})
<|endoftext|>


<commit_before>const smash = require("../../../smash");
const logger = smash.logger();
const errorUtil = smash.errorUtil();
const Request = require("./lib/request");
const Response = require("./lib/response");
const Router = require("./lib/router");
const { RESPONSE_HEADERS_DEFAULT } = require("./lib/constant");

class ApiGatewayProxyRest {
	constructor() {
		this.router = new Router();
	}

	_buildRequest(event, context) {
		const request = new Request(event, context);
		return request;
	}

	_buildResponse(request) {
		const response = new Response(this, request);
		const headers = smash.config.get(RESPONSE_HEADERS_DEFAULT);
		response.addHeaders(headers);
		return response;
	}

	handleEvent(event, context, callback) {
		if (typeof callback !== 'function') {
			throw new errorUtil.TypeError("Third parameter of handleEvent() must be a function, ", callback);
		}
		this._callback = callback;
		const request = this._buildRequest(event, context);
		const response = this._buildResponse(request);
		if (typeof event !== "object" || this.isEvent(event) === false) {
			response.handleError(errorUtil.internalServerError("Wrong type of event as argument to ApiGatewayProxy.handleEvent()"));
		} else {
			try {
				this.router.handleRequest(request, response);
			} catch (error) {
				return response.handleError(error);
			}
			this.handleRequest(request, response);
		}
	}

	async handleRequest(request, response) {
		logger.info("RequestId: " + request.requestId);
		logger.info("Matched route: " + request.route.method + " " + request.route.path + "; version: " + request.route.version + "; request: " + request.route.method + " " + request.path + " in env: " + smash.getEnv("ENV") + " with user: " + (request.user ? request.user.username : "Anonymous"));
		smash.setCurrentEvent(request);
		if (smash.filter.hasInRule(request.route) === true) {
			smash.filter.cleanIn(request.route, request);
		}
		try {
			await request.route.callback.call(smash, request, response);
		} catch (error) {
			response.handleError(error);
		}
		return this;
	}

	handleResponse(response) {
		logger.info("Response code: " + response.code);
		this._callback(null, {
			statusCode: response.code,
			headers: response.headers,
			body: response.stringifiedBody,
		});
		return this;
	}

	isEvent(event) {
		if (event.httpMethod && event.path && !event.type) {
			return true;
		}
		return false;
	}

	get(route, callback) {
		this.router.get(route, callback);
		return this;
	}

	post(route, callback) {
		this.router.post(route, callback);
		return this;
	}

	put(route, callback) {
		this.router.put(route, callback);
		return this;
	}

	delete(route, callback) {
		this.router.delete(route, callback);
		return this;
	}

	patch(route, callback) {
		this.router.patch(route, callback);
		return this;
	}

	options(route, callback) {
		this.router.options(route, callback);
		return this;
	}

	head(route, callback) {
		this.router.head(route, callback);
		return this;
	}

	getHandlers() {
		return this.getRoutes();
	}

	getRoutes() {
		return this.router.getRoutes();
	}

	expose() {
		return [
			{
				"functionName": "get",
				"function": "get",
			},
			{
				"functionName": "post",
				"function": "post",
			},
			{
				"functionName": "put",
				"function": "put",
			},
			{
				"functionName": "delete",
				"function": "delete",
			},
			{
				"functionName": "patch",
				"function": "patch",
			},
			{
				"functionName": "options",
				"function": "options",
			},
			{
				"functionName": "head",
				"function": "head",
			},
		];
	}
}

module.exports = ApiGatewayProxyRest;
<commit_msg>Fix error handling<commit_after>const smash = require("../../../smash");
const logger = smash.logger();
const errorUtil = smash.errorUtil();
const Request = require("./lib/request");
const Response = require("./lib/response");
const Router = require("./lib/router");
const { RESPONSE_HEADERS_DEFAULT } = require("./lib/constant");

class ApiGatewayProxyRest {
	constructor() {
		this.router = new Router();
	}

	_buildRequest(event, context) {
		const request = new Request(event, context);
		return request;
	}

	_buildResponse(request) {
		const response = new Response(this, request);
		const headers = smash.config.get(RESPONSE_HEADERS_DEFAULT);
		response.addHeaders(headers);
		return response;
	}

	handleEvent(event, context, callback) {
		if (typeof callback !== 'function') {
			throw new errorUtil.TypeError("Third parameter of handleEvent() must be a function, ", callback);
		}
		this._callback = callback;
		const request = this._buildRequest(event, context);
		const response = this._buildResponse(request);
		if (typeof event !== "object" || this.isEvent(event) === false) {
			response.handleError(errorUtil.internalServerError("Wrong type of event as argument to ApiGatewayProxy.handleEvent()"));
		} else {
			try {
				this.router.handleRequest(request, response);
			} catch (error) {
				return response.handleError(error);
			}
			this.handleRequest(request, response);
		}
	}

	async handleRequest(request, response) {
		logger.info("RequestId: " + request.requestId);
		logger.info("Matched route: " + request.route.method + " " + request.route.path + "; version: " + request.route.version + "; request: " + request.route.method + " " + request.path + " in env: " + smash.getEnv("ENV") + " with user: " + (request.user ? request.user.username : "Anonymous"));
		smash.setCurrentEvent(request);
		try {
			if (smash.filter.hasInRule(request.route) === true) {
				smash.filter.cleanIn(request.route, request);
			}
			await request.route.callback.call(smash, request, response);
		} catch (error) {
			response.handleError(error);
		}
		return this;
	}

	handleResponse(response) {
		logger.info("Response code: " + response.code);
		this._callback(null, {
			statusCode: response.code,
			headers: response.headers,
			body: response.stringifiedBody,
		});
		return this;
	}

	isEvent(event) {
		if (event.httpMethod && event.path && !event.type) {
			return true;
		}
		return false;
	}

	get(route, callback) {
		this.router.get(route, callback);
		return this;
	}

	post(route, callback) {
		this.router.post(route, callback);
		return this;
	}

	put(route, callback) {
		this.router.put(route, callback);
		return this;
	}

	delete(route, callback) {
		this.router.delete(route, callback);
		return this;
	}

	patch(route, callback) {
		this.router.patch(route, callback);
		return this;
	}

	options(route, callback) {
		this.router.options(route, callback);
		return this;
	}

	head(route, callback) {
		this.router.head(route, callback);
		return this;
	}

	getHandlers() {
		return this.getRoutes();
	}

	getRoutes() {
		return this.router.getRoutes();
	}

	expose() {
		return [
			{
				"functionName": "get",
				"function": "get",
			},
			{
				"functionName": "post",
				"function": "post",
			},
			{
				"functionName": "put",
				"function": "put",
			},
			{
				"functionName": "delete",
				"function": "delete",
			},
			{
				"functionName": "patch",
				"function": "patch",
			},
			{
				"functionName": "options",
				"function": "options",
			},
			{
				"functionName": "head",
				"function": "head",
			},
		];
	}
}

module.exports = ApiGatewayProxyRest;
<|endoftext|>


<commit_before>import React from 'react';
import {shouldComponentUpdate} from 'react-addons-pure-render-mixin';
import {Motion, spring} from 'react-motion';

import HeightReporter from './HeightReporter';

const Collapse = React.createClass({
  propTypes: {
    isOpened: React.PropTypes.bool.isRequired,
    children: React.PropTypes.node.isRequired,
    fixedHeight: React.PropTypes.number,
    style: React.PropTypes.object
  },

  getDefaultProps() {
    return {fixedHeight: -1, style: {}};
  },

  getInitialState() {
    return {height: 0, dirty: true};
  },

  componentWillMount() {
    this.height = '0.00';
  },

  componentWillReceiveProps({children, fixedHeight}) {
    if (!fixedHeight && children !== this.props.children) {
      this.setState({dirty: true});
    }
  },

  shouldComponentUpdate,

  onHeightReady(height) {
    this.setState({height, dirty: false});
  },

  renderHeightReporter() {
    if (!this.state.dirty && this.state.height) {
      return null;
    }
    const {isOpened, fixedHeight, ...props} = this.props;

    return (
      <HeightReporter onHeightReady={this.onHeightReady} {...props} />
    );
  },

  renderFixed() {
    const {isOpened, style, children, fixedHeight, ...props} = this.props;

    return (
      <Motion defaultStyle={{height: 0}} style={{height: spring(isOpened ? fixedHeight : 0)}}>
        {({height}) => (!isOpened && !height) ? null : (

            {children}

        )}
      </Motion>
    );
  },

  render() {
    const {isOpened, style, children, fixedHeight, ...props} = this.props;

    if (fixedHeight > -1) {
      return this.renderFixed();
    }

    const {height} = this.state;

    return (

        {this.renderHeightReporter()}

        <Motion defaultStyle={{height: 0}} style={{height: spring(isOpened ? height : 0)}}>
          {st => {
            this.height = parseFloat(st.height).toFixed(2);
            if (!isOpened && !st.height) {
              return null;
            }

            const newStyle = this.height !== parseFloat(height).toFixed(2) ? {
              height: st.height,
              overflow: 'hidden'
            } : {height: 'auto'};

            return (

                {children}

            );
          }}
        </Motion>

    );
  }
});

export default Collapse;
<commit_msg>Fix auto-height collapse.<commit_after>import React from 'react';
import {shouldComponentUpdate} from 'react-addons-pure-render-mixin';
import {Motion, spring} from 'react-motion';

import HeightReporter from './HeightReporter';

const Collapse = React.createClass({
  propTypes: {
    isOpened: React.PropTypes.bool.isRequired,
    children: React.PropTypes.node.isRequired,
    fixedHeight: React.PropTypes.number,
    style: React.PropTypes.object
  },

  getDefaultProps() {
    return {fixedHeight: -1, style: {}};
  },

  getInitialState() {
    return {height: 0, dirty: true};
  },

  componentWillMount() {
    this.height = '0.00';
  },

  componentWillReceiveProps({children, fixedHeight}) {
    if (fixedHeight < 0 && children !== this.props.children) {
      this.setState({dirty: true});
    }
  },

  shouldComponentUpdate,

  onHeightReady(height) {
    this.setState({height, dirty: false});
  },

  renderHeightReporter() {
    if (!this.state.dirty && this.state.height) {
      return null;
    }
    const {isOpened, fixedHeight, ...props} = this.props;

    return (
      <HeightReporter onHeightReady={this.onHeightReady} {...props} />
    );
  },

  renderFixed() {
    const {isOpened, style, children, fixedHeight, ...props} = this.props;

    return (
      <Motion defaultStyle={{height: 0}} style={{height: spring(isOpened ? fixedHeight : 0)}}>
        {({height}) => (!isOpened && !height) ? null : (

            {children}

        )}
      </Motion>
    );
  },

  render() {
    const {isOpened, style, children, fixedHeight, ...props} = this.props;

    if (fixedHeight > -1) {
      return this.renderFixed();
    }

    const {height} = this.state;

    return (

        {this.renderHeightReporter()}

        <Motion defaultStyle={{height: 0}} style={{height: spring(isOpened ? height : 0)}}>
          {st => {
            this.height = parseFloat(st.height).toFixed(2);
            if (!isOpened && !st.height) {
              return null;
            }

            const newStyle = this.height !== parseFloat(height).toFixed(2) ? {
              height: st.height,
              overflow: 'hidden'
            } : {height: 'auto'};

            return (

                {children}

            );
          }}
        </Motion>

    );
  }
});

export default Collapse;
<|endoftext|>


<commit_before>const log = require('kth-node-log')
const Promise = require('bluebird')
const ldap = require('ldapjs')

function getBoundClient () {
  return new Promise((resolve, reject) => {
    const options = {
      url: process.env.LDAP_URL || 'ldaps://ldap.kth.se',
      timeout: 1000,
      connectTimeout: 1000,
      log: log
    }
    log.info('Should get ldap client for', options)
    const ldapClient = ldap.createClient(options)
    ldapClient.on('error', function (e) {
      log.error('In ldapClient on error:', e)
      reject(e)
    })
    ldapClient.bind(process.env.LDAP_USERNAME, process.env.LDAP_PASSWORD, function (err) {
      if (err) {
        reject(err)
      } else {
        log.info('Created bound ldap client')
        resolve(ldapClient)
      }
    })
  })
}

function lookupUser (ldapClient, kthid) {
  return new Promise((resolve, reject) => {
    log.info('Should try to search')
    ldapClient.search(
      'ou=UG,dc=referens,dc=sys,dc=kth,dc=se',
      {
        scope: 'sub',
        filter: `(ugKthId=${kthid})`,
        timeLimit: 10,
        paging: true,
        attributes: ['givenName', 'sn', 'norEduPersonNIN'],
        paged: {
          pageSize: 1000,
          pagePause: false
        }
      },
      function (err, res) {
        if (err) {
          log.debug('God err from search:', err)
          reject(err)
        } else {
          let user
          res.on('searchEntry', ({object}) => { user = object })
          res.on('end', () => resolve(user))
          res.on('error', reject)
        }
      }
    )
  })
}

module.exports = {
  getBoundClient,
  lookupUser
}
<commit_msg>timeout and connectTimeout are separate events.<commit_after>const log = require('kth-node-log')
const Promise = require('bluebird')
const ldap = require('ldapjs')

function getBoundClient () {
  return new Promise((resolve, reject) => {
    const options = {
      url: process.env.LDAP_URL || 'ldaps://ldap.kth.se',
      timeout: 1000,
      connectTimeout: 1000,
      log: log
    }
    log.info('Should get ldap client for', options)
    const ldapClient = ldap.createClient(options)
    const doReject = function (e) {
      log.debug('In ldapClient rejection callback:', e)
      reject(e)
    }
    ldapClient.on('error', doReject)
    ldapClient.on('timeout', doReject)
    ldapClient.on('connectTimeout', doReject)
    ldapClient.bind(process.env.LDAP_USERNAME, process.env.LDAP_PASSWORD, function (err) {
      if (err) {
        reject(err)
      } else {
        log.info('Created bound ldap client')
        resolve(ldapClient)
      }
    })
  })
}

function lookupUser (ldapClient, kthid) {
  return new Promise((resolve, reject) => {
    log.info('Should try to search')
    ldapClient.search(
      'ou=UG,dc=referens,dc=sys,dc=kth,dc=se',
      {
        scope: 'sub',
        filter: `(ugKthId=${kthid})`,
        timeLimit: 10,
        paging: true,
        attributes: ['givenName', 'sn', 'norEduPersonNIN'],
        paged: {
          pageSize: 1000,
          pagePause: false
        }
      },
      function (err, res) {
        if (err) {
          log.debug('God err from search:', err)
          reject(err)
        } else {
          let user
          res.on('searchEntry', ({object}) => { user = object })
          res.on('end', () => resolve(user))
          res.on('error', reject)
        }
      }
    )
  })
}

module.exports = {
  getBoundClient,
  lookupUser
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React, { Component } from 'react'

import sdk from './sdk'
import SocialUser from './SocialUser'

export default class SocialLogin extends Component {
  static propTypes = {
    appId: PropTypes.string.isRequired,
    callback: PropTypes.func,
    children: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number,
      PropTypes.element,
      PropTypes.node
    ]).isRequired,
    provider: PropTypes.oneOf([
      'facebook',
      'google',
      'linkedin'
    ]).isRequired,
    version: PropTypes.string
  }

  static defaultProps = {
    version: '2.8'
  }

  constructor (props) {
    super(props)

    this.id = 'sl' + Math.floor(Math.random() * 0xFFFF)

    this.handleSocialLoginInvokeSuccess = this.handleSocialLoginInvokeSuccess.bind(this)
    this.handleSocialLoginInvokeFailure = this.handleSocialLoginInvokeFailure.bind(this)
    this.handleLogin = this.handleLogin.bind(this)
  }

  handleSocialLoginInvokeSuccess (res) {
    const { callback, provider } = this.props

    // console.log(res)  // Uncomment to check response coming from provider in log

    const user = new SocialUser()
    let userProfile
    let token

    switch (provider) {
      case 'google':
        const profile = window.gapi.auth2.getAuthInstance().currentUser.get().getBasicProfile()
        const authResponse = window.gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse(true)

        userProfile = {
          id: profile.getId(),
          name: profile.getName(),
          firstName: profile.getGivenName(),
          lastName: profile.getFamilyName(),
          email: profile.getEmail(),
          profilePicURL: profile.getImageUrl()
        }
        token = {
          accessToken: authResponse.access_token,
          expiresAt: authResponse.expires_at
        }

        break
      case 'facebook':
        userProfile = {
          id: res.id,
          name: res.name,
          firstName: res.first_name,
          lastName: res.last_name,
          email: res.email,
          profilePicURL: res.picture.data.url
        }
        token = {
          accessToken: res.authResponse.accessToken,
          expiresAt: res.authResponse.expiresIn
        }

        break
      case 'linkedin':
        userProfile = {
          id: window.IN.ENV.auth.member_id,
          name: `${res.values[0].firstName} ${res.values[0].lastName}`,
          firstName: res.values[0].firstName,
          lastName: res.values[0].lastName,
          email: res.values[0].emailAddress,
          profilePicURL: res.values[0].pictureUrl
        }
        token = {
          accessToken: undefined // Couldn't find a way to fetch token
        }

        const expiresIn = new Date()

        expiresIn.setSeconds(expiresIn.getSeconds() + window.IN.ENV.auth.oauth_expires_in)
        user.token.expiresAt = expiresIn

        break
      default:
        throw new Error(`Provider ’${provider}’ isn’t supported.`)
    }

    user.provider = provider
    user.profile = userProfile
    user.token = token

    callback(user, null)
  }

  handleSocialLoginInvokeFailure (err) {
    this.props.callback(null, err)
  }

  handleLogin (e, obj) {
    const { appId, provider, version } = this.props
    const handleSuccess = this.handleSocialLoginInvokeSuccess

    if (provider === 'facebook') {
      window.FB.init({
        appId,
        xfbml: true,
        version: `v${version}`
      })

      // Invoke Facebook Login
      window.FB.login((response) => {
        const loginResponse = response

        window.FB.api('/me', { fields: 'email,name,id,first_name,last_name,picture' }, (profileResponse) => {
          Object.assign(profileResponse, loginResponse)

          handleSuccess(profileResponse)
        })
      }, { scope: 'email' })
    } else if (provider === 'linkedin') {
      window.IN.User.authorize((data) => {
        window.IN.API.Profile('me').fields([
          'id',
          'firstName',
          'lastName',
          'pictureUrl',
          'publicProfileUrl',
          'emailAddress'
        ]).result((profile) => {
          handleSuccess(profile)
        }).error((err) => {
          this.handleSocialLoginInvokeFailure(err)
        })
      })
    }
  }

  componentDidMount () {
    const appId = this.props.appId

    if (this.props.provider === 'google') {
      sdk.google.oldLoad(appId, this.id, this.handleSocialLoginInvokeSuccess, this.handleSocialLoginInvokeFailure)
    } else if (this.props.provider === 'facebook') {
      sdk.facebook.oldLoad(appId)
    } else if (this.props.provider === 'linkedin') {
      sdk.linkedin.oldLoad(appId)
    }
  }

  getProfile () {
    window.IN.API.Profile('me').fields([
      'id',
      'firstName',
      'lastName',
      'pictureUrl',
      'publicProfileUrl',
      'emailAddress'
    ]).result(function (profile) {
      alert(profile)
    })
  }

  render () {
    return (

{this.props.children}

    )
  }
}
<commit_msg>Expose id token in handleSocialLoginInvokeSuccess<commit_after>import PropTypes from 'prop-types'
import React, { Component } from 'react'

import sdk from './sdk'
import SocialUser from './SocialUser'

export default class SocialLogin extends Component {
  static propTypes = {
    appId: PropTypes.string.isRequired,
    callback: PropTypes.func,
    children: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number,
      PropTypes.element,
      PropTypes.node
    ]).isRequired,
    provider: PropTypes.oneOf([
      'facebook',
      'google',
      'linkedin'
    ]).isRequired,
    version: PropTypes.string
  }

  static defaultProps = {
    version: '2.8'
  }

  constructor (props) {
    super(props)

    this.id = 'sl' + Math.floor(Math.random() * 0xFFFF)

    this.handleSocialLoginInvokeSuccess = this.handleSocialLoginInvokeSuccess.bind(this)
    this.handleSocialLoginInvokeFailure = this.handleSocialLoginInvokeFailure.bind(this)
    this.handleLogin = this.handleLogin.bind(this)
  }

  handleSocialLoginInvokeSuccess (res) {
    const { callback, provider } = this.props

    // console.log(res)  // Uncomment to check response coming from provider in log

    const user = new SocialUser()
    let userProfile
    let token

    switch (provider) {
      case 'google':
        const profile = window.gapi.auth2.getAuthInstance().currentUser.get().getBasicProfile()
        const authResponse = window.gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse(true)

        userProfile = {
          id: profile.getId(),
          name: profile.getName(),
          firstName: profile.getGivenName(),
          lastName: profile.getFamilyName(),
          email: profile.getEmail(),
          profilePicURL: profile.getImageUrl()
        }
        token = {
          accessToken: authResponse.access_token,
          idToken: authResponse.id_token,
          scope: authResponse.scope,
          expiresIn: authResponse.expires_in,
          firstIssued_at: authResponse.first_issued_at,
          expiresAt: authResponse.expires_at
        }

        break
      case 'facebook':
        userProfile = {
          id: res.id,
          name: res.name,
          firstName: res.first_name,
          lastName: res.last_name,
          email: res.email,
          profilePicURL: res.picture.data.url
        }
        token = {
          accessToken: res.authResponse.accessToken,
          expiresAt: res.authResponse.expiresIn
        }

        break
      case 'linkedin':
        userProfile = {
          id: window.IN.ENV.auth.member_id,
          name: `${res.values[0].firstName} ${res.values[0].lastName}`,
          firstName: res.values[0].firstName,
          lastName: res.values[0].lastName,
          email: res.values[0].emailAddress,
          profilePicURL: res.values[0].pictureUrl
        }
        token = {
          accessToken: undefined // Couldn't find a way to fetch token
        }

        const expiresIn = new Date()

        expiresIn.setSeconds(expiresIn.getSeconds() + window.IN.ENV.auth.oauth_expires_in)
        user.token.expiresAt = expiresIn

        break
      default:
        throw new Error(`Provider ’${provider}’ isn’t supported.`)
    }

    user.provider = provider
    user.profile = userProfile
    user.token = token

    callback(user, null)
  }

  handleSocialLoginInvokeFailure (err) {
    this.props.callback(null, err)
  }

  handleLogin (e, obj) {
    const { appId, provider, version } = this.props
    const handleSuccess = this.handleSocialLoginInvokeSuccess

    if (provider === 'facebook') {
      window.FB.init({
        appId,
        xfbml: true,
        version: `v${version}`
      })

      // Invoke Facebook Login
      window.FB.login((response) => {
        const loginResponse = response

        window.FB.api('/me', { fields: 'email,name,id,first_name,last_name,picture' }, (profileResponse) => {
          Object.assign(profileResponse, loginResponse)

          handleSuccess(profileResponse)
        })
      }, { scope: 'email' })
    } else if (provider === 'linkedin') {
      window.IN.User.authorize((data) => {
        window.IN.API.Profile('me').fields([
          'id',
          'firstName',
          'lastName',
          'pictureUrl',
          'publicProfileUrl',
          'emailAddress'
        ]).result((profile) => {
          handleSuccess(profile)
        }).error((err) => {
          this.handleSocialLoginInvokeFailure(err)
        })
      })
    }
  }

  componentDidMount () {
    const appId = this.props.appId

    if (this.props.provider === 'google') {
      sdk.google.oldLoad(appId, this.id, this.handleSocialLoginInvokeSuccess, this.handleSocialLoginInvokeFailure)
    } else if (this.props.provider === 'facebook') {
      sdk.facebook.oldLoad(appId)
    } else if (this.props.provider === 'linkedin') {
      sdk.linkedin.oldLoad(appId)
    }
  }

  getProfile () {
    window.IN.API.Profile('me').fields([
      'id',
      'firstName',
      'lastName',
      'pictureUrl',
      'publicProfileUrl',
      'emailAddress'
    ]).result(function (profile) {
      alert(profile)
    })
  }

  render () {
    return (

{this.props.children}

    )
  }
}
<|endoftext|>


<commit_before>define(function (require) {

    var Base = require('../core/Base');
    var glMatrix = require('../dep/glmatrix');
    var glenum = require('../core/glenum');
    var mat4 = glMatrix.mat4;
    var vec3 = glMatrix.vec3;
    var vec4 = glMatrix.vec4;

    var vec3Set = vec3.set;
    var vec3Create = vec3.create;

    var vec4Create = vec4.create;

    var round = Math.round;

    var PRIMITIVE_TRIANGLE = 1;
    var PRIMITIVE_LINE = 2;
    var PRIMITIVE_POINT = 3;

    function PrimitivePool(constructor) {
        this.ctor = constructor;

        this._data = [];

        this._size = 0;
    }

    PrimitivePool.prototype = {
        pick: function () {
            var data = this._data;
            var size = this._size;
            var obj = data[size];
            if (! obj) {
                // Constructor must have no parameters
                obj = new this.ctor();
                data[size] = obj;
            }
            this._size++;
            return obj;
        },

        reset: function () {
            this._size = 0;
        },

        shrink: function () {
            this._data.length = this._size;
        },

        clear: function () {
            this._data = [];
            this._size = 0;
        }
    }

    function Triangle() {
        this.vertices = [vec4Create(), vec4Create(), vec4Create()];
        this.color = vec4Create();

        this.depth = 0;
    }

    Triangle.prototype.type = PRIMITIVE_TRIANGLE;

    function Point() {
        // Here use an array to make it more convinient to proccessing in _setPrimitive method
        this.vertices = [vec4Create()];

        this.color = vec4Create();

        this.depth = 0;
    }

    Point.prototype.type = PRIMITIVE_POINT;

    function Line() {
        this.vertices = [vec4Create(), vec4Create()];
        this.color = vec4Create();

        this.depth = 0;

        this.lineWidth = 1;
    }

    Line.prototype.type = PRIMITIVE_LINE;

    function depthSortFunc(x, y) {
        // Sort from far to near, which in depth of projection space is from larger to smaller
        return y.depth - x.depth;
    }

    function vec3ToColorStr(v3) {
        return 'rgb(' + round(v3[0] * 255) + ',' + round(v3[1] * 255) + ',' + round(v3[2] * 255) + ')';
    }

    function vec4ToColorStr(v4) {
        return 'rgba(' + round(v4[0] * 255) + ',' + round(v4[1] * 255) + ',' + round(v4[2] * 255) + ',' + v4[3] + ')';
    }

    var CanvasRenderer = Base.derive({

        canvas: null,

        _width: 100,

        _height: 100,

        devicePixelRatio: window.devicePixelRatio || 1.0,

        color: [0.0, 0.0, 0.0, 0.0],

        clear: true,

        ctx: null,

        // Cached primitive list, including triangle, line, point
        _primitives: [],

        // Triangle pool
        _triangles: new PrimitivePool(Triangle),

        // Line pool
        _lines: new PrimitivePool(Line),

        // Point pool
        _points: new PrimitivePool(Point)
    }, function () {
        if (! this.canvas) {
            this.canvas = document.createElement('canvas');
        }
        var canvas = this.canvas;

        try {
            this.ctx = canvas.getContext('2d');
            var ctx = this.ctx;
            if (! ctx) {
                throw new Error();
            }
        }
        catch (e) {
            throw 'Error creating WebGL Context ' + e;
        }

        this.resize();
    }, {

        resize: function (width, height) {
            var dpr = this.devicePixelRatio;
            var canvas = this.canvas;
            if (width != null) {
                canvas.style.width = width + 'px';
                canvas.style.height = height + 'px';
                canvas.width = width * dpr;
                canvas.height = height * dpr;

                this._width = width;
                this._height = height;
            }
            else {
                this._width = canvas.width / dpr;
                this._height = canvas.height / dpr;
            }
        },

        getWidth: function () {
            return this._width;
        },

        getHeight: function () {
            return this._height;
        },

        getViewportAspect: function () {
            return this._width / this._height;
        },

        render: function (scene, camera) {

            if (this.clear) {
                var color = this.color;
                var ctx = this.ctx;
                var w = this._width;
                var h = this._height;
                if (color && color[3] === 0) {
                    ctx.clearRect(0, 0, w, h);
                }
                else {
                    // Has transparency
                    if (color[3] < 1) {
                        ctx.clearRect(0, 0, w, h);
                    }
                    ctx.fillStyle = color.length === 4 ? vec4ToColorStr(color) : vec3ToColorStr(color);
                    ctx.fillRect(0, 0, w, h);
                }
            }

            scene.update();
            camera.update();

            var opaqueQueue = scene.opaqueQueue;
            var transparentQueue = scene.transparentQueue;
            var sceneMaterial = scene.material;

            var queue = opaqueQueue.concat(transparentQueue);

            this.renderQueue(queue, camera);
        },

        renderQueue: function (queue, camera) {
            var viewProj = mat4.create();
            mat4.multiply(viewProj, camera.projectionMatrix._array, camera.viewMatrix._array);
            var worldViewProjMat = mat4.create();
            var posViewSpace = vec3.create();

            var primitives = this._primitives;
            var trianglesPool = this._triangles;
            var linesPool = this._lines;
            var pointsPool = this._points;

            trianglesPool.reset();
            linesPool.reset();
            pointsPool.reset();

            var nPrimitive = 0;

            var indices = [0, 0, 0];
            var matColor = [];
            for (var i = 0; i < queue.length; i++) {
                var renderable = queue[i];

                mat4.multiply(worldViewProjMat, viewProj, renderable.worldTransform._array);

                var geometry = renderable.geometry;
                var material = renderable.material;
                var attributes = geometry.attributes;

                // alpha is default 1
                if (material.color.length == 3) {
                    vec3.copy(matColor, material.color);
                }
                else {
                    vec4.copy(matColor, material.color);
                }

                var nVertex = geometry.getVertexNumber();
                // Only support TRIANGLES, LINES, POINTS draw modes
                switch (renderable.mode) {
                    case glenum.TRIANGLES:
                        if (geometry.isUseFace()) {
                            var nFace = geometry.getFaceNumber();
                            for (var j = 0; j < nFace; j++) {
                                geometry.getFace(j, indices);

                                var triangle = trianglesPool.pick();
                                triangle.material = material;

                                var clipped = this._setPrimitive(triangle, indices, 3, attributes, worldViewProjMat, matColor);

                                if (! clipped) {
                                    primitives[nPrimitive++] = triangle;
                                }
                            }
                        }
                        else {
                            for (var j = 0; j < nVertex;) {
                                indices[0] = j++;
                                indices[1] = j++;
                                indices[2] = j++;

                                var triangle = trianglesPool.pick();
                                triangle.material = material;

                                var clipped = this._setPrimitive(triangle, indices, 3, attributes, worldViewProjMat, matColor);

                                if (! clipped) {
                                    primitives[nPrimitive++] = triangle;
                                }
                            }
                        }
                        break;
                    case glenum.LINES:
                        // LINES mode can't use face
                        for (var j = 0; j < nVertex;) {
                            indices[0] = j++;
                            indices[1] = j++;
                            var line = linesPool.pick();
                            line.material = material;
                            line.lineWidth = renderable.lineWidth;

                            var clipped = this._setPrimitive(line, indices, 2, attributes, worldViewProjMat, matColor);

                            if (! clipped) {
                                primitives[nPrimitive++] = line;
                            }
                        }
                        break;
                    case glenum.POINTS:
                        for (var j = 0; j < nVertex; j++) {
                            indices[0] = j;
                            var point = pointsPool.pick();
                            point.material = material;

                            var clipped = this._setPrimitive(point, indices, 1, attributes, worldViewProjMat, matColor);

                            if (! clipped) {
                                primitives[nPrimitive++] = point;
                            }
                        }
                        // POINTS mode can't use face
                        break;
                }
            }

            trianglesPool.shrink();
            linesPool.shrink();
            pointsPool.shrink();

            primitives.length = nPrimitive;

            primitives.sort(depthSortFunc);
            this._drawPrimitives(primitives);
        },

        _setPrimitive: (function () {
            var vertexColor = vec4Create();
            return function (primitive, indices, size, attributes, worldViewProjMat, matColor) {
                var colorAttrib = attributes.color;
                var useVertexColor = colorAttrib.value && colorAttrib.value.length > 0;
                var priColor = primitive.color;

                primitive.depth = 0;
                if (useVertexColor) {
                    vec4.set(priColor, 0, 0, 0, 0);
                }

                var clipped = true;

                var percent = 1 / size;
                for (var i = 0; i < size; i++) {
                    var coord = primitive.vertices[i];
                    attributes.position.get(indices[i], coord);
                    coord[3] = 1;
                    vec4.transformMat4(coord, coord, worldViewProjMat);
                    if (useVertexColor) {
                        colorAttrib.get(indices[i], vertexColor);
                        // Average vertex color
                        // Each primitive only call fill or stroke once
                        // So color must be the same
                        vec4.scaleAndAdd(priColor, priColor, vertexColor, percent);
                    }

                    // Clipping
                    var x = coord[0];
                    var y = coord[1];
                    var z = coord[2];
                    var w = coord[3];

                    // TODO Point clipping
                    if (x > -w && x < w && y > -w && y < w && z > -w && z < w) {
                        clipped = false;
                    }

                    var invW = 1 / w;
                    coord[0] = x * invW;
                    coord[1] = y * invW;
                    coord[2] = z * invW;
                    // Use primitive average depth;
                    primitive.depth += coord[2];
                }

                if (! clipped) {
                    primitive.depth /= 3;

                    if (useVertexColor) {
                        vec4.mul(priColor, priColor, matColor);
                    }
                    else {
                        vec4.copy(priColor, matColor);
                    }
                }

                return clipped;
            }
        })(),

        _drawPrimitives: function (primitives) {
            var ctx = this.ctx;
            ctx.save();

            var prevMaterial;

            var dpr = this.devicePixelRatio;
            var width = this._width * dpr;
            var height = this._height * dpr;
            var halfWidth = width / 2;
            var halfHeight = height / 2;

            var prevLineWidth;

            for (var i = 0; i < primitives.length; i++) {
                var primitive = primitives[i];
                var vertices = primitive.vertices;

                var primitiveType = primitive.type;
                var material = primitive.material;
                if (material !== prevMaterial) {
                    // Set material
                    ctx.globalAlpha = material.opacity;
                    prevMaterial = material;
                }

                var colorStr = vec4ToColorStr(primitive.color);
                switch (primitiveType) {
                    case PRIMITIVE_TRIANGLE:
                        var v0 = vertices[0];
                        var v1 = vertices[1];
                        var v2 = vertices[2];
                        ctx.fillStyle = colorStr;
                        ctx.beginPath();
                        ctx.moveTo((v0[0] + 1) * halfWidth, (-v0[1] + 1) * halfHeight);
                        ctx.lineTo((v1[0] + 1) * halfWidth, (-v1[1] + 1) * halfHeight);
                        ctx.lineTo((v2[0] + 1) * halfWidth, (-v2[1] + 1) * halfHeight);
                        ctx.closePath();
                        ctx.fill();
                        break;
                    case PRIMITIVE_LINE:
                        var v0 = vertices[0];
                        var v1 = vertices[1];
                        var lineWidth = primitive.lineWidth;
                        ctx.strokeStyle = colorStr;
                        if (lineWidth !== prevLineWidth) {
                            ctx.lineWidth = prevLineWidth = lineWidth;
                        }
                        ctx.beginPath();
                        ctx.moveTo((v0[0] + 1) * halfWidth, (-v0[1] + 1) * halfHeight);
                        ctx.lineTo((v1[0] + 1) * halfWidth, (-v1[1] + 1) * halfHeight);
                        ctx.stroke();
                        break;
                    case PRIMITIVE_POINT:
                        var pointSize = material.pointSize;
                        var pointShape = material.pointShape;
                        var halfSize = pointSize / 2;
                        if (pointSize > 0) {
                            var v0 = vertices[0];
                            var cx = (v0[0] + 1) * halfWidth;
                            var cy = (-v0[1] + 1) * halfHeight;

                            ctx.fillStyle = colorStr;
                            if (pointShape === 'rectangle') {
                                ctx.fillRect(cx - halfSize, cy - halfSize, pointSize, pointSize);
                            }
                            else if (pointShape === 'circle') {
                                ctx.beginPath();
                                ctx.arc(cx, cy, halfSize, 0, Math.PI * 2);
                                ctx.fill();
                            }
                        }
                        break;
                }
            }

            ctx.restore();
        },

        dispose: function () {
            this._triangles.clear();
            this._lines.clear();
            this._points.clear();
            this._primitives = [];

            this.ctx = null;
            this.canvas = null;
        }
    });

    return CanvasRenderer;
});<commit_msg>Canvas renderer: clear with dpr > 1, depth calc bug fix<commit_after>define(function (require) {

    var Base = require('../core/Base');
    var glMatrix = require('../dep/glmatrix');
    var glenum = require('../core/glenum');
    var mat4 = glMatrix.mat4;
    var vec3 = glMatrix.vec3;
    var vec4 = glMatrix.vec4;

    var vec3Set = vec3.set;
    var vec3Create = vec3.create;

    var vec4Create = vec4.create;

    var round = Math.round;

    var PRIMITIVE_TRIANGLE = 1;
    var PRIMITIVE_LINE = 2;
    var PRIMITIVE_POINT = 3;

    function PrimitivePool(constructor) {
        this.ctor = constructor;

        this._data = [];

        this._size = 0;
    }

    PrimitivePool.prototype = {
        pick: function () {
            var data = this._data;
            var size = this._size;
            var obj = data[size];
            if (! obj) {
                // Constructor must have no parameters
                obj = new this.ctor();
                data[size] = obj;
            }
            this._size++;
            return obj;
        },

        reset: function () {
            this._size = 0;
        },

        shrink: function () {
            this._data.length = this._size;
        },

        clear: function () {
            this._data = [];
            this._size = 0;
        }
    }

    function Triangle() {
        this.vertices = [vec4Create(), vec4Create(), vec4Create()];
        this.color = vec4Create();

        this.depth = 0;
    }

    Triangle.prototype.type = PRIMITIVE_TRIANGLE;

    function Point() {
        // Here use an array to make it more convinient to proccessing in _setPrimitive method
        this.vertices = [vec4Create()];

        this.color = vec4Create();

        this.depth = 0;
    }

    Point.prototype.type = PRIMITIVE_POINT;

    function Line() {
        this.vertices = [vec4Create(), vec4Create()];
        this.color = vec4Create();

        this.depth = 0;

        this.lineWidth = 1;
    }

    Line.prototype.type = PRIMITIVE_LINE;

    function depthSortFunc(x, y) {
        // Sort from far to near, which in depth of projection space is from larger to smaller
        return y.depth - x.depth;
    }

    function vec3ToColorStr(v3) {
        return 'rgb(' + round(v3[0] * 255) + ',' + round(v3[1] * 255) + ',' + round(v3[2] * 255) + ')';
    }

    function vec4ToColorStr(v4) {
        return 'rgba(' + round(v4[0] * 255) + ',' + round(v4[1] * 255) + ',' + round(v4[2] * 255) + ',' + v4[3] + ')';
    }

    var CanvasRenderer = Base.derive({

        canvas: null,

        _width: 100,

        _height: 100,

        devicePixelRatio: window.devicePixelRatio || 1.0,

        color: [0.0, 0.0, 0.0, 0.0],

        clear: true,

        ctx: null,

        // Cached primitive list, including triangle, line, point
        _primitives: [],

        // Triangle pool
        _triangles: new PrimitivePool(Triangle),

        // Line pool
        _lines: new PrimitivePool(Line),

        // Point pool
        _points: new PrimitivePool(Point)
    }, function () {
        if (! this.canvas) {
            this.canvas = document.createElement('canvas');
        }
        var canvas = this.canvas;

        try {
            this.ctx = canvas.getContext('2d');
            var ctx = this.ctx;
            if (! ctx) {
                throw new Error();
            }
        }
        catch (e) {
            throw 'Error creating WebGL Context ' + e;
        }

        this.resize();
    }, {

        resize: function (width, height) {
            var dpr = this.devicePixelRatio;
            var canvas = this.canvas;
            if (width != null) {
                canvas.style.width = width + 'px';
                canvas.style.height = height + 'px';
                canvas.width = width * dpr;
                canvas.height = height * dpr;

                this._width = width;
                this._height = height;
            }
            else {
                this._width = canvas.width / dpr;
                this._height = canvas.height / dpr;
            }
        },

        getWidth: function () {
            return this._width;
        },

        getHeight: function () {
            return this._height;
        },

        getViewportAspect: function () {
            return this._width / this._height;
        },

        render: function (scene, camera) {

            if (this.clear) {
                var color = this.color;
                var ctx = this.ctx;
                var dpr = this.devicePixelRatio;
                var w = this._width * dpr;
                var h = this._height * dpr;
                if (color && color[3] === 0) {
                    ctx.clearRect(0, 0, w, h);
                }
                else {
                    // Has transparency
                    if (color[3] < 1) {
                        ctx.clearRect(0, 0, w, h);
                    }
                    ctx.fillStyle = color.length === 4 ? vec4ToColorStr(color) : vec3ToColorStr(color);
                    ctx.fillRect(0, 0, w, h);
                }
            }

            scene.update();
            camera.update();

            var opaqueQueue = scene.opaqueQueue;
            var transparentQueue = scene.transparentQueue;
            var sceneMaterial = scene.material;

            var queue = opaqueQueue.concat(transparentQueue);

            this.renderQueue(queue, camera);
        },

        renderQueue: function (queue, camera) {
            var viewProj = mat4.create();
            mat4.multiply(viewProj, camera.projectionMatrix._array, camera.viewMatrix._array);
            var worldViewProjMat = mat4.create();
            var posViewSpace = vec3.create();

            var primitives = this._primitives;
            var trianglesPool = this._triangles;
            var linesPool = this._lines;
            var pointsPool = this._points;

            trianglesPool.reset();
            linesPool.reset();
            pointsPool.reset();

            var nPrimitive = 0;

            var indices = [0, 0, 0];
            var matColor = [];
            for (var i = 0; i < queue.length; i++) {
                var renderable = queue[i];

                mat4.multiply(worldViewProjMat, viewProj, renderable.worldTransform._array);

                var geometry = renderable.geometry;
                var material = renderable.material;
                var attributes = geometry.attributes;

                // alpha is default 1
                if (material.color.length == 3) {
                    vec3.copy(matColor, material.color);
                    matColor[3] = 1;
                }
                else {
                    vec4.copy(matColor, material.color);
                }

                var nVertex = geometry.getVertexNumber();
                // Only support TRIANGLES, LINES, POINTS draw modes
                switch (renderable.mode) {
                    case glenum.TRIANGLES:
                        if (geometry.isUseFace()) {
                            var nFace = geometry.getFaceNumber();
                            for (var j = 0; j < nFace; j++) {
                                geometry.getFace(j, indices);

                                var triangle = trianglesPool.pick();
                                triangle.material = material;

                                var clipped = this._setPrimitive(triangle, indices, 3, attributes, worldViewProjMat, matColor);

                                if (! clipped) {
                                    primitives[nPrimitive++] = triangle;
                                }
                            }
                        }
                        else {
                            for (var j = 0; j < nVertex;) {
                                indices[0] = j++;
                                indices[1] = j++;
                                indices[2] = j++;

                                var triangle = trianglesPool.pick();
                                triangle.material = material;

                                var clipped = this._setPrimitive(triangle, indices, 3, attributes, worldViewProjMat, matColor);

                                if (! clipped) {
                                    primitives[nPrimitive++] = triangle;
                                }
                            }
                        }
                        break;
                    case glenum.LINES:
                        // LINES mode can't use face
                        for (var j = 0; j < nVertex;) {
                            indices[0] = j++;
                            indices[1] = j++;
                            var line = linesPool.pick();
                            line.material = material;
                            line.lineWidth = renderable.lineWidth;

                            var clipped = this._setPrimitive(line, indices, 2, attributes, worldViewProjMat, matColor);

                            if (! clipped) {
                                primitives[nPrimitive++] = line;
                            }
                        }
                        break;
                    case glenum.POINTS:
                        for (var j = 0; j < nVertex; j++) {
                            indices[0] = j;
                            var point = pointsPool.pick();
                            point.material = material;

                            var clipped = this._setPrimitive(point, indices, 1, attributes, worldViewProjMat, matColor);

                            if (! clipped) {
                                primitives[nPrimitive++] = point;
                            }
                        }
                        // POINTS mode can't use face
                        break;
                }
            }

            trianglesPool.shrink();
            linesPool.shrink();
            pointsPool.shrink();

            primitives.length = nPrimitive;

            primitives.sort(depthSortFunc);
            this._drawPrimitives(primitives);
        },

        _setPrimitive: (function () {
            var vertexColor = vec4Create();
            return function (primitive, indices, size, attributes, worldViewProjMat, matColor) {
                var colorAttrib = attributes.color;
                var useVertexColor = colorAttrib.value && colorAttrib.value.length > 0;
                var priColor = primitive.color;

                primitive.depth = 0;
                if (useVertexColor) {
                    vec4.set(priColor, 0, 0, 0, 0);
                }

                var clipped = true;

                var percent = 1 / size;
                for (var i = 0; i < size; i++) {
                    var coord = primitive.vertices[i];
                    attributes.position.get(indices[i], coord);
                    coord[3] = 1;
                    vec4.transformMat4(coord, coord, worldViewProjMat);
                    if (useVertexColor) {
                        colorAttrib.get(indices[i], vertexColor);
                        // Average vertex color
                        // Each primitive only call fill or stroke once
                        // So color must be the same
                        vec4.scaleAndAdd(priColor, priColor, vertexColor, percent);
                    }

                    // Clipping
                    var x = coord[0];
                    var y = coord[1];
                    var z = coord[2];
                    var w = coord[3];

                    // TODO Point clipping
                    if (x > -w && x < w && y > -w && y < w && z > -w && z < w) {
                        clipped = false;
                    }

                    var invW = 1 / w;
                    coord[0] = x * invW;
                    coord[1] = y * invW;
                    coord[2] = z * invW;
                    // Use primitive average depth;
                    primitive.depth += coord[2];
                }

                if (! clipped) {
                    primitive.depth /= size;

                    if (useVertexColor) {
                        vec4.mul(priColor, priColor, matColor);
                    }
                    else {
                        vec4.copy(priColor, matColor);
                    }
                }

                return clipped;
            }
        })(),

        _drawPrimitives: function (primitives) {
            var ctx = this.ctx;
            ctx.save();

            var prevMaterial;

            var dpr = this.devicePixelRatio;
            var width = this._width * dpr;
            var height = this._height * dpr;
            var halfWidth = width / 2;
            var halfHeight = height / 2;

            var prevLineWidth;

            for (var i = 0; i < primitives.length; i++) {
                var primitive = primitives[i];
                var vertices = primitive.vertices;

                var primitiveType = primitive.type;
                var material = primitive.material;
                if (material !== prevMaterial) {
                    // Set material
                    ctx.globalAlpha = material.opacity;
                    prevMaterial = material;
                }

                var colorStr = vec4ToColorStr(primitive.color);
                switch (primitiveType) {
                    case PRIMITIVE_TRIANGLE:
                        var v0 = vertices[0];
                        var v1 = vertices[1];
                        var v2 = vertices[2];
                        ctx.fillStyle = colorStr;
                        ctx.beginPath();
                        ctx.moveTo((v0[0] + 1) * halfWidth, (-v0[1] + 1) * halfHeight);
                        ctx.lineTo((v1[0] + 1) * halfWidth, (-v1[1] + 1) * halfHeight);
                        ctx.lineTo((v2[0] + 1) * halfWidth, (-v2[1] + 1) * halfHeight);
                        ctx.closePath();
                        ctx.fill();
                        break;
                    case PRIMITIVE_LINE:
                        var v0 = vertices[0];
                        var v1 = vertices[1];
                        var lineWidth = primitive.lineWidth;
                        ctx.strokeStyle = colorStr;
                        if (lineWidth !== prevLineWidth) {
                            ctx.lineWidth = prevLineWidth = lineWidth;
                        }
                        ctx.beginPath();
                        ctx.moveTo((v0[0] + 1) * halfWidth, (-v0[1] + 1) * halfHeight);
                        ctx.lineTo((v1[0] + 1) * halfWidth, (-v1[1] + 1) * halfHeight);
                        ctx.stroke();
                        break;
                    case PRIMITIVE_POINT:
                        var pointSize = material.pointSize;
                        var pointShape = material.pointShape;
                        var halfSize = pointSize / 2;
                        if (pointSize > 0) {
                            var v0 = vertices[0];
                            var cx = (v0[0] + 1) * halfWidth;
                            var cy = (-v0[1] + 1) * halfHeight;

                            ctx.fillStyle = colorStr;
                            if (pointShape === 'rectangle') {
                                ctx.fillRect(cx - halfSize, cy - halfSize, pointSize, pointSize);
                            }
                            else if (pointShape === 'circle') {
                                ctx.beginPath();
                                ctx.arc(cx, cy, halfSize, 0, Math.PI * 2);
                                ctx.fill();
                            }
                        }
                        break;
                }
            }

            ctx.restore();
        },

        dispose: function () {
            this._triangles.clear();
            this._lines.clear();
            this._points.clear();
            this._primitives = [];

            this.ctx = null;
            this.canvas = null;
        }
    });

    return CanvasRenderer;
});<|endoftext|>


<commit_before>import {
  hiddenFromAT
, listensTo
, devices
} from '../util'

export default ctx => function (tagName, props) {
  const hidden      = hiddenFromAT(props)
  const button      = props.role === 'button'
  const onKeyDown   = listensTo(props, 'onKeyDown')

  // rule fails when the element is not hidden from aria,
  // has role="button" and no onKeyDownHandler
  const bad = !hidden && button && !onKeyDown

  if ( bad ) {
    ctx.report({
      msg: 'You have `role="button"` but did not define an `onKeyDown` handler. '
         + 'Add it, and have the "Space" key do the same thing as an `onClick` handler.'
    , url: 'https://www.w3.org/WAI/GL/wiki/Making_actions_keyboard_accessible_by_using_keyboard_event_handlers_with_WAI-ARIA_controls'
    , affects: [
        devices.keyboardOnly
      ]
    })
  }
}
<commit_msg>fix button-role space<commit_after>import {
  hiddenFromAT
, listensTo
, devices
, fn
} from '../util'

export default [{
  msg: 'You have `role="button"` but did not define an `onKeyDown` handler. '
     + 'Add it, and have the "Space" key do the same thing as an `onClick` handler.'
, url: 'https://www.w3.org/WAI/GL/wiki/Making_actions_keyboard_accessible_by_using_keyboard_event_handlers_with_WAI-ARIA_controls'
, affects: [
    devices.keyboardOnly
  ]
, test (tagName, props) {
    const hidden      = hiddenFromAT(props)
    const button      = props.role === 'button'
    const onKeyDown   = listensTo(props, 'onKeyDown')

    // rule passes when element is hidden,
    // has role='button' and has an onKeyDown prop
    return hidden || (button && onKeyDown)
  }
}]

import React from 'react'

export const pass = [{
  when: 'role="button" but there is an onKeyDown handler.'
, render: () =>

}, {
  when: 'there is no role'
, render: () =>

}, {
  when: 'there the role is not button'
, render: () =>

}, {
  when: 'the element is aria-hidden'
, render: () =>

}]

export const fail = [{
  when: 'role="button" and no `onKeyDown` is present'
, render: () =>

}]
<|endoftext|>


<commit_before>/**
 * Global things that never change, colors and keyframes
 */

import { keyframes } from 'styled-components';
import {DIRECTIONS} from './station';

export const colors = {
  darkGrey: '#232323',
  lightGrey: '#353535',
  white: '#ffffff',
  black: '#191919',
  red: '#c91f1b'
};

export const times = {
  pod: {
    moveIn: 3000,
    moveAround: 5000
  }
};
const screens = (num) => `${num * 100/7}vh`;

export const sizes = {
  pod: {
    width: '3em',
    height: '3em'
  },
  hub: {
    width: '40vw',
    height: screens(4)
  },
  list: {
    height: screens(1)
  },
  icon: {
    width: '1em',
    height: '1em'
  }
};

export const animations = {
  moveAround() {
    return keyframes`
      0%, 100% {
        transform:
          rotate(0)
          scale(1)
          translateY(-${Math.random()}vh);
      }

      50% {
        transform:
          rotate(0)
          scale(1)
          translateY(-${Math.random() + 2}vh);
      }
    `;
  },
  // todo: make this look better (#12)
  buzz() {
    return keyframes`
      0%, 100% {
        transform:
          scale(1)
          translateX(${Math.random()}vh)
          translateY(${Math.random()}vw);
      }

      50% {
        transform:
          scale(${Math.random() * (1.4 - 0.6) + 0.6})
          translateX(${Math.random()}vh)
          translateY(${Math.random()}vw);
      }
    `;
  },
}

export const zIndex = {
  list: 8,
  pod: {
    [DIRECTIONS.southwest]: 2,
    [DIRECTIONS.southeast]: 2,
    [DIRECTIONS.northwest]: 6,
    [DIRECTIONS.northeast]: 6,
  },
  hub: {
    south_front: 7,
    south_back: 5,
    jar: 4,
    north_front: 3,
    north_back: 1,
    platform: 0,
  }
}

export const API_BASE_URI = process.env.NODE_ENV === 'development' ? 'localhost:3001' : '/';
<commit_msg>add very light grey<commit_after>/**
 * Global things that never change, colors and keyframes
 */

import { keyframes } from 'styled-components';
import {DIRECTIONS} from './station';

export const colors = {
  darkGrey: '#232323',
  lightGrey: '#353535',
  veryLightGrey: '#b5b5b5',
  white: '#ffffff',
  black: '#191919',
  red: '#c91f1b'
};

export const times = {
  pod: {
    moveIn: 3000,
    moveAround: 5000
  }
};
const screens = (num) => `${num * 100/7}vh`;

export const sizes = {
  pod: {
    width: '3em',
    height: '3em'
  },
  hub: {
    width: '40vw',
    height: screens(4)
  },
  list: {
    height: screens(1),
    info: {
      width: '5vw'
    }
  },
  icon: {
    width: '1em',
    height: '1em'
  }
};

export const animations = {
  moveAround() {
    return keyframes`
      0%, 100% {
        transform:
          rotate(0)
          scale(1)
          translateY(-${Math.random()}vh);
      }

      50% {
        transform:
          rotate(0)
          scale(1)
          translateY(-${Math.random() + 2}vh);
      }
    `;
  },
  // todo: make this look better (#12)
  buzz() {
    return keyframes`
      0%, 100% {
        transform:
          scale(1)
          translateX(${Math.random()}vh)
          translateY(${Math.random()}vw);
      }

      50% {
        transform:
          scale(${Math.random() * (1.4 - 0.6) + 0.6})
          translateX(${Math.random()}vh)
          translateY(${Math.random()}vw);
      }
    `;
  },
}

export const zIndex = {
  list: 8,
  pod: {
    [DIRECTIONS.southwest]: 2,
    [DIRECTIONS.southeast]: 2,
    [DIRECTIONS.northwest]: 6,
    [DIRECTIONS.northeast]: 6,
  },
  hub: {
    south_front: 7,
    south_back: 5,
    jar: 4,
    north_front: 3,
    north_back: 1,
    platform: 0,
  }
}

export const API_BASE_URI = process.env.NODE_ENV === 'development' ? 'localhost:3001' : '/';
<|endoftext|>


<commit_before>'use strict';

let Response = require('../../tools/response');
let mongoose = require('mongoose');
let async = require('async');

module.exports = function(taskSchema){

    /*
     * Tools methods
     */
    taskSchema.statics.delete = function(params, callback) {
        mongoose.model('Task').find({_id: params.id}).remove(function(err, removed){
            if (err)
                callback(err);

            callback(null, removed);
        });
    };

    /*
     * Verification methods
     */
    function checkParametersForDelete(req, res, callback) {
        let parametersOK = false;

        if (!req.body || !req.body.id) {
            Response.missing(res, 'id', -11);
        } else {
            parametersOK = true;
        }

        /*
         * TODO: Check user perms to delete US
         */

        if (parametersOK) {
            callback();
        } else {
            callback({
                alreadySent: true
            });
        }
    }

    /*
     * Express calls
     */
    taskSchema.statics.exDelete = function (req, res) {
        async.waterfall([
            (next) => checkParametersForDelete(req, res, next),
            (next) => mongoose.model('Task').delete(req.body, next)
        ], (err, task) => {
            if (err && err.alreadySent)
                return;

            if (err)
                return Response.insertError(res, err);

            Response.success(res, 'Task deleted !', task);
        });
    };
};<commit_msg>fix(server): Fixing parameters names to respect format.<commit_after>'use strict';

let Response = require('../../tools/response');
let mongoose = require('mongoose');
let async = require('async');

module.exports = function(taskSchema){

    /*
     * Tools methods
     */
    taskSchema.statics.delete = function(params, callback) {
        mongoose.model('Task').find({_id: params._id}).remove(function(err, removed){
            if (err)
                callback(err);

            callback(null, removed);
        });
    };

    /*
     * Verification methods
     */
    function checkParametersForDelete(req, res, callback) {
        let parametersOK = false;

        if (!req.body || !req.body._id) {
            Response.missing(res, 'id', -11);
        } else {
            parametersOK = true;
        }

        /*
         * TODO: Check user perms to delete US
         */

        if (parametersOK) {
            callback();
        } else {
            callback({
                alreadySent: true
            });
        }
    }

    /*
     * Express calls
     */
    taskSchema.statics.exDelete = function (req, res) {
        async.waterfall([
            (next) => checkParametersForDelete(req, res, next),
            (next) => mongoose.model('Task').delete(req.body, next)
        ], (err, task) => {
            if (err && err.alreadySent)
                return;

            if (err)
                return Response.insertError(res, err);

            Response.success(res, 'Task deleted !', task);
        });
    };
};<|endoftext|>


<commit_before>enyo.kind(
	{
		name: "PreviewDevicePicker",
		kind: "onyx.Picker",
		components: [
			{content: "default",           value: { height:  800, width:  600, ppi: 163, dpr: 1 }, active: true},
			{content: "iPhone\u2122",      value: { height:  480, width:  320, ppi: 163, dpr: 1 }},
			{content: "iPhone\u2122 4",    value: { height:  960, width:  640, ppi: 326, dpr: 2 }},
			{content: "iPhone\u2122 5",    value: { height: 1136, width:  640, ppi: 326, dpr: 2 }},

			{content: "iPad\u2122 Retina", value: { width: 2048, height: 1536, ppi: 264, dpr: 2 }},
			{content: "iPad\u2122 2",      value: { width: 1024, height:  768, ppi: 132, dpr: 1 }},
			{content: "iPad\u2122 mini",   value: { width: 1024, height:  768, ppi: 163, dpr: 1 }}
		]
	}
);

enyo.kind(
	{
		name: "Preview",
		kind: "FittableColumns",
		classes: "enyo-fit enyo-border-box",
		style: "margin: 4px; background-color: #DDD",

		components: [
			{
				style: "width: 150px; margin: 4px" ,
				components: [
					{
						kind: 'onyx.Groupbox',
						style : "margin-top: 8px",
						components: [
							{kind: "onyx.GroupboxHeader", content: "Device"},
							{
								kind: "onyx.PickerDecorator",
								onSelect: "resize",
								style :"padding: 6px",
								components:
								[
									{style: "width: 100%"}, // A content-less PickerButton
									{
										kind: "PreviewDevicePicker", name: "device"
									}
								]
							},
							{content: "width: 600 px",  name: "devWidth",  style: "padding: 8px"},
							{content: "height: 800 px", name: "devHeight", style: "padding: 8px"},
							{content: "DPR: 1",        name: "devDPR",    style: "padding: 8px",
							 attributes: {title: "display pixel ratio"} }
						]
					},
					{tag: "br"},
					{
						kind: 'onyx.Groupbox',
						components: [
							{kind: "onyx.GroupboxHeader", content: "Screen"},
							{
								kind: "onyx.PickerDecorator",
								onSelect: "resize",
								style : "padding: 6px",
								components:
								[
									{style: "width: 100%"}, // A content-less PickerButton
									{
										kind: "onyx.Picker", name: "orientation",
										components: [
											{content: "portrait", active: true },
											{content: "landscape"              }
										]
									}
								]
							},
							{content: "width: 600 px",  name: "screenWidth",  style: "padding: 8px",
							 attributes: { title: "device width divided by DPR" }
							},
							{content: "height: 800 px", name: "screenHeight", style: "padding: 8px",
							 attributes: { title: "device height divided by DPR" }
							}
						]
					},
					{tag: "br"},
					{
						kind: 'onyx.Groupbox',
						components: [
							{kind: "onyx.GroupboxHeader", content: "Zoom"},
							{
								// padding required so the gray box is connected to groupbox
								style: "padding-top: 4px; padding-bottom: 4px",
								components: [
									{kind: "onyx.Slider", value: 100, onChange: 'zoom', onChanging: 'zoom' }
								]
							}
						]
					},
					{tag: "br"},
					{
						kind: "onyx.Button",
						ontap:"reload",
						style: "padding: 5px; width: 100%; margin-bottom: 5px",
						components: [
							{tag: 'img', attributes: { src: "assets/images/preview_reload.png"} }
						]
					},
					{tag: "br"},
					{
						kind:"onyx.Button",
						content: "Detach test",
						ontap:"detachIframe",
						style: "padding: 5px; width: 100%",
						attributes: { title: "detach test device, then right click to enable Ripple emulator"}
					}
				]
			},
			{
				name: 'scrolledIframe',
				fit: true,
				kind: "ares.ScrolledIFrame"
			}
		],

		debug: true ,
		iframeUrl: null,

		dlog: function() {
			if (this.debug) {
				this.log.apply(this, arguments) ;
			}
		},

		zoom: function(inSender, inEvent) {

			this.scale = 0.3 + 0.7 * inSender.getValue() / 100 ;
			this.applyScale() ;
		},
		applyScale: function() {
			enyo.dom.transformValue(
				this.$.scrolledIframe.$.iframe, "scale", this.scale
			) ;
			this.resized() ;
		},

		resize: function() {
			var device = this.$.device.selected ;
			var orientation = this .$.orientation.selected ;

			this.dlog("size for device " , device.content , " orientation " , orientation.content ) ;

			var dw  = device.value.width ;
			var dh  = device.value.height ;
			var dpr = device.value.dpr ;
			this.$.devWidth .setContent("width: "  + dw + ' px') ;
			this.$.devHeight.setContent("height: " + dh + ' px') ;
			this.$.devDPR   .setContent("DPR: "    + dpr) ;

			var swap = orientation.swap ;
			var targetW = ( swap ? dh : dw ) / dpr ;
			var targetH = ( swap ? dw : dh ) / dpr ;

			this.$.scrolledIframe.setGeometry( targetW , targetH) ;
			this.$.screenWidth .setContent("width: "  + targetW + 'px') ;
			this.$.screenHeight.setContent("height: " + targetH + 'px') ;
			this.resized() ;
		},

		getQueryParams: function(qs) {
			qs = qs.split("+").join(" ");

			var params = {}, tokens, re = /[?&]?([^=&]+)=?([^&]*)/g;

			while ((tokens = re.exec(qs))) {
				params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
			}

			return params;
		},

		// retrieve URL from window and setup iframe url
		create: function() {
			this.inherited(arguments);

			var param = this.getQueryParams(window.location.search) ;
			this.log("preview url " + param.url) ;
			this.iframeUrl = param.url ;

			this.$.scrolledIframe.setUrl   (param.url) ;
		},

		reload: function() {
			this.$.scrolledIframe.reload();
			this.applyScale() ;
		},

		detachIframe: function() {
			window.open(
				this.iframeUrl ,
				'_blank', // ensure that a new window is created each time preview is tapped
				'scrollbars=1,menubar=1',
				false
			);
			window.close();
		}
	}
);

<commit_msg>ENYO-2517: check screen size and requested aspect to decide to swap or not<commit_after>enyo.kind(
	{
		name: "PreviewDevicePicker",
		kind: "onyx.Picker",
		components: [
			{content: "default",           value: { height:  800, width:  600, ppi: 163, dpr: 1 }, active: true},
			{content: "iPhone\u2122",      value: { height:  480, width:  320, ppi: 163, dpr: 1 }},
			{content: "iPhone\u2122 4",    value: { height:  960, width:  640, ppi: 326, dpr: 2 }},
			{content: "iPhone\u2122 5",    value: { height: 1136, width:  640, ppi: 326, dpr: 2 }},

			{content: "iPad\u2122 Retina", value: { width: 2048, height: 1536, ppi: 264, dpr: 2 }},
			{content: "iPad\u2122 2",      value: { width: 1024, height:  768, ppi: 132, dpr: 1 }},
			{content: "iPad\u2122 mini",   value: { width: 1024, height:  768, ppi: 163, dpr: 1 }}
		]
	}
);

enyo.kind(
	{
		name: "Preview",
		kind: "FittableColumns",
		classes: "enyo-fit enyo-border-box",
		style: "margin: 4px; background-color: #DDD",

		components: [
			{
				style: "width: 150px; margin: 4px" ,
				components: [
					{
						kind: 'onyx.Groupbox',
						style : "margin-top: 8px",
						components: [
							{kind: "onyx.GroupboxHeader", content: "Device"},
							{
								kind: "onyx.PickerDecorator",
								onSelect: "resize",
								style :"padding: 6px",
								components:
								[
									{style: "width: 100%"}, // A content-less PickerButton
									{
										kind: "PreviewDevicePicker", name: "device"
									}
								]
							},
							{content: "width: 600 px",  name: "devWidth",  style: "padding: 8px"},
							{content: "height: 800 px", name: "devHeight", style: "padding: 8px"},
							{content: "DPR: 1",        name: "devDPR",    style: "padding: 8px",
							 attributes: {title: "display pixel ratio"} }
						]
					},
					{tag: "br"},
					{
						kind: 'onyx.Groupbox',
						components: [
							{kind: "onyx.GroupboxHeader", content: "Screen"},
							{
								kind: "onyx.PickerDecorator",
								onSelect: "resize",
								style : "padding: 6px",
								components:
								[
									{style: "width: 100%"}, // A content-less PickerButton
									{
										kind: "onyx.Picker", name: "orientation",
										components: [
											{content: "portrait", active: true },
											{content: "landscape"              }
										]
									}
								]
							},
							{content: "width: 600 px",  name: "screenWidth",  style: "padding: 8px",
							 attributes: { title: "device width divided by DPR" }
							},
							{content: "height: 800 px", name: "screenHeight", style: "padding: 8px",
							 attributes: { title: "device height divided by DPR" }
							}
						]
					},
					{tag: "br"},
					{
						kind: 'onyx.Groupbox',
						components: [
							{kind: "onyx.GroupboxHeader", content: "Zoom"},
							{
								// padding required so the gray box is connected to groupbox
								style: "padding-top: 4px; padding-bottom: 4px",
								components: [
									{kind: "onyx.Slider", value: 100, onChange: 'zoom', onChanging: 'zoom' }
								]
							}
						]
					},
					{tag: "br"},
					{
						kind: "onyx.Button",
						ontap:"reload",
						style: "padding: 5px; width: 100%; margin-bottom: 5px",
						components: [
							{tag: 'img', attributes: { src: "assets/images/preview_reload.png"} }
						]
					},
					{tag: "br"},
					{
						kind:"onyx.Button",
						content: "Detach test",
						ontap:"detachIframe",
						style: "padding: 5px; width: 100%",
						attributes: { title: "detach test device, then right click to enable Ripple emulator"}
					}
				]
			},
			{
				name: 'scrolledIframe',
				fit: true,
				kind: "ares.ScrolledIFrame"
			}
		],

		debug: true ,
		iframeUrl: null,

		dlog: function() {
			if (this.debug) {
				this.log.apply(this, arguments) ;
			}
		},

		zoom: function(inSender, inEvent) {

			this.scale = 0.3 + 0.7 * inSender.getValue() / 100 ;
			this.applyScale() ;
		},
		applyScale: function() {
			enyo.dom.transformValue(
				this.$.scrolledIframe.$.iframe, "scale", this.scale
			) ;
			this.resized() ;
		},

		resize: function() {
			var device = this.$.device.selected ;
			var orientation = this .$.orientation.selected ;

			this.dlog("size for device " , device.content , " orientation " , orientation.content ) ;

			var dw  = device.value.width ;
			var dh  = device.value.height ;
			var dpr = device.value.dpr ;
			this.$.devWidth .setContent("width: "  + dw + ' px') ;
			this.$.devHeight.setContent("height: " + dh + ' px') ;
			this.$.devDPR   .setContent("DPR: "    + dpr) ;

			// there's no logical xor in javascript. Emulate one :-/
			var wantWide = orientation.content === 'landscape' ;
			var isWide   = dw > dh ;
			var swap     = wantWide ^ isWide ; // bitwise xor works fine with boolean

			var targetW  = ( swap ? dh : dw ) / dpr ;
			var targetH  = ( swap ? dw : dh ) / dpr ;

			this.$.scrolledIframe.setGeometry( targetW , targetH) ;
			this.$.screenWidth .setContent("width: "  + targetW + 'px') ;
			this.$.screenHeight.setContent("height: " + targetH + 'px') ;
			this.resized() ;
		},

		getQueryParams: function(qs) {
			qs = qs.split("+").join(" ");

			var params = {}, tokens, re = /[?&]?([^=&]+)=?([^&]*)/g;

			while ((tokens = re.exec(qs))) {
				params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
			}

			return params;
		},

		// retrieve URL from window and setup iframe url
		create: function() {
			this.inherited(arguments);

			var param = this.getQueryParams(window.location.search) ;
			this.log("preview url " + param.url) ;
			this.iframeUrl = param.url ;

			this.$.scrolledIframe.setUrl   (param.url) ;
		},

		reload: function() {
			this.$.scrolledIframe.reload();
			this.applyScale() ;
		},

		detachIframe: function() {
			window.open(
				this.iframeUrl ,
				'_blank', // ensure that a new window is created each time preview is tapped
				'scrollbars=1,menubar=1',
				false
			);
			window.close();
		}
	}
);

<|endoftext|>


<commit_before>// ==UserScript==
// @name        GitHub-diff-whitespace
// @namespace   http://jason.karns.name
// @match       https://github.com/*/commit/*
// @match       https://github.com/*/pull/*
// @version     1
// ==/UserScript==

( function( querystring ){
  var querystringToObject = function( querystring ){
    var params = {};
    querystring.replace(
        new RegExp( '([^?=&]+)(=([^&]*))?', 'g' ),
        function( $0, $1, $2, $3 ) { params[ $1 ] = $3; }
    );
    return params;
  };

  var objectToQueryString = function( params ){
    var values = [];
    for( param in params ){
      var value = ( params[ param ] == null ? '' : params[ param ] );
      values.push( encodeURIComponent( param ) + '=' + encodeURIComponent( value ) )
    }
    return values.join( '&' ).replace( /%20/g, '+' );
  };

  var toggleW = function( params, whitespace ){
    if( whitespace ){
      delete params.w;
    }
    else {
      params.w = true;
    }
    return params;
  };

  var addWhitespaceToggleButton = function( button_group, querystring ){
    var a = document.createElement( 'a' )
    a.className = button_group.querySelector( 'a' ).className;
    a.href = '?' + querystring;
    a.title = 'Toggle Whitespace';
    a.textContent = '\u2423 \u2422';

    var li = document.createElement( 'li' )
    li.appendChild( a );

    button_group.insertBefore( li, button_group.firstChild );
  }

  var addWhitespaceToggleButtons = function( querystring ){
    Array.prototype.forEach.call(
      document.querySelectorAll( '.diff-view .actions .button-group' ),
      function( button_group, index, button_groups ){
        addWhitespaceToggleButton( button_group, querystring );
      }
    );
  };

  var params = querystringToObject( querystring );
  var whitespace = Boolean(params.w);
  querystring = objectToQueryString( toggleW( params, whitespace ) );
  addWhitespaceToggleButtons( querystring );

})( location.search );
<commit_msg>use the open box, not the slash-b character<commit_after>// ==UserScript==
// @name        GitHub-diff-whitespace
// @namespace   http://jason.karns.name
// @match       https://github.com/*/commit/*
// @match       https://github.com/*/pull/*
// @version     1
// ==/UserScript==

( function( querystring ){
  var querystringToObject = function( querystring ){
    var params = {};
    querystring.replace(
        new RegExp( '([^?=&]+)(=([^&]*))?', 'g' ),
        function( $0, $1, $2, $3 ) { params[ $1 ] = $3; }
    );
    return params;
  };

  var objectToQueryString = function( params ){
    var values = [];
    for( param in params ){
      var value = ( params[ param ] == null ? '' : params[ param ] );
      values.push( encodeURIComponent( param ) + '=' + encodeURIComponent( value ) )
    }
    return values.join( '&' ).replace( /%20/g, '+' );
  };

  var toggleW = function( params, whitespace ){
    if( whitespace ){
      delete params.w;
    }
    else {
      params.w = true;
    }
    return params;
  };

  var addWhitespaceToggleButton = function( button_group, querystring ){
    var a = document.createElement( 'a' )
    a.className = button_group.querySelector( 'a' ).className;
    a.href = '?' + querystring;
    a.title = 'Toggle Whitespace';
    a.textContent = ' \u2423 ';

    var li = document.createElement( 'li' )
    li.appendChild( a );

    button_group.insertBefore( li, button_group.firstChild );
  }

  var addWhitespaceToggleButtons = function( querystring ){
    Array.prototype.forEach.call(
      document.querySelectorAll( '.diff-view .actions .button-group' ),
      function( button_group, index, button_groups ){
        addWhitespaceToggleButton( button_group, querystring );
      }
    );
  };

  var params = querystringToObject( querystring );
  var whitespace = Boolean(params.w);
  querystring = objectToQueryString( toggleW( params, whitespace ) );
  addWhitespaceToggleButtons( querystring );

})( location.search );
<|endoftext|>