<commit_before>'use strict';

var del = require('del');
var gulp = require('gulp');
var autoprefixer = require('gulp-autoprefixer');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var sourcemaps = require('gulp-sourcemaps');
var cssnano = require('gulp-cssnano');
var postcss = require('gulp-postcss');
var stylefmt = require('gulp-stylefmt');
var sorting = require('postcss-sorting');
var torem = require('postcss-pxtorem');
var sortOrder = require('./.postcss-sorting.json');
var pkg = require('./package.json');

// Config
var build = {
	css: './dist/assets/css',
	docs: './docs/_media/',
	scss: './src/scss/'
};

var AUTOPREFIXER_BROWSERS = [
	'ie >= 11',
	'edge >= 12',
	'ff >= 38',
	'chrome >= 35',
	'safari >= 8',
	'opera >= 35',
	'ios >= 8'
];

gulp.task('css', function () {
	var css = gulp
	.src(build.scss + '*.scss')
	.pipe(sourcemaps.init())
	.pipe(sass({
		indentType: 'tab',
		indentWidth: 1,
		outputStyle: 'expanded',
		precision: 10,
		onError: console.error.bind(console, 'Sass error:')
	}))
	.pipe(autoprefixer(AUTOPREFIXER_BROWSERS))
	.pipe(
		postcss([
			sorting(sortOrder),
			torem({
				rootValue: 16,
				unitPrecision: 7,
				propWhiteList: [
					'font',
					'font-size',
					'margin',
					'margin-left',
					'margin-right',
					'margin-top',
					'margin-bottom',
					'padding',
					'padding-left',
					'padding-right',
					'padding-top',
					'padding-bottom'],
				selectorBlackList: [],
				replace: true,
				mediaQuery: false,
				minPixelValue: 0
			})
		])
	)
	.pipe(stylefmt())
	.pipe(rename({
		suffix: '.' + pkg.version,
		extname: '.css'
	}))
	.pipe(sourcemaps.write('./'))
	.pipe(gulp.dest(build.css));

	return css;
});

gulp.task('clean', function () {
	del(['dist']);
});

gulp.task('minify', ['css'], function () {
	var css = gulp
	.src(build.css + '/*.' + pkg.version + '.css')
	.pipe(sourcemaps.init())
	.pipe(cssnano())
	.pipe(rename({
		suffix: '.min',
		extname: '.css'
	}))
	.pipe(sourcemaps.write('./'))
	.pipe(gulp.dest(build.css));

	return css;
});

gulp.task('docs:css', function () {
	var css = gulp
	.src(build.docs + '*.scss')
	.pipe(sourcemaps.init())
	.pipe(sass({
		indentType: 'tab',
		indentWidth: 1,
		outputStyle: 'expanded',
		precision: 10,
		onError: console.error.bind(console, 'Sass error:')
	}))
	.pipe(autoprefixer(AUTOPREFIXER_BROWSERS))
	.pipe(
		postcss([
			sorting(sortOrder),
			torem({
				rootValue: 16,
				unitPrecision: 7,
				propWhiteList: [
					'font',
					'font-size',
					'margin',
					'margin-left',
					'margin-right',
					'margin-top',
					'margin-bottom',
					'padding',
					'padding-left',
					'padding-right',
					'padding-top',
					'padding-bottom'],
				selectorBlackList: [],
				replace: true,
				mediaQuery: false,
				minPixelValue: 0
			})
		])
	)
	.pipe(stylefmt())
	.pipe(cssnano())
	.pipe(rename({
		suffix: '.' + pkg.version + '.min',
		extname: '.css'
	}))
	.pipe(sourcemaps.write('./'))
	.pipe(gulp.dest(build.docs));

	return css;
});

gulp.task('setup:settings', function () {
	var settings = gulp
	.src('node_modules/base-l.settings/*.scss')
	.pipe(gulp.dest('src/scss/settings/'));

	return settings;
});

gulp.task('setup:mixins', function () {
	var mixins = gulp
		.src('node_modules/base-l.tools/mixin/*.scss')
		.pipe(gulp.dest('src/scss/tools/mixin/'));

	return mixins;
});

gulp.task('setup:functions', function () {
	var funcitons = gulp
		.src('node_modules/base-l.tools/function/*.scss')
		.pipe(gulp.dest('src/scss/tools/funciton/'));

	return funcitons;
});

gulp.task('watch', function () {
	gulp.watch('src/scss/**/*.scss', ['css', 'minify']);
	gulp.watch('docs/_media/*.scss', ['docs:css']);
});

gulp.task('setup', ['setup:settings', 'setup:mixins', 'setup:functions']);
gulp.task('serve', ['watch']);
gulp.task('default', ['css', 'minify', 'watch']);
<commit_msg>spelled function incorectly<commit_after>'use strict';

var del = require('del');
var gulp = require('gulp');
var autoprefixer = require('gulp-autoprefixer');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var sourcemaps = require('gulp-sourcemaps');
var cssnano = require('gulp-cssnano');
var postcss = require('gulp-postcss');
var stylefmt = require('gulp-stylefmt');
var sorting = require('postcss-sorting');
var torem = require('postcss-pxtorem');
var sortOrder = require('./.postcss-sorting.json');
var pkg = require('./package.json');

// Config
var build = {
	css: './dist/assets/css',
	docs: './docs/_media/',
	scss: './src/scss/'
};

var AUTOPREFIXER_BROWSERS = [
	'ie >= 11',
	'edge >= 12',
	'ff >= 38',
	'chrome >= 35',
	'safari >= 8',
	'opera >= 35',
	'ios >= 8'
];

gulp.task('css', function () {
	var css = gulp
	.src(build.scss + '*.scss')
	.pipe(sourcemaps.init())
	.pipe(sass({
		indentType: 'tab',
		indentWidth: 1,
		outputStyle: 'expanded',
		precision: 10,
		onError: console.error.bind(console, 'Sass error:')
	}))
	.pipe(autoprefixer(AUTOPREFIXER_BROWSERS))
	.pipe(
		postcss([
			sorting(sortOrder),
			torem({
				rootValue: 16,
				unitPrecision: 7,
				propWhiteList: [
					'font',
					'font-size',
					'margin',
					'margin-left',
					'margin-right',
					'margin-top',
					'margin-bottom',
					'padding',
					'padding-left',
					'padding-right',
					'padding-top',
					'padding-bottom'],
				selectorBlackList: [],
				replace: true,
				mediaQuery: false,
				minPixelValue: 0
			})
		])
	)
	.pipe(stylefmt())
	.pipe(rename({
		suffix: '.' + pkg.version,
		extname: '.css'
	}))
	.pipe(sourcemaps.write('./'))
	.pipe(gulp.dest(build.css));

	return css;
});

gulp.task('clean', function () {
	del(['dist']);
});

gulp.task('minify', ['css'], function () {
	var css = gulp
	.src(build.css + '/*.' + pkg.version + '.css')
	.pipe(sourcemaps.init())
	.pipe(cssnano())
	.pipe(rename({
		suffix: '.min',
		extname: '.css'
	}))
	.pipe(sourcemaps.write('./'))
	.pipe(gulp.dest(build.css));

	return css;
});

gulp.task('docs:css', function () {
	var css = gulp
	.src(build.docs + '*.scss')
	.pipe(sourcemaps.init())
	.pipe(sass({
		indentType: 'tab',
		indentWidth: 1,
		outputStyle: 'expanded',
		precision: 10,
		onError: console.error.bind(console, 'Sass error:')
	}))
	.pipe(autoprefixer(AUTOPREFIXER_BROWSERS))
	.pipe(
		postcss([
			sorting(sortOrder),
			torem({
				rootValue: 16,
				unitPrecision: 7,
				propWhiteList: [
					'font',
					'font-size',
					'margin',
					'margin-left',
					'margin-right',
					'margin-top',
					'margin-bottom',
					'padding',
					'padding-left',
					'padding-right',
					'padding-top',
					'padding-bottom'],
				selectorBlackList: [],
				replace: true,
				mediaQuery: false,
				minPixelValue: 0
			})
		])
	)
	.pipe(stylefmt())
	.pipe(cssnano())
	.pipe(rename({
		suffix: '.' + pkg.version + '.min',
		extname: '.css'
	}))
	.pipe(sourcemaps.write('./'))
	.pipe(gulp.dest(build.docs));

	return css;
});

gulp.task('setup:settings', function () {
	var settings = gulp
	.src('node_modules/base-l.settings/*.scss')
	.pipe(gulp.dest('src/scss/settings/'));

	return settings;
});

gulp.task('setup:mixins', function () {
	var mixins = gulp
		.src('node_modules/base-l.tools/mixin/*.scss')
		.pipe(gulp.dest('src/scss/tools/mixin/'));

	return mixins;
});

gulp.task('setup:functions', function () {
	var funcitons = gulp
		.src('node_modules/base-l.tools/function/*.scss')
		.pipe(gulp.dest('src/scss/tools/function/'));

	return funcitons;
});

gulp.task('watch', function () {
	gulp.watch('src/scss/**/*.scss', ['css', 'minify']);
	gulp.watch('docs/_media/*.scss', ['docs:css']);
});

gulp.task('setup', ['setup:settings', 'setup:mixins', 'setup:functions']);
gulp.task('serve', ['watch']);
gulp.task('default', ['css', 'minify', 'watch']);
<|endoftext|>


<commit_before>CarsController = RouteController.extend({

  // A place to put your subscriptions
  // this.subscribe('items');
  // // add the subscription to the waitlist
  // this.subscribe('item', this.params._id).wait();

  subscriptions: function() {
  },

  // Subscriptions or other things we want to "wait" on. This also
  // automatically uses the loading hook. That's the only difference between
  // this option and the subscriptions option above.
  // return Meteor.subscribe('post', this.params._id);

  waitOn: function () {
  },

  // A data function that can be used to automatically set the data context for
  // our layout. This function can also be used by hooks and plugins. For
  // example, the "dataNotFound" plugin calls this function to see if it
  // returns a null value, and if so, renders the not found template.
  // return Posts.findOne({_id: this.params._id});

  data: function () {
  },

  // You can provide any of the hook options

  onRun: function () {
    this.next();
  },
  onRerun: function () {
    this.next();
  },
  onBeforeAction: function () {
    this.next();
  },

  // The same thing as providing a function as the second parameter. You can
  // also provide a string action name here which will be looked up on a Controller
  // when the route runs. More on Controllers later. Note, the action function
  // is optional. By default a route will render its template, layout and
  // regions automatically.
  // Example:
  //  action: 'myActionFunction'

  action: function () {
    this.render();
  },
  onAfterAction: function () {
  },
  onStop: function () {
  }
});
<<<<<<< HEAD
=======

CarsController = RouteController.extend({
  subscriptions: function () {
    this.subscribe('cars');
  },
  data: function () {
  },
  create: function() {
    this.render('CreateCar', {});
  }
});

>>>>>>> testing
<commit_msg>Fix conflict<commit_after>CarsController = RouteController.extend({

  // A place to put your subscriptions
  // this.subscribe('items');
  // // add the subscription to the waitlist
  // this.subscribe('item', this.params._id).wait();

  subscriptions: function() {
  },

  // Subscriptions or other things we want to "wait" on. This also
  // automatically uses the loading hook. That's the only difference between
  // this option and the subscriptions option above.
  // return Meteor.subscribe('post', this.params._id);

  waitOn: function () {
  },

  // A data function that can be used to automatically set the data context for
  // our layout. This function can also be used by hooks and plugins. For
  // example, the "dataNotFound" plugin calls this function to see if it
  // returns a null value, and if so, renders the not found template.
  // return Posts.findOne({_id: this.params._id});

  data: function () {
  },

  // You can provide any of the hook options

  onRun: function () {
    this.next();
  },
  onRerun: function () {
    this.next();
  },
  onBeforeAction: function () {
    this.next();
  },

  // The same thing as providing a function as the second parameter. You can
  // also provide a string action name here which will be looked up on a Controller
  // when the route runs. More on Controllers later. Note, the action function
  // is optional. By default a route will render its template, layout and
  // regions automatically.
  // Example:
  //  action: 'myActionFunction'

  action: function () {
    this.render();
  },
  onAfterAction: function () {
  },
  onStop: function () {
  }
});

CarsController = RouteController.extend({
  subscriptions: function () {
    this.subscribe('cars');
  },
  data: function () {
  },
  create: function() {
    this.render('CreateCar', {});
  }
});

<|endoftext|>


<commit_before>'use strict';

/**
 * @module dhsniem
 *
 * @description
 * Main module of the application.
 */
angular
  .module('dhsniem', [
    'ui.router',
    'ui.bootstrap',
    'ngAria'
  ])
  .config(function ($urlRouterProvider) {
    $urlRouterProvider.when('', '/'); // redirect to root if the state is ''
    $urlRouterProvider.otherwise('/'); // redirect to root if state is not found
  })

  .run(function ($rootScope, $window, $location) {
    // $window.ga('create', 'UA-27432921-1', 'auto');
    $rootScope.$on('$stateChangeSuccess', function () {
      $window.scroll(0, 0);
      // $window.ga('send', 'pageview', $location.url());
    });
  });

<commit_msg>added back ga scripts<commit_after>'use strict';

/**
 * @module dhsniem
 *
 * @description
 * Main module of the application.
 */
angular
  .module('dhsniem', [
    'ui.router',
    'ui.bootstrap',
    'ngAria'
  ])
  .config(function ($urlRouterProvider) {
    $urlRouterProvider.when('', '/'); // redirect to root if the state is ''
    $urlRouterProvider.otherwise('/'); // redirect to root if state is not found
  })

  .run(function ($rootScope, $window, $location) {
    $window.ga('create', 'UA-27432921-1', 'auto');
    $rootScope.$on('$stateChangeSuccess', function () {
      $window.scroll(0, 0);
      $window.ga('send', 'pageview', $location.url());
    });
  });

<|endoftext|>


<commit_before>export default /* glsl */`
#ifdef USE_FOG

	#ifdef FOG_EXP2

		float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );

	#else

		float fogFactor = smoothstep( fogNear, fogFar, fogDepth );

	#endif

	gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );

#endif
`;
<commit_msg>Simplify FOG_EXP2 shader code<commit_after>export default /* glsl */`
#ifdef USE_FOG

	#ifdef FOG_EXP2

		float fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth ) );

	#else

		float fogFactor = smoothstep( fogNear, fogFar, fogDepth );

	#endif

	gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );

#endif
`;
<|endoftext|>


<commit_before>/**
 * Welcome to Pebble.js!
 *
 * This is where you write your app.
 */

var UI = require('ui');
var Vector2 = require('vector2');

var main = new UI.Card({
  title: 'Pebble.js',
  icon: 'images/menu_icon.png',
  subtitle: 'Hello World!',
  body: 'Press any button.'
});

main.show();

main.on('click', 'up', function(e) {
  var menu = new UI.Menu({
    sections: [{
      items: [{
        title: 'Pebble.js',
        icon: 'images/menu_icon.png',
        subtitle: 'Can do Menus'
      }, {
        title: 'Second Item',
        subtitle: 'Subtitle Text'
      }]
    }]
  });
  menu.on('select', function(e) {
    console.log('Selected item #' + e.itemIndex + ' of section #' + e.sectionIndex);
    console.log('The item is titled "' + e.item.title + '"');
  });
  menu.show();
});

main.on('click', 'select', function(e) {
  var wind = new UI.Window();
  var textfield = new UI.Text({
    position: new Vector2(0, 50),
    size: new Vector2(144, 30),
    font: 'gothic-24-bold',
    text: 'Text Anywhere!',
    textAlign: 'center'
  });
  wind.add(textfield);
  wind.show();
});

main.on('click', 'down', function(e) {
  var card = new UI.Card();
  card.title('A Card');
  card.subtitle('Is a Window');
  card.body('The simplest window type in Pebble.js.');
  card.show();
});
<commit_msg>Remove Default Code<commit_after>/**
 * Welcome to Pebble.js!
 *
 * This is where you write your app.
 */

var UI = require('ui');

var main = new UI.Card({
  title: 'PebblePanic',
  icon: 'images/menu_icon.png',
  subtitle: 'vDev',
  body: 'Press UP for ambulance /nPress Select to text contacts /nPress Down for Fire/Police'
});

main.show();

main.on('click', 'up', function(e) {
  var card = new UI.Card();
  card.title('A Card');
  card.subtitle('Is a Window');
  card.body('The simplest window type in Pebble.js.');
  card.show();
});

main.on('click', 'select', function(e) {
  var card = new UI.Card();
  card.title('A Card');
  card.subtitle('Is a Window');
  card.body('The simplest window type in Pebble.js.');
  card.show();
});

main.on('click', 'down', function(e) {
  var card = new UI.Card();
  card.title('A Card');
  card.subtitle('Is a Window');
  card.body('The simplest window type in Pebble.js.');
  card.show();
});
<|endoftext|>


<commit_before>import { Socket } from 'phoenix';
import Raven from 'raven-js';
import listenStoreChanges from '../listenStoreChanges';
import { logDebug } from '../logging';
import { CONFIG } from '../constants';
import {
  connect,
  logMessage,
  connectionClosed,
  authFailed,
  assignWork,
  workFinished,
  checkState,
  setPluginVersion,
  channelLeft,
  reloadPlugin,
  updateWorkerState,
  notify,
} from '../actions';

const AUTO_RECONNECT_TIMEOUT = 60 * 1000;
const READY_RETRY_TIMEOUT = 60 * 1000;
const READY_RETRY_PERIOD = 10 * 1000;

export const startSocket = (store, socketConstructor = Socket) => {
  let socket = null;
  let channel = null;
  let disconnectedAt = null;
  let readyRetryStartedAt = null;
  let readyRetryTimer = null;

  const clearReadyRetry = () => {
    clearTimeout(readyRetryTimer);
    readyRetryStartedAt = null;
    readyRetryTimer = null;
  };

  const pushWorkerState = (state, retryOnFail = false) => {
    if (!channel) {
      // Channel hasn't been joined, but it's OK.
      return;
    }

    if (!retryOnFail && readyRetryTimer) {
      // There was a previous attempt at automatically retrying; cancel it
      // because we manually changed state.
      clearReadyRetry();
    }

    channel.push('update_state', { worker_state: state })
      .receive('already_ready', () => {
        if (retryOnFail) {
          // In this case, we're automatically reconnecting so it's unlikely
          // that there are actually multiple connections and more likely that
          // there's a "zombie" connection on the server. So we retry for a
          // while (long enough for zombie connections to timeout) and then move
          // to "inactive" without a notification.
          if (!readyRetryStartedAt) {
            readyRetryStartedAt = Date.now();
          }
          if (Date.now() - readyRetryStartedAt > READY_RETRY_TIMEOUT) {
            const uuid = store.getState().worker.get('uuid');
            Raven.captureException(new Error('Worker timed out moving to "ready" state'), {
              extra: { worker_uuid: uuid },
            });
            clearReadyRetry();
            store.dispatch(updateWorkerState('inactive'));
          } else {
            readyRetryTimer = setTimeout(() => pushWorkerState('ready', true), READY_RETRY_PERIOD);
          }
        } else {
          store.dispatch(updateWorkerState('inactive'));
          store.dispatch(notify('doubleReady'));
        }
      });
  };

  const workerState = () => store.getState().worker.get('state');

  const handleAssignWork = (payload) => {
    if (workerState() === 'ready') {
      store.dispatch(assignWork(payload));
    } else {
      channel.push(
        'work_rejected',
        { reason: 'invalid_worker_state', worker_state: workerState() }
      );
    }
  };

  const handleWorkFinished = () => {
    store.dispatch(workFinished());
  };

  const handleCheckVersion = ({ version }) => {
    store.dispatch(setPluginVersion(version));
  };

  const handleCheckState = ({ worker_state: state }) => {
    if (!(['working', 'inactive', 'ready'].includes(state))) {
      throw new Error(`Unrecognized state for check_state message: ${state}`);
    }

    store.dispatch(checkState(state));
    const currentState = store.getState().worker.get('state');
    if (currentState !== state) {
      pushWorkerState(currentState);
    }
  };

  const handleReload = () => {
    store.dispatch(reloadPlugin());
  };

  const handleLeave = () => {
    if (!channel) {
      throw new Error("Leaving a channel when channel isn't joined");
    }

    channel.leave();
    channel = null;
    store.dispatch(channelLeft());
    socket.disconnect();
  };

  const joinLobby = () => {
    const lobby = socket.channel('workers:lobby');
    lobby.on('reload', handleReload);
    lobby.join().receive('ok', resp => {
      logDebug('Joined lobby successfully', resp);
    }).receive('error', resp => {
      throw new Error(`Error joining lobby: ${resp}`);
    });
  };

  const connectToSocket = ({ socket: socketState, worker }) => {
    const workerUUID = worker.get('uuid');
    const socketAuth = socketState.get('auth');
    const SocketConstructor = socketConstructor;

    socket = new SocketConstructor(CONFIG.socketURL, {
      params: socketAuth.toObject(),
      logger: (kind, msg, data) => {
        let payload;
        try {
          payload = JSON.stringify(data);
        } catch (ex) {
          if (ex instanceof TypeError) {
            payload = '<binary>';
          } else {
            throw ex;
          }
        }
        const log = `${kind}: ${msg} ${payload}`;
        store.dispatch(logMessage(log));
      },
    });
    socket.onClose(() => {
      disconnectedAt = Date.now();
      clearReadyRetry();
      store.dispatch(connectionClosed());
    });
    socket.connect();

    channel = socket.channel(`workers:${workerUUID}`);
    channel.on('assign_work', handleAssignWork);
    channel.on('work_finished', handleWorkFinished);
    channel.on('check_version', handleCheckVersion);
    channel.on('check_state', handleCheckState);
    channel.on('reload', handleReload);
    channel.on('leave', handleLeave);
    channel.join()
      .receive('ok', resp => {
        disconnectedAt = null;
        pushWorkerState(workerState(), true);
        store.dispatch(connect(resp));
        // We only want to join the lobby if the actual channel connection was
        // successful
        joinLobby();
      }).receive('error', resp => store.dispatch(authFailed(resp)));
  };

  const reconnectSocket = (state) => {
    if (!socket) {
      throw Error('reconnectSocket called without a current socket');
    }

    socket.disconnect();
    socket = null;
    disconnectedAt = null;
    connectToSocket(state);
  };

  const shouldConnect = ({ socket: socketState, worker }) => {
    const currentState = socketState.get('state');
    return socket === null &&
      socketState.get('auth') !== null &&
      (currentState === 'unconnected' || currentState === 'unauthenticated') &&
      worker.get('uuid') !== null;
  };

  const shouldReconnect = (
    { worker: prevWorker, socket: prevSocket }, { worker: curWorker, socket: curSocket }
  ) => {
    if (prevSocket.get('state') !== 'reconnecting' && curSocket.get('state') === 'reconnecting') {
      return true;
    }

    if (disconnectedAt &&
        curSocket.get('state') === 'unconnected' &&
        (Date.now() - disconnectedAt > AUTO_RECONNECT_TIMEOUT)) {
      // If it's been a while since we disconnected, it's possible that the
      // auto-reconnect has failed so we try to manually reconnect.
      return true;
    }

    const prevUUID = prevWorker.get('uuid');
    const curUUID = curWorker.get('uuid');
    if (socket && prevUUID && curUUID && prevUUID !== curUUID) {
      return true;
    }

    return false;
  };

  const handleWorkerState = (previousState, currentState) => {
    const oldState = previousState.worker.get('state');
    const newState = currentState.worker.get('state');

    if (oldState !== newState) {
      pushWorkerState(newState);
    }
  };

  const handleUpdate = (previousState, currentState) => {
    if (shouldConnect(currentState)) {
      connectToSocket(currentState);
    } else if (shouldReconnect(previousState, currentState)) {
      reconnectSocket(currentState);
    }
    handleWorkerState(previousState, currentState);
  };

  const getSocket = () => socket;

  listenStoreChanges(store, handleUpdate);
  if (!store.getState().socket.get('auth')) {
    store.dispatch(authFailed('No credentials'));
  }

  return {
    getSocket,
  };
};
<commit_msg>RF-17247 Add some more useful debugging for lobby join error<commit_after>import { Socket } from 'phoenix';
import Raven from 'raven-js';
import listenStoreChanges from '../listenStoreChanges';
import { logDebug } from '../logging';
import { CONFIG } from '../constants';
import {
  connect,
  logMessage,
  connectionClosed,
  authFailed,
  assignWork,
  workFinished,
  checkState,
  setPluginVersion,
  channelLeft,
  reloadPlugin,
  updateWorkerState,
  notify,
} from '../actions';

const AUTO_RECONNECT_TIMEOUT = 60 * 1000;
const READY_RETRY_TIMEOUT = 60 * 1000;
const READY_RETRY_PERIOD = 10 * 1000;

export const startSocket = (store, socketConstructor = Socket) => {
  let socket = null;
  let channel = null;
  let disconnectedAt = null;
  let readyRetryStartedAt = null;
  let readyRetryTimer = null;

  const clearReadyRetry = () => {
    clearTimeout(readyRetryTimer);
    readyRetryStartedAt = null;
    readyRetryTimer = null;
  };

  const pushWorkerState = (state, retryOnFail = false) => {
    if (!channel) {
      // Channel hasn't been joined, but it's OK.
      return;
    }

    if (!retryOnFail && readyRetryTimer) {
      // There was a previous attempt at automatically retrying; cancel it
      // because we manually changed state.
      clearReadyRetry();
    }

    channel.push('update_state', { worker_state: state })
      .receive('already_ready', () => {
        if (retryOnFail) {
          // In this case, we're automatically reconnecting so it's unlikely
          // that there are actually multiple connections and more likely that
          // there's a "zombie" connection on the server. So we retry for a
          // while (long enough for zombie connections to timeout) and then move
          // to "inactive" without a notification.
          if (!readyRetryStartedAt) {
            readyRetryStartedAt = Date.now();
          }
          if (Date.now() - readyRetryStartedAt > READY_RETRY_TIMEOUT) {
            const uuid = store.getState().worker.get('uuid');
            Raven.captureException(new Error('Worker timed out moving to "ready" state'), {
              extra: { worker_uuid: uuid },
            });
            clearReadyRetry();
            store.dispatch(updateWorkerState('inactive'));
          } else {
            readyRetryTimer = setTimeout(() => pushWorkerState('ready', true), READY_RETRY_PERIOD);
          }
        } else {
          store.dispatch(updateWorkerState('inactive'));
          store.dispatch(notify('doubleReady'));
        }
      });
  };

  const workerState = () => store.getState().worker.get('state');

  const handleAssignWork = (payload) => {
    if (workerState() === 'ready') {
      store.dispatch(assignWork(payload));
    } else {
      channel.push(
        'work_rejected',
        { reason: 'invalid_worker_state', worker_state: workerState() }
      );
    }
  };

  const handleWorkFinished = () => {
    store.dispatch(workFinished());
  };

  const handleCheckVersion = ({ version }) => {
    store.dispatch(setPluginVersion(version));
  };

  const handleCheckState = ({ worker_state: state }) => {
    if (!(['working', 'inactive', 'ready'].includes(state))) {
      throw new Error(`Unrecognized state for check_state message: ${state}`);
    }

    store.dispatch(checkState(state));
    const currentState = store.getState().worker.get('state');
    if (currentState !== state) {
      pushWorkerState(currentState);
    }
  };

  const handleReload = () => {
    store.dispatch(reloadPlugin());
  };

  const handleLeave = () => {
    if (!channel) {
      throw new Error("Leaving a channel when channel isn't joined");
    }

    channel.leave();
    channel = null;
    store.dispatch(channelLeft());
    socket.disconnect();
  };

  const joinLobby = () => {
    const lobby = socket.channel('workers:lobby');
    lobby.on('reload', handleReload);
    lobby.join().receive('ok', resp => {
      logDebug('Joined lobby successfully', resp);
    }).receive('error', resp => {
      throw new Error(`Error joining lobby: ${JSON.stringify(resp)}`);
    });
  };

  const connectToSocket = ({ socket: socketState, worker }) => {
    const workerUUID = worker.get('uuid');
    const socketAuth = socketState.get('auth');
    const SocketConstructor = socketConstructor;

    socket = new SocketConstructor(CONFIG.socketURL, {
      params: socketAuth.toObject(),
      logger: (kind, msg, data) => {
        let payload;
        try {
          payload = JSON.stringify(data);
        } catch (ex) {
          if (ex instanceof TypeError) {
            payload = '<binary>';
          } else {
            throw ex;
          }
        }
        const log = `${kind}: ${msg} ${payload}`;
        store.dispatch(logMessage(log));
      },
    });
    socket.onClose(() => {
      disconnectedAt = Date.now();
      clearReadyRetry();
      store.dispatch(connectionClosed());
    });
    socket.connect();

    channel = socket.channel(`workers:${workerUUID}`);
    channel.on('assign_work', handleAssignWork);
    channel.on('work_finished', handleWorkFinished);
    channel.on('check_version', handleCheckVersion);
    channel.on('check_state', handleCheckState);
    channel.on('reload', handleReload);
    channel.on('leave', handleLeave);
    channel.join()
      .receive('ok', resp => {
        disconnectedAt = null;
        pushWorkerState(workerState(), true);
        store.dispatch(connect(resp));
        // We only want to join the lobby if the actual channel connection was
        // successful
        joinLobby();
      }).receive('error', resp => store.dispatch(authFailed(resp)));
  };

  const reconnectSocket = (state) => {
    if (!socket) {
      throw Error('reconnectSocket called without a current socket');
    }

    socket.disconnect();
    socket = null;
    disconnectedAt = null;
    connectToSocket(state);
  };

  const shouldConnect = ({ socket: socketState, worker }) => {
    const currentState = socketState.get('state');
    return socket === null &&
      socketState.get('auth') !== null &&
      (currentState === 'unconnected' || currentState === 'unauthenticated') &&
      worker.get('uuid') !== null;
  };

  const shouldReconnect = (
    { worker: prevWorker, socket: prevSocket }, { worker: curWorker, socket: curSocket }
  ) => {
    if (prevSocket.get('state') !== 'reconnecting' && curSocket.get('state') === 'reconnecting') {
      return true;
    }

    if (disconnectedAt &&
        curSocket.get('state') === 'unconnected' &&
        (Date.now() - disconnectedAt > AUTO_RECONNECT_TIMEOUT)) {
      // If it's been a while since we disconnected, it's possible that the
      // auto-reconnect has failed so we try to manually reconnect.
      return true;
    }

    const prevUUID = prevWorker.get('uuid');
    const curUUID = curWorker.get('uuid');
    if (socket && prevUUID && curUUID && prevUUID !== curUUID) {
      return true;
    }

    return false;
  };

  const handleWorkerState = (previousState, currentState) => {
    const oldState = previousState.worker.get('state');
    const newState = currentState.worker.get('state');

    if (oldState !== newState) {
      pushWorkerState(newState);
    }
  };

  const handleUpdate = (previousState, currentState) => {
    if (shouldConnect(currentState)) {
      connectToSocket(currentState);
    } else if (shouldReconnect(previousState, currentState)) {
      reconnectSocket(currentState);
    }
    handleWorkerState(previousState, currentState);
  };

  const getSocket = () => socket;

  listenStoreChanges(store, handleUpdate);
  if (!store.getState().socket.get('auth')) {
    store.dispatch(authFailed('No credentials'));
  }

  return {
    getSocket,
  };
};
<|endoftext|>


<commit_before>'use strict'

var events = require('events')
var myUtils = require('../utils')
var Q = require('q')
var util = require('util')
var winston = require('winston-debug')
var winstonWrapper = require('winston-meta-wrapper')

function AbstractTransport () {
  // logging
  this._log = winstonWrapper(winston)
  this._log.addMeta({
    module: '1tp:transports'
  })
  // event emitter
  events.EventEmitter.call(this)
  // register _error handler
  myUtils.mixinEventEmitterErrorFunction(this)
  // version number
  this.version = myUtils.version
}

// Inherit EventEmitter
util.inherits(AbstractTransport, events.EventEmitter)

AbstractTransport.prototype.transportType = function () {
  var errorMsg = 'AbstractTransport.transportType function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.listen = function (listeningInfo, onSuccess, onFailure) {
  var errorMsg = 'AbstractTransport.listen function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.listenP = function (listeningInfo) {
  var deferred = Q.defer()
  this.listen(
    listeningInfo,
    function (connectionInfo) {
      deferred.resolve(connectionInfo)
    },
    function (error) {
      deferred.reject(error)
    }
  )
  return deferred.promise
}

AbstractTransport.prototype.connect = function (peerConnectionInfo, onSuccess, onFailure) {
  var errorMsg = 'AbstractTransport.connect function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.connectP = function (peerConnectionInfo) {
  var deferred = Q.defer()
  this.connect(
    peerConnectionInfo,
    function (stream, peerConnectionInfo) {
      stream._peerConnectionInfo = peerConnectionInfo
      deferred.resolve(stream)
    },
    function (error) {
      deferred.reject(error)
    }
  )
  return deferred.promise
}

// AbstractTransport.prototype.abort = function (peerConnectionInfo) {
//   var errorMsg = 'AbstractTransport.abort function not implemented'
//   this._log.error(errorMsg)
//   this._error(errorMsg)
// }

AbstractTransport.prototype.connectTimeout = function () {
  var errorMsg = 'AbstractTransport.connectTimeout function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.close = function (onSuccess, onFailure) {
  var errorMsg = 'AbstractTransport.close function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.closeP = function () {
  var deferred = Q.defer()
  this.close(
    function () {
      deferred.resolve()
    },
    function (error) {
      deferred.reject(error)
    }
  )
  return deferred.promise
}

AbstractTransport.prototype._fireListeningEvent = function (myConnectionInfo, callback) {
  this._log.debug('firing listening event with connectionInfo ' + JSON.stringify(myConnectionInfo))
  if (callback) {
    callback(myConnectionInfo)
    return
  }
  this.emit('listening', myConnectionInfo)
}

AbstractTransport.prototype._fireConnectEvent = function (stream, peerConnectionInfo, callback) {
  this._log.debug('firing connect event with peerConnectionInfo ' + JSON.stringify(peerConnectionInfo))
  if (callback) {
    callback(stream, peerConnectionInfo)
    return
  }
  this.emit('connect', stream, peerConnectionInfo)
}

AbstractTransport.prototype._fireConnectionEvent = function (stream, transport, peerConnectionInfo) {
  this._log.debug('firing connection event with peerConnectionInfo ' + JSON.stringify(peerConnectionInfo))
  this.emit('connection', stream, transport, peerConnectionInfo)
}

AbstractTransport.prototype._fireCloseEvent = function (callback) {
  this._log.debug('firing close event')
  if (callback) {
    callback()
    return
  }
  this.emit('close')
}

module.exports = AbstractTransport
<commit_msg>added abort function to superclass<commit_after>'use strict'

var events = require('events')
var myUtils = require('../utils')
var Q = require('q')
var util = require('util')
var winston = require('winston-debug')
var winstonWrapper = require('winston-meta-wrapper')

function AbstractTransport () {
  // logging
  this._log = winstonWrapper(winston)
  this._log.addMeta({
    module: '1tp:transports'
  })
  // event emitter
  events.EventEmitter.call(this)
  // register _error handler
  myUtils.mixinEventEmitterErrorFunction(this)
  // version number
  this.version = myUtils.version
}

// Inherit EventEmitter
util.inherits(AbstractTransport, events.EventEmitter)

AbstractTransport.prototype.transportType = function () {
  var errorMsg = 'AbstractTransport.transportType function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.listen = function (listeningInfo, onSuccess, onFailure) {
  var errorMsg = 'AbstractTransport.listen function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.listenP = function (listeningInfo) {
  var deferred = Q.defer()
  this.listen(
    listeningInfo,
    function (connectionInfo) {
      deferred.resolve(connectionInfo)
    },
    function (error) {
      deferred.reject(error)
    }
  )
  return deferred.promise
}

AbstractTransport.prototype.connect = function (peerConnectionInfo, onSuccess, onFailure) {
  var errorMsg = 'AbstractTransport.connect function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.connectP = function (peerConnectionInfo) {
  var deferred = Q.defer()
  this.connect(
    peerConnectionInfo,
    function (stream, peerConnectionInfo) {
      stream._peerConnectionInfo = peerConnectionInfo
      deferred.resolve(stream)
    },
    function (error) {
      deferred.reject(error)
    }
  )
  return deferred.promise
}

AbstractTransport.prototype.abort = function (peerConnectionInfo) {
  var errorMsg = 'AbstractTransport.abort function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.connectTimeout = function () {
  var errorMsg = 'AbstractTransport.connectTimeout function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.close = function (onSuccess, onFailure) {
  var errorMsg = 'AbstractTransport.close function not implemented'
  this._log.error(errorMsg)
  this._error(errorMsg)
}

AbstractTransport.prototype.closeP = function () {
  var deferred = Q.defer()
  this.close(
    function () {
      deferred.resolve()
    },
    function (error) {
      deferred.reject(error)
    }
  )
  return deferred.promise
}

AbstractTransport.prototype._fireListeningEvent = function (myConnectionInfo, callback) {
  this._log.debug('firing listening event with connectionInfo ' + JSON.stringify(myConnectionInfo))
  if (callback) {
    callback(myConnectionInfo)
    return
  }
  this.emit('listening', myConnectionInfo)
}

AbstractTransport.prototype._fireConnectEvent = function (stream, peerConnectionInfo, callback) {
  this._log.debug('firing connect event with peerConnectionInfo ' + JSON.stringify(peerConnectionInfo))
  if (callback) {
    callback(stream, peerConnectionInfo)
    return
  }
  this.emit('connect', stream, peerConnectionInfo)
}

AbstractTransport.prototype._fireConnectionEvent = function (stream, transport, peerConnectionInfo) {
  this._log.debug('firing connection event with peerConnectionInfo ' + JSON.stringify(peerConnectionInfo))
  this.emit('connection', stream, transport, peerConnectionInfo)
}

AbstractTransport.prototype._fireCloseEvent = function (callback) {
  this._log.debug('firing close event')
  if (callback) {
    callback()
    return
  }
  this.emit('close')
}

module.exports = AbstractTransport
<|endoftext|>


<commit_before>
/*!--------------------------------*\
   3-Jekyll Theme
   @author Peiwen Lu (P233)
   https://github.com/P233/3-Jekyll
\*---------------------------------*/

// Detect window size, if less than 1280px add class 'mobile' to sidebar therefore it will be auto hide when trigger the pjax request in small screen devices.
if ($(window).width() <= 1280) {
  $('#sidebar').addClass('mobile')
}

// Variables
var sidebar    = $('#sidebar'),
    container  = $('#post'),
    content    = $('#pjax'),
    button     = $('#icon-arrow');

// Tags switcher
var clickHandler = function(id) {
  return function()i{
    $(this).addClass('active').siblings().removeClass('active');
    $('.pl__all').hide();
    $('.' + id).delay(50).fadeIn(350);
  }
};

$('#tags__ul li').each(function(index){
  $('#' + $(this).attr('id')).on('click', clickHandler($(this).attr('id')));
});

// If sidebar has class 'mobile', hide it after clicking.
$('.pl__all').on('click', function() {
  $(this).addClass('active').siblings().removeClass('active');
  if (sidebar.hasClass('mobile')) {
    $('#sidebar, #pjax, #icon-arrow').addClass('fullscreen');
  }
});

// Enable fullscreen.
$('#js-fullscreen').on('click', function() {
  if (button.hasClass('fullscreen')) {
    sidebar.removeClass('fullscreen');
    button.removeClass('fullscreen');
    content.delay(300).queue(function(){
      $(this).removeClass('fullscreen').dequeue();
    });
  } else {
    sidebar.addClass('fullscreen');
    button.addClass('fullscreen');
    content.delay(200).queue(function(){
      $(this).addClass('fullscreen').dequeue();
    });
  }
});

$('#avatar').on('click', function() {
  if (button.hasClass('fullscreen')) {
    sidebar.removeClass('fullscreen');
    button.removeClass('fullscreen');
    content.delay(300).queue(function(){
      $(this).removeClass('fullscreen').dequeue();
    });
  } else {
    sidebar.addClass('fullscreen');
    button.addClass('fullscreen');
    content.delay(200).queue(function(){
      $(this).addClass('fullscreen').dequeue();
    });
  }
});

$('#mobile-avatar').on('click', function(){
  $('#sidebar, #pjax, #icon-arrow').addClass('fullscreen');
});

// Pjax
$(document).pjax('#avatar, #mobile-avatar, .pl__all', '#pjax', { fragment: '#pjax', timeout: 10000 });
$(document).on({
  'pjax:click': function() {
    content.removeClass('fadeIn').addClass('fadeOut');
    NProgress.start();
  },
  'pjax:start': function() {
    content.css({'opacity':0});
  },
  'pjax:end': function() {
    NProgress.done();
    container.scrollTop(0);
    content.css({'opacity':1}).removeClass('fadeOut').addClass('fadeIn');
    afterPjax();
  }
});

// Re-run scripts for post content after pjax
function afterPjax() {
  // Open links in new tab
  $('#post__content a').attr('target','_blank');

  // Generate post TOC for h1 h2 and h3
  var toc = $('#post__toc-ul');
  // Empty TOC and generate an entry for h1
  toc.empty().append('
' + $('#post__title').text() + '
');

  // Generate entries for h2 and h3
  $('#post__content').children('h2,h3').each(function() {
    // Generate random ID for each heading
    $(this).attr('id', function() {
      var ID = "",
          alphabet = "abcdefghijklmnopqrstuvwxyz";

      for(var i=0; i < 5; i++) {
        ID += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
      }
      return ID;
    });

    if ($(this).prop("tagName") == 'H2') {
      toc.append('
' + $(this).text() + '
');
    } else {
      toc.append('
' + $(this).text() + '
');
    }
  });

  // Smooth scrolling
  $('.js-anchor-link').on('click', function() {
    var target = $(this.hash);
    container.animate({scrollTop: target.offset().top + container.scrollTop() - 70}, 500, function() {
      target.addClass('flash').delay(700).queue(function() {
        $(this).removeClass('flash').dequeue();
      });
    });
  });
i
  // Lazy Loading Disqs
  // http://jsfiddle.net/dragoncrew/SHGwe/1/
  var ds_loaded = false,
      top = $('#disqus_thread').offset().top;
  window.disqus_shortname = $('#disqus_thread').attr('name');

  function check() {
    if ( !ds_loaded && container.scrollTop() + container.height() > top ) {
      $.ajax({
        type: 'GET',
        url: 'http://' + disqus_shortname + '.disqus.com/embed.js',
        dataType: 'script',
        cache: true
      });
      ds_loaded = true;
    }
  }check();
  container.scroll(check);
}afterPjax();

<commit_msg>恢复<commit_after>
/*!--------------------------------*\
   3-Jekyll Theme
   @author Peiwen Lu (P233)
   https://github.com/P233/3-Jekyll
\*---------------------------------*/

// Detect window size, if less than 1280px add class 'mobile' to sidebar therefore it will be auto hide when trigger the pjax request in small screen devices.
if ($(window).width() <= 1280) {
  $('#sidebar').addClass('mobile')
}

// Variables
var sidebar    = $('#sidebar'),
    container  = $('#post'),
    content    = $('#pjax'),
    button     = $('#icon-arrow');

// Tags switcher
var clickHandler = function(id) {
  return function()i{
    $(this).addClass('active').siblings().removeClass('active');
    $('.pl__all').hide();
    $('.' + id).delay(50).fadeIn(350);
  }
};

$('#tags__ul li').each(function(index){
  $('#' + $(this).attr('id')).on('click', clickHandler($(this).attr('id')));
});

// If sidebar has class 'mobile', hide it after clicking.
$('.pl__all').on('click', function() {
  $(this).addClass('active').siblings().removeClass('active');
  if (sidebar.hasClass('mobile')) {
    $('#sidebar, #pjax, #icon-arrow').addClass('fullscreen');
  }
});

// Enable fullscreen.
$('#js-fullscreen').on('click', function() {
  if (button.hasClass('fullscreen')) {
    sidebar.removeClass('fullscreen');
    button.removeClass('fullscreen');
    content.delay(300).queue(function(){
      $(this).removeClass('fullscreen').dequeue();
    });
  } else {
    sidebar.addClass('fullscreen');
    button.addClass('fullscreen');
    content.delay(200).queue(function(){
      $(this).addClass('fullscreen').dequeue();
    });
  }
});

$('#mobile-avatar').on('click', function(){
  $('#sidebar, #pjax, #icon-arrow').addClass('fullscreen');
});

// Pjax
$(document).pjax('#avatar, #mobile-avatar, .pl__all', '#pjax', { fragment: '#pjax', timeout: 10000 });
$(document).on({
  'pjax:click': function() {
    content.removeClass('fadeIn').addClass('fadeOut');
    NProgress.start();
  },
  'pjax:start': function() {
    content.css({'opacity':0});
  },
  'pjax:end': function() {
    NProgress.done();
    container.scrollTop(0);
    content.css({'opacity':1}).removeClass('fadeOut').addClass('fadeIn');
    afterPjax();
  }
});

// Re-run scripts for post content after pjax
function afterPjax() {
  // Open links in new tab
  $('#post__content a').attr('target','_blank');

  // Generate post TOC for h1 h2 and h3
  var toc = $('#post__toc-ul');
  // Empty TOC and generate an entry for h1
  toc.empty().append('
' + $('#post__title').text() + '
');

  // Generate entries for h2 and h3
  $('#post__content').children('h2,h3').each(function() {
    // Generate random ID for each heading
    $(this).attr('id', function() {
      var ID = "",
          alphabet = "abcdefghijklmnopqrstuvwxyz";

      for(var i=0; i < 5; i++) {
        ID += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
      }
      return ID;
    });

    if ($(this).prop("tagName") == 'H2') {
      toc.append('
' + $(this).text() + '
');
    } else {
      toc.append('
' + $(this).text() + '
');
    }
  });

  // Smooth scrolling
  $('.js-anchor-link').on('click', function() {
    var target = $(this.hash);
    container.animate({scrollTop: target.offset().top + container.scrollTop() - 70}, 500, function() {
      target.addClass('flash').delay(700).queue(function() {
        $(this).removeClass('flash').dequeue();
      });
    });
  });
i
  // Lazy Loading Disqs
  // http://jsfiddle.net/dragoncrew/SHGwe/1/
  var ds_loaded = false,
      top = $('#disqus_thread').offset().top;
  window.disqus_shortname = $('#disqus_thread').attr('name');

  function check() {
    if ( !ds_loaded && container.scrollTop() + container.height() > top ) {
      $.ajax({
        type: 'GET',
        url: 'http://' + disqus_shortname + '.disqus.com/embed.js',
        dataType: 'script',
        cache: true
      });
      ds_loaded = true;
    }
  }check();
  container.scroll(check);
}afterPjax();

<|endoftext|>


<commit_before>'use strict';

import { isDef, string } from 'metal';
import parse from './parse';
import { MultiMap } from 'metal-structs';

var parseFn_ = parse;

class Uri {

	/**
	 * This class contains setters and getters for the parts of the URI.
	 * The following figure displays an example URIs and their component parts.
	 *
	 *                                  path
	 *	                             ┌───┴────┐
	 *	  abc://example.com:123/path/data?key=value#fragid1
	 *	  └┬┘   └────┬────┘ └┬┘           └───┬───┘ └──┬──┘
	 * protocol  hostname  port            search    hash
	 *          └──────┬───────┘
	 *                host
	 *
	 * @param {*=} opt_uri Optional string URI to parse
	 * @constructor
	 */
	constructor(opt_uri = '') {
		this.url = Uri.parse(this.maybeAddProtocolAndHostname_(opt_uri));
	}

	/**
	 * Adds parameters to uri from a MultiMap as source.
	 * @param {MultiMap} multimap The MultiMap containing the
	 *   parameters.
	 * @protected
	 * @chainable
	 */
	addParametersFromMultiMap(multimap) {
		multimap.names().forEach((name) => {
			multimap.getAll(name).forEach((value) => {
				this.addParameterValue(name, value);
			});
		});
		return this;
	}

	/**
	 * Adds the value of the named query parameters.
	 * @param {string} key The parameter to set.
	 * @param {*} value The new value. Will be explicitly casted to String.
	 * @chainable
	 */
	addParameterValue(name, value) {
		this.ensureQueryInitialized_();
		if (isDef(value)) {
			value = String(value);
		}
		this.query.add(name, value);
		return this;
	}

	/**
	 * Adds the values of the named query parameter.
	 * @param {string} key The parameter to set.
	 * @param {*} value The new value.
	 * @chainable
	 */
	addParameterValues(name, values) {
		values.forEach((value) => this.addParameterValue(name, value));
		return this;
	}

	/**
	 * Ensures query internal map is initialized and synced with initial value
	 * extracted from URI search part.
	 * @protected
	 */
	ensureQueryInitialized_() {
		if (this.query) {
			return;
		}
		this.query = new MultiMap();
		var search = this.url.search;
		if (search) {
			search.substring(1).split('&').forEach((param) => {
				var [key, value] = param.split('=');
				if (isDef(value)) {
					value = Uri.urlDecode(value);
				}
				this.addParameterValue(key, value);
			});
		}
	}

	/**
	 * Gets the hash part of uri.
	 * @return {string}
	 */
	getHash() {
		return this.url.hash || '';
	}

	/**
	 * Gets the host part of uri. E.g. [hostname]:[port].
	 * @return {string}
	 */
	getHost() {
		var host = this.getHostname();
		if (host) {
			var port = this.getPort();
			if (port && port !== '80') {
				host += ':' + port;
			}
		}
		return host;
	}

	/**
	 * Gets the hostname part of uri without protocol and port.
	 * @return {string}
	 */
	getHostname() {
		var hostname = this.url.hostname;
		if (hostname === Uri.HOSTNAME_PLACEHOLDER) {
			return '';
		}
		return hostname;
	}

	/**
	 * Gets the origin part of uri. E.g. http://[hostname]:[port].
	 * @return {string}
	 */
	getOrigin() {
		var host = this.getHost();
		if (host) {
			return this.getProtocol() + '//' + host;
		}
		return '';
	}

	/**
	 * Returns the first value for a given parameter or undefined if the given
	 * parameter name does not appear in the query string.
	 * @param {string} paramName Unescaped parameter name.
	 * @return {string|undefined} The first value for a given parameter or
	 *   undefined if the given parameter name does not appear in the query
	 *   string.
	 */
	getParameterValue(name) {
		this.ensureQueryInitialized_();
		return this.query.get(name);
	}

	/**
	 * Returns the values for a given parameter as a list of decoded
	 * query parameter values.
	 * @param {string} name The parameter to get values for.
	 * @return {!Array<?>} The values for a given parameter as a list of decoded
	 *   query parameter values.
	 */
	getParameterValues(name) {
		this.ensureQueryInitialized_();
		return this.query.getAll(name);
	}

	/**
	 * Returns the names of the parameters.
	 * @return {!Array<string>} The names for the parameters as a list of
	 *   strings.
	 */
	getParameterNames() {
		this.ensureQueryInitialized_();
		return this.query.names();
	}

	/**
	 * Gets the function currently being used to parse URIs.
	 * @return {!function()}
	 */
	static getParseFn() {
		return parseFn_;
	}

	/**
	 * Gets the pathname part of uri.
	 * @return {string}
	 */
	getPathname() {
		return this.url.pathname;
	}

	/**
	 * Gets the port number part of uri as string.
	 * @return {string}
	 */
	getPort() {
		return this.url.port;
	}

	/**
	 * Gets the protocol part of uri. E.g. http:.
	 * @return {string}
	 */
	getProtocol() {
		return this.url.protocol;
	}

	/**
	 * Gets the search part of uri. Search value is retrieved from query
	 * parameters.
	 * @return {string}
	 */
	getSearch() {
		var search = '';
		var querystring = '';
		this.getParameterNames().forEach((name) => {
			this.getParameterValues(name).forEach((value) => {
				querystring += name;
				if (isDef(value)) {
					querystring += '=' + encodeURIComponent(value);
				}
				querystring += '&';
			});
		});
		querystring = querystring.slice(0, -1);
		if (querystring) {
			search += '?' + querystring;
		}
		return search;
	}

	/**
	 * Checks if uri contains the parameter.
	 * @param {string} name
	 * @return {boolean}
	 */
	hasParameter(name) {
		this.ensureQueryInitialized_();
		return this.query.contains(name);
	}

	/**
	 * Makes this URL unique by adding a random param to it. Useful for avoiding
	 * cache.
	 */
	makeUnique() {
		this.setParameterValue(Uri.RANDOM_PARAM, string.getRandomString());
		return this;
	}

	/**
	 * Maybe adds protocol and a hostname placeholder on a parial URI if needed.
	 * Relevent for compatibility with URL native object.
	 * @param {string=} opt_uri
	 * @return {string} URI with protocol and hostname placeholder.
	 */
	maybeAddProtocolAndHostname_(opt_uri) {
		var url = opt_uri;
		if (opt_uri.indexOf('://') === -1 &&
			opt_uri.indexOf('javascript:') !== 0) { // jshint ignore:line

			url = Uri.DEFAULT_PROTOCOL;
			if (opt_uri[0] !== '/' || opt_uri[1] !== '/') {
				url += '//';
			}

			switch (opt_uri.charAt(0)) {
				case '.':
				case '?':
				case '#':
					url += Uri.HOSTNAME_PLACEHOLDER;
					url += '/';
					url += opt_uri;
					break;
				case '':
				case '/':
					if (opt_uri[1] !== '/') {
						url += Uri.HOSTNAME_PLACEHOLDER;
					}
					url += opt_uri;
					break;
				default:
					url += opt_uri;
			}
		}
		return url;
	}

	/**
	 * Normalizes the parsed object to be in the expected standard.
	 * @param {!Object}
	 */
	static normalizeObject(parsed) {
		var length = parsed.pathname ? parsed.pathname.length : 0;
		if (length > 1 && parsed.pathname[length - 1] === '/') {
			parsed.pathname = parsed.pathname.substr(0, length - 1);
		}
		return parsed;
	}

	/**
	 * Parses the given uri string into an object.
	 * @param {*=} opt_uri Optional string URI to parse
	 */
	static parse(opt_uri) {
		return Uri.normalizeObject(parseFn_(opt_uri));
	}

	/**
	 * Removes the named query parameter.
	 * @param {string} name The parameter to remove.
	 * @chainable
	 */
	removeParameter(name) {
		this.ensureQueryInitialized_();
		this.query.remove(name);
		return this;
	}

	/**
	 * Removes uniqueness parameter of the uri.
	 * @chainable
	 */
	removeUnique() {
		this.removeParameter(Uri.RANDOM_PARAM);
		return this;
	}

	/**
	 * Sets the hash.
	 * @param {string} hash
	 * @chainable
	 */
	setHash(hash) {
		this.url.hash = hash;
		return this;
	}

	/**
	 * Sets the hostname.
	 * @param {string} hostname
	 * @chainable
	 */
	setHostname(hostname) {
		this.url.hostname = hostname;
		return this;
	}

	/**
	 * Sets the value of the named query parameters, clearing previous values
	 * for that key.
	 * @param {string} key The parameter to set.
	 * @param {*} value The new value.
	 * @chainable
	 */
	setParameterValue(name, value) {
		this.removeParameter(name);
		this.addParameterValue(name, value);
		return this;
	}

	/**
	 * Sets the values of the named query parameters, clearing previous values
	 * for that key.
	 * @param {string} key The parameter to set.
	 * @param {*} value The new value.
	 * @chainable
	 */
	setParameterValues(name, values) {
		this.removeParameter(name);
		values.forEach((value) => this.addParameterValue(name, value));
		return this;
	}

	/**
	 * Sets the pathname.
	 * @param {string} pathname
	 * @chainable
	 */
	setPathname(pathname) {
		this.url.pathname = pathname;
		return this;
	}

	/**
	 * Sets the port number.
	 * @param {*} port Port number.
	 * @chainable
	 */
	setPort(port) {
		this.url.port = port;
		return this;
	}

	/**
	 * Sets the function that will be used for parsing the original string uri
	 * into an object.
	 * @param {!function()} parseFn
	 */
	static setParseFn(parseFn) {
		parseFn_ = parseFn;
	}

	/**
	 * Sets the protocol. If missing http: is used as default.
	 * @param {string} protocol
	 * @chainable
	 */
	setProtocol(protocol) {
		this.url.protocol = protocol;
		if (this.url.protocol[this.url.protocol.length - 1] !== ':') {
			this.url.protocol += ':';
		}
		return this;
	}

	/**
	 * @return {string} The string form of the url.
	 * @override
	 */
	toString() {
		var href = '';
		var host = this.getHost();
		if (host) {
			href += this.getProtocol() + '//';
		}
		href += host + this.getPathname() + this.getSearch() + this.getHash();
		return href;
	}

	/**
	 * Joins the given paths.
	 * @param {string} basePath
	 * @param {...string} ...paths Any number of paths to be joined with the base url.
	 * @static
	 */
	static joinPaths(basePath, ...paths) {
		if (basePath.charAt(basePath.length - 1) === '/') {
			basePath = basePath.substring(0, basePath.length - 1);
		}
		paths = paths.map(path => path.charAt(0) === '/' ? path.substring(1) : path);
		return [basePath].concat(paths).join('/').replace(/\/$/, '');
	}

	/**
	 * URL-decodes the string. We need to specially handle '+'s because
	 * the javascript library doesn't convert them to spaces.
	 * @param {string} str The string to url decode.
	 * @return {string} The decoded {@code str}.
	 */
	static urlDecode(str) {
		return decodeURIComponent(str.replace(/\+/g, ' '));
	}

}

/**
 * Default protocol value.
 * @type {string}
 * @default http:
 * @static
 */
Uri.DEFAULT_PROTOCOL = 'http:';

/**
 * Hostname placeholder. Relevant to internal usage only.
 * @type {string}
 * @static
 */
Uri.HOSTNAME_PLACEHOLDER = 'hostname' + Date.now();

/**
 * Name used by the param generated by `makeUnique`.
 * @type {string}
 * @static
 */
Uri.RANDOM_PARAM = 'zx';

export default Uri;
<commit_msg>Inherits default protocol from browser if existing<commit_after>'use strict';

import { isDef, string } from 'metal';
import parse from './parse';
import { MultiMap } from 'metal-structs';

var parseFn_ = parse;

class Uri {

	/**
	 * This class contains setters and getters for the parts of the URI.
	 * The following figure displays an example URIs and their component parts.
	 *
	 *                                  path
	 *	                             ┌───┴────┐
	 *	  abc://example.com:123/path/data?key=value#fragid1
	 *	  └┬┘   └────┬────┘ └┬┘           └───┬───┘ └──┬──┘
	 * protocol  hostname  port            search    hash
	 *          └──────┬───────┘
	 *                host
	 *
	 * @param {*=} opt_uri Optional string URI to parse
	 * @constructor
	 */
	constructor(opt_uri = '') {
		this.url = Uri.parse(this.maybeAddProtocolAndHostname_(opt_uri));
	}

	/**
	 * Adds parameters to uri from a MultiMap as source.
	 * @param {MultiMap} multimap The MultiMap containing the
	 *   parameters.
	 * @protected
	 * @chainable
	 */
	addParametersFromMultiMap(multimap) {
		multimap.names().forEach((name) => {
			multimap.getAll(name).forEach((value) => {
				this.addParameterValue(name, value);
			});
		});
		return this;
	}

	/**
	 * Adds the value of the named query parameters.
	 * @param {string} key The parameter to set.
	 * @param {*} value The new value. Will be explicitly casted to String.
	 * @chainable
	 */
	addParameterValue(name, value) {
		this.ensureQueryInitialized_();
		if (isDef(value)) {
			value = String(value);
		}
		this.query.add(name, value);
		return this;
	}

	/**
	 * Adds the values of the named query parameter.
	 * @param {string} key The parameter to set.
	 * @param {*} value The new value.
	 * @chainable
	 */
	addParameterValues(name, values) {
		values.forEach((value) => this.addParameterValue(name, value));
		return this;
	}

	/**
	 * Ensures query internal map is initialized and synced with initial value
	 * extracted from URI search part.
	 * @protected
	 */
	ensureQueryInitialized_() {
		if (this.query) {
			return;
		}
		this.query = new MultiMap();
		var search = this.url.search;
		if (search) {
			search.substring(1).split('&').forEach((param) => {
				var [key, value] = param.split('=');
				if (isDef(value)) {
					value = Uri.urlDecode(value);
				}
				this.addParameterValue(key, value);
			});
		}
	}

	/**
	 * Gets the hash part of uri.
	 * @return {string}
	 */
	getHash() {
		return this.url.hash || '';
	}

	/**
	 * Gets the host part of uri. E.g. [hostname]:[port].
	 * @return {string}
	 */
	getHost() {
		var host = this.getHostname();
		if (host) {
			var port = this.getPort();
			if (port && port !== '80') {
				host += ':' + port;
			}
		}
		return host;
	}

	/**
	 * Gets the hostname part of uri without protocol and port.
	 * @return {string}
	 */
	getHostname() {
		var hostname = this.url.hostname;
		if (hostname === Uri.HOSTNAME_PLACEHOLDER) {
			return '';
		}
		return hostname;
	}

	/**
	 * Gets the origin part of uri. E.g. http://[hostname]:[port].
	 * @return {string}
	 */
	getOrigin() {
		var host = this.getHost();
		if (host) {
			return this.getProtocol() + '//' + host;
		}
		return '';
	}

	/**
	 * Returns the first value for a given parameter or undefined if the given
	 * parameter name does not appear in the query string.
	 * @param {string} paramName Unescaped parameter name.
	 * @return {string|undefined} The first value for a given parameter or
	 *   undefined if the given parameter name does not appear in the query
	 *   string.
	 */
	getParameterValue(name) {
		this.ensureQueryInitialized_();
		return this.query.get(name);
	}

	/**
	 * Returns the values for a given parameter as a list of decoded
	 * query parameter values.
	 * @param {string} name The parameter to get values for.
	 * @return {!Array<?>} The values for a given parameter as a list of decoded
	 *   query parameter values.
	 */
	getParameterValues(name) {
		this.ensureQueryInitialized_();
		return this.query.getAll(name);
	}

	/**
	 * Returns the names of the parameters.
	 * @return {!Array<string>} The names for the parameters as a list of
	 *   strings.
	 */
	getParameterNames() {
		this.ensureQueryInitialized_();
		return this.query.names();
	}

	/**
	 * Gets the function currently being used to parse URIs.
	 * @return {!function()}
	 */
	static getParseFn() {
		return parseFn_;
	}

	/**
	 * Gets the pathname part of uri.
	 * @return {string}
	 */
	getPathname() {
		return this.url.pathname;
	}

	/**
	 * Gets the port number part of uri as string.
	 * @return {string}
	 */
	getPort() {
		return this.url.port;
	}

	/**
	 * Gets the protocol part of uri. E.g. http:.
	 * @return {string}
	 */
	getProtocol() {
		return this.url.protocol;
	}

	/**
	 * Gets the search part of uri. Search value is retrieved from query
	 * parameters.
	 * @return {string}
	 */
	getSearch() {
		var search = '';
		var querystring = '';
		this.getParameterNames().forEach((name) => {
			this.getParameterValues(name).forEach((value) => {
				querystring += name;
				if (isDef(value)) {
					querystring += '=' + encodeURIComponent(value);
				}
				querystring += '&';
			});
		});
		querystring = querystring.slice(0, -1);
		if (querystring) {
			search += '?' + querystring;
		}
		return search;
	}

	/**
	 * Checks if uri contains the parameter.
	 * @param {string} name
	 * @return {boolean}
	 */
	hasParameter(name) {
		this.ensureQueryInitialized_();
		return this.query.contains(name);
	}

	/**
	 * Makes this URL unique by adding a random param to it. Useful for avoiding
	 * cache.
	 */
	makeUnique() {
		this.setParameterValue(Uri.RANDOM_PARAM, string.getRandomString());
		return this;
	}

	/**
	 * Maybe adds protocol and a hostname placeholder on a parial URI if needed.
	 * Relevent for compatibility with URL native object.
	 * @param {string=} opt_uri
	 * @return {string} URI with protocol and hostname placeholder.
	 */
	maybeAddProtocolAndHostname_(opt_uri) {
		var url = opt_uri;
		if (opt_uri.indexOf('://') === -1 &&
			opt_uri.indexOf('javascript:') !== 0) { // jshint ignore:line

			url = Uri.DEFAULT_PROTOCOL;
			if (opt_uri[0] !== '/' || opt_uri[1] !== '/') {
				url += '//';
			}

			switch (opt_uri.charAt(0)) {
				case '.':
				case '?':
				case '#':
					url += Uri.HOSTNAME_PLACEHOLDER;
					url += '/';
					url += opt_uri;
					break;
				case '':
				case '/':
					if (opt_uri[1] !== '/') {
						url += Uri.HOSTNAME_PLACEHOLDER;
					}
					url += opt_uri;
					break;
				default:
					url += opt_uri;
			}
		}
		return url;
	}

	/**
	 * Normalizes the parsed object to be in the expected standard.
	 * @param {!Object}
	 */
	static normalizeObject(parsed) {
		var length = parsed.pathname ? parsed.pathname.length : 0;
		if (length > 1 && parsed.pathname[length - 1] === '/') {
			parsed.pathname = parsed.pathname.substr(0, length - 1);
		}
		return parsed;
	}

	/**
	 * Parses the given uri string into an object.
	 * @param {*=} opt_uri Optional string URI to parse
	 */
	static parse(opt_uri) {
		return Uri.normalizeObject(parseFn_(opt_uri));
	}

	/**
	 * Removes the named query parameter.
	 * @param {string} name The parameter to remove.
	 * @chainable
	 */
	removeParameter(name) {
		this.ensureQueryInitialized_();
		this.query.remove(name);
		return this;
	}

	/**
	 * Removes uniqueness parameter of the uri.
	 * @chainable
	 */
	removeUnique() {
		this.removeParameter(Uri.RANDOM_PARAM);
		return this;
	}

	/**
	 * Sets the hash.
	 * @param {string} hash
	 * @chainable
	 */
	setHash(hash) {
		this.url.hash = hash;
		return this;
	}

	/**
	 * Sets the hostname.
	 * @param {string} hostname
	 * @chainable
	 */
	setHostname(hostname) {
		this.url.hostname = hostname;
		return this;
	}

	/**
	 * Sets the value of the named query parameters, clearing previous values
	 * for that key.
	 * @param {string} key The parameter to set.
	 * @param {*} value The new value.
	 * @chainable
	 */
	setParameterValue(name, value) {
		this.removeParameter(name);
		this.addParameterValue(name, value);
		return this;
	}

	/**
	 * Sets the values of the named query parameters, clearing previous values
	 * for that key.
	 * @param {string} key The parameter to set.
	 * @param {*} value The new value.
	 * @chainable
	 */
	setParameterValues(name, values) {
		this.removeParameter(name);
		values.forEach((value) => this.addParameterValue(name, value));
		return this;
	}

	/**
	 * Sets the pathname.
	 * @param {string} pathname
	 * @chainable
	 */
	setPathname(pathname) {
		this.url.pathname = pathname;
		return this;
	}

	/**
	 * Sets the port number.
	 * @param {*} port Port number.
	 * @chainable
	 */
	setPort(port) {
		this.url.port = port;
		return this;
	}

	/**
	 * Sets the function that will be used for parsing the original string uri
	 * into an object.
	 * @param {!function()} parseFn
	 */
	static setParseFn(parseFn) {
		parseFn_ = parseFn;
	}

	/**
	 * Sets the protocol. If missing http: is used as default.
	 * @param {string} protocol
	 * @chainable
	 */
	setProtocol(protocol) {
		this.url.protocol = protocol;
		if (this.url.protocol[this.url.protocol.length - 1] !== ':') {
			this.url.protocol += ':';
		}
		return this;
	}

	/**
	 * @return {string} The string form of the url.
	 * @override
	 */
	toString() {
		var href = '';
		var host = this.getHost();
		if (host) {
			href += this.getProtocol() + '//';
		}
		href += host + this.getPathname() + this.getSearch() + this.getHash();
		return href;
	}

	/**
	 * Joins the given paths.
	 * @param {string} basePath
	 * @param {...string} ...paths Any number of paths to be joined with the base url.
	 * @static
	 */
	static joinPaths(basePath, ...paths) {
		if (basePath.charAt(basePath.length - 1) === '/') {
			basePath = basePath.substring(0, basePath.length - 1);
		}
		paths = paths.map(path => path.charAt(0) === '/' ? path.substring(1) : path);
		return [basePath].concat(paths).join('/').replace(/\/$/, '');
	}

	/**
	 * URL-decodes the string. We need to specially handle '+'s because
	 * the javascript library doesn't convert them to spaces.
	 * @param {string} str The string to url decode.
	 * @return {string} The decoded {@code str}.
	 */
	static urlDecode(str) {
		return decodeURIComponent(str.replace(/\+/g, ' '));
	}

}

/**
 * Default protocol value.
 * @type {string}
 * @default http:
 * @static
 */
Uri.DEFAULT_PROTOCOL = (typeof window !== 'undefined' && window.location) ?
	window.location.protocol : 'http:';

/**
 * Hostname placeholder. Relevant to internal usage only.
 * @type {string}
 * @static
 */
Uri.HOSTNAME_PLACEHOLDER = 'hostname' + Date.now();

/**
 * Name used by the param generated by `makeUnique`.
 * @type {string}
 * @static
 */
Uri.RANDOM_PARAM = 'zx';

export default Uri;
<|endoftext|>


<commit_before>var CommentBox = React.createClass({
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  handleCommentSubmit: function(comment) {
    // TODO: サーバに送信、リストをリフレッシュ
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (

Comments

        <CommentList data={this.state.data} />
        <CommentForm onCommentSubmit={this.handleCommentSubmit} />

    );
  }
});
var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });
    return (

        {commentNodes}

    );
  }
});

var CommentForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var author = ReactDOM.findDOMNode(this.refs.author).value.trim();
    var text = ReactDOM.findDOMNode(this.refs.text).value.trim();
    if (!text || !author) {
      return;
    }
    this.props.onCommentSubmit({author: author, text: text});
    ReactDOM.findDOMNode(this.refs.author).value = '';
    ReactDOM.findDOMNode(this.refs.text).value = '';
    return;
  },
  render: function() {
    return (
      <form className="commentForm" onSubmit={this.handleSubmit}>
        <input type="text" placeholder="Your name" ref="author" />
        <input type="text" placeholder="Say something..." ref="text" />
        <input type="submit" value="Post" />
      </form>
    );
  }
});

var Comment = React.createClass({
  render: function() {
    var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
    return (

          {this.props.author}

    );
  }
});

ReactDOM.render(
  <CommentBox url="comments.json" pollInterval={2000} />,
  document.getElementById('content')
);
<commit_msg>tutorial19.js<commit_after>var CommentBox = React.createClass({
  loadCommentsFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  handleCommentSubmit: function(comment) {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      type: 'POST',
      data: comment,
      success: function (data) {
        this.setState({data: data});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },
  getInitialState: function() {
    return {data: []};
  },
  componentDidMount: function() {
    this.loadCommentsFromServer();
    setInterval(this.loadCommentsFromServer, this.props.pollInterval);
  },
  render: function() {
    return (

Comments

        <CommentList data={this.state.data} />
        <CommentForm onCommentSubmit={this.handleCommentSubmit} />

    );
  }
});
var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function (comment) {
      return (
        <Comment author={comment.author}>
          {comment.text}
        </Comment>
      );
    });
    return (

        {commentNodes}

    );
  }
});

var CommentForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();
    var author = ReactDOM.findDOMNode(this.refs.author).value.trim();
    var text = ReactDOM.findDOMNode(this.refs.text).value.trim();
    if (!text || !author) {
      return;
    }
    this.props.onCommentSubmit({author: author, text: text});
    ReactDOM.findDOMNode(this.refs.author).value = '';
    ReactDOM.findDOMNode(this.refs.text).value = '';
    return;
  },
  render: function() {
    return (
      <form className="commentForm" onSubmit={this.handleSubmit}>
        <input type="text" placeholder="Your name" ref="author" />
        <input type="text" placeholder="Say something..." ref="text" />
        <input type="submit" value="Post" />
      </form>
    );
  }
});

var Comment = React.createClass({
  render: function() {
    var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
    return (

          {this.props.author}

    );
  }
});

ReactDOM.render(
  <CommentBox url="comments.json" pollInterval={2000} />,
  document.getElementById('content')
);
<|endoftext|>


<commit_before>var NativeStorageError = require('./NativeStorageError');

// args = [reference, variable]
function LocalStorageHandle(success, error, intent, operation, args) {
    var reference = args[0];
    var variable = args[1];

    if (operation.startsWith('put') || operation.startsWith('set')) {
        try {
            var varAsString = JSON.stringify(variable);
            if (reference === null) {
                error(new NativeStorageError(NativeStorageError.NULL_REFERENCE, "JS", ""));
                return;
            }
            localStorage.setItem(reference, varAsString);
            success(variable);
        } catch (err) {
            error(new NativeStorageError(NativeStorageError.JSON_ERROR, "JS", err));
        }
    } else if (operation.startsWith('get')) {
        var item = {};
        item = localStorage.getItem(reference);
        if (item === null) {
            error(new NativeStorageError(NativeStorageError.ITEM_NOT_FOUND,"JS",""));
            return;
        }
        try {
            var obj = JSON.parse(item);
            //console.log("LocalStorage Reading: "+obj);
            success(obj);
        } catch (err) {
            error(new NativeStorageError(NativeStorageError.JSON_ERROR, "JS", err));
        }
    } else if (operation === 'keys') {
      var keys = [];
      for(var i = 0; i < localStorage.length; i++){
         keys.push(localStorage.key(i));
      }
      success(keys);
    }
}
module.exports = LocalStorageHandle;
<commit_msg>Fixed error code on browser platform<commit_after>var NativeStorageError = require('./NativeStorageError');

// args = [reference, variable]
function LocalStorageHandle(success, error, intent, operation, args) {
    var reference = args[0];
    var variable = args[1];

    if (operation.startsWith('put') || operation.startsWith('set')) {
        try {
            var varAsString = JSON.stringify(variable);
            if (reference === null) {
                error(NativeStorageError.NULL_REFERENCE);
                return;
            }
            localStorage.setItem(reference, varAsString);
            success(variable);
        } catch (err) {
            error(NativeStorageError.JSON_ERROR);
        }
    } else if (operation.startsWith('get')) {
        var item = {};
        item = localStorage.getItem(reference);
        if (item === null) {
            error(NativeStorageError.ITEM_NOT_FOUND);
            return;
        }
        try {
            var obj = JSON.parse(item);
            //console.log("LocalStorage Reading: "+obj);
            success(obj);
        } catch (err) {
            error(NativeStorageError.JSON_ERROR);
        }
    } else if (operation === 'keys') {
      var keys = [];
      for(var i = 0; i < localStorage.length; i++){
         keys.push(localStorage.key(i));
      }
      success(keys);
    }
}
module.exports = LocalStorageHandle;
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  'use strict';

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    banner: '/*\n' +
    ' * Copyright (c) 2015 peeracle contributors\n' +
    ' *\n' +
    ' * Permission is hereby granted, free of charge, to any person obtaining a copy\n' +
    ' * of this software and associated documentation files (the "Software"), to deal\n' +
    ' * in the Software without restriction, including without limitation the rights\n' +
    ' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n' +
    ' * copies of the Software, and to permit persons to whom the Software is\n' +
    ' * furnished to do so, subject to the following conditions:\n' +
    ' *\n' +
    ' * The above copyright notice and this permission notice shall be included in\n' +
    ' * all copies or substantial portions of the Software.\n' +
    ' *\n' +
    ' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n' +
    ' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n' +
    ' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n' +
    ' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n' +
    ' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n' +
    ' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n' +
    ' * SOFTWARE.\n' +
    ' */\n',

    karma: {
      unit: {
        configFile: 'karma.conf.js'
      }
    },

    concat: {
      options: {
        banner: '<%= banner %>\n' +
        '\'use strict\';\n\n' +
        '(function(){\n' +
        '\n' +
        'var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || \
        window.webkitRTCPeerConnection || window.msRTCPeerConnection;\n' +
        'var RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || \
        window.webkitRTCSessionDescription || window.msRTCSessionDescription;\n' +
        'var RTCIceCandidate = window.mozRTCIceCandidate || window.webkitRTCIceCandidate || \
        window.RTCIceCandidate;\n',

        footer: '})();\n',

        process: function (src, filepath) {
          var moduleName = filepath.slice(4, filepath.length - 3);
          var modules = moduleName.split('.');
          var moduleStr = 'Peeracle';
          for (var i = 0; i < modules.length; ++i) {
            moduleStr += '.' + modules[i];
          }

          return src.replace(/(^|\n)[ \t]*('use strict'|"use strict");?\n/g, '$1')
            .replace(/module.exports = /g, moduleStr + ' = ')
            .replace(/var (.*) = require\('.\/(.*)'\);/g, 'var $1 = Peeracle.$2;');
        },
        stripBanners: true
      },
      dist: {
        src: [
          'src/Listenable.js',
          'src/Peeracle.js',
          'src/BinaryStream.js',

          'src/Hash/index.js',
          'src/Hash/Crc32.js',
          'src/Hash/Murmur3.js',

          'src/DataSource/index.js',
          'src/DataSource/File.js',
          'src/DataSource/Http.js',

          'src/Downloader/index.js',
          'src/Downloader/Http.js',
          'src/Downloader/P2P.js',

          'src/Manager.js',

          'src/Media/index.js',
          'src/Media/MP4.js',
          'src/Media/WebM.js',

          'src/Metadata.js',
          'src/MetadataSerializer.js',
          'src/MetadataUnserializer.js',
          'src/Peer.js',
          'src/PeerConnection.js',
          'src/Storage/index.js',
          'src/Storage/Memory.js',

          'src/Stream.js',

          'src/Tracker/index.js',
          'src/Tracker/Client.js',
          'src/Tracker/Message.js',

          'src/Utils.js'
        ],
        dest: 'dist/<%= pkg.name %>-<%= pkg.version %>.js'
      }
    },

    preprocess: {
      inline: {
        src: 'dist/<%= pkg.name %>-<%= pkg.version %>.js',
        options: {
          inline: true,
          context: {
            DEBUG: false
          }
        }
      }
    },

    jsbeautifier: {
      files: ['dist/<%= pkg.name %>-<%= pkg.version %>.js'],
      options: {
        js: {
          braceStyle: "collapse",
          breakChainedMethods: false,
          e4x: false,
          evalCode: false,
          indentChar: " ",
          indentLevel: 0,
          indentSize: 2,
          indentWithTabs: false,
          jslintHappy: false,
          keepArrayIndentation: false,
          keepFunctionIndentation: false,
          maxPreserveNewlines: 10,
          preserveNewlines: true,
          spaceBeforeConditional: true,
          spaceInParen: false,
          unescapeStrings: false,
          wrapLineLength: 80,
          endWithNewline: true
        }
      }
    },

    eslint: {
      target: ['src/*.js']
    },

    'closure-compiler': {
      frontend: {
        closurePath: '.',
        js: [
          'dist/<%= pkg.name %>-<%= pkg.version %>.js',
          'exports.js'
        ],
        jsOutputFile: 'dist/<%= pkg.name %>-<%= pkg.version %>.min.js',
        maxBuffer: 500,
        options: {
          compilation_level: 'ADVANCED_OPTIMIZATIONS',
          language_in: 'ECMASCRIPT5_STRICT'
        }
      },
      frontend_debug: {
        closurePath: '.',
        js: 'dist/<%= pkg.name %>-<%= pkg.version %>.js',
        jsOutputFile: 'dist/<%= pkg.name %>-<%= pkg.version %>.debug.js',
        options: {
          debug: true,
          formatting: 'PRETTY_PRINT'
        }
      }
    },
  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-preprocess');
  grunt.loadNpmTasks('grunt-eslint');
  grunt.loadNpmTasks('grunt-jsbeautifier');
  grunt.loadNpmTasks('grunt-closure-compiler');
  grunt.loadNpmTasks('grunt-contrib-jasmine');

  // Default task(s).
  grunt.registerTask('default', ['concat', 'preprocess', 'eslint', 'jsbeautifier'/*, 'closure-compiler'*/, 'karma']);

  // Build only task
  grunt.registerTask('build', ['concat', 'preprocess', 'eslint', 'jsbeautifier'/*, 'closure-compiler'*/]);
  grunt.registerTask('test', ['karma']);
};
<commit_msg>Grunt: Define Peeracle globally<commit_after>module.exports = function (grunt) {
  'use strict';

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),

    banner: '/*\n' +
    ' * Copyright (c) 2015 peeracle contributors\n' +
    ' *\n' +
    ' * Permission is hereby granted, free of charge, to any person obtaining a copy\n' +
    ' * of this software and associated documentation files (the "Software"), to deal\n' +
    ' * in the Software without restriction, including without limitation the rights\n' +
    ' * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n' +
    ' * copies of the Software, and to permit persons to whom the Software is\n' +
    ' * furnished to do so, subject to the following conditions:\n' +
    ' *\n' +
    ' * The above copyright notice and this permission notice shall be included in\n' +
    ' * all copies or substantial portions of the Software.\n' +
    ' *\n' +
    ' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n' +
    ' * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n' +
    ' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n' +
    ' * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n' +
    ' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n' +
    ' * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n' +
    ' * SOFTWARE.\n' +
    ' */\n',

    karma: {
      unit: {
        configFile: 'karma.conf.js'
      }
    },

    concat: {
      options: {
        banner: '<%= banner %>\n' +
        '\'use strict\';\n\n' +
        '(function(){\n' +
        '\n' +
        'var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || \
        window.webkitRTCPeerConnection || window.msRTCPeerConnection;\n' +
        'var RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || \
        window.webkitRTCSessionDescription || window.msRTCSessionDescription;\n' +
        'var RTCIceCandidate = window.mozRTCIceCandidate || window.webkitRTCIceCandidate || \
        window.RTCIceCandidate;\n',

        footer: '\nwindow[\'Peeracle\'] = Peeracle;\n})();\n',

        process: function (src, filepath) {
          var moduleName = filepath.slice(4, filepath.length - 3);
          var modules = moduleName.split('.');
          var moduleStr = 'Peeracle';
          for (var i = 0; i < modules.length; ++i) {
            moduleStr += '.' + modules[i];
          }

          return src.replace(/(^|\n)[ \t]*('use strict'|"use strict");?\n/g, '$1')
            .replace(/module.exports = /g, moduleStr + ' = ')
            .replace(/var (.*) = require\('.\/(.*)'\);/g, 'var $1 = Peeracle.$2;');
        },
        stripBanners: true
      },
      dist: {
        src: [
          'src/Listenable.js',
          'src/Peeracle.js',
          'src/BinaryStream.js',

          'src/Hash/index.js',
          'src/Hash/Crc32.js',
          'src/Hash/Murmur3.js',

          'src/DataSource/index.js',
          'src/DataSource/File.js',
          'src/DataSource/Http.js',

          'src/Downloader/index.js',
          'src/Downloader/Http.js',
          'src/Downloader/P2P.js',

          'src/Manager.js',

          'src/Media/index.js',
          'src/Media/MP4.js',
          'src/Media/WebM.js',

          'src/Metadata.js',
          'src/MetadataSerializer.js',
          'src/MetadataUnserializer.js',
          'src/Peer.js',
          'src/PeerConnection.js',
          'src/Storage/index.js',
          'src/Storage/Memory.js',

          'src/Stream.js',

          'src/Tracker/index.js',
          'src/Tracker/Client.js',
          'src/Tracker/Message.js',

          'src/Utils.js'
        ],
        dest: 'dist/<%= pkg.name %>-<%= pkg.version %>.js'
      }
    },

    preprocess: {
      inline: {
        src: 'dist/<%= pkg.name %>-<%= pkg.version %>.js',
        options: {
          inline: true,
          context: {
            DEBUG: false
          }
        }
      }
    },

    jsbeautifier: {
      files: ['dist/<%= pkg.name %>-<%= pkg.version %>.js'],
      options: {
        js: {
          braceStyle: "collapse",
          breakChainedMethods: false,
          e4x: false,
          evalCode: false,
          indentChar: " ",
          indentLevel: 0,
          indentSize: 2,
          indentWithTabs: false,
          jslintHappy: false,
          keepArrayIndentation: false,
          keepFunctionIndentation: false,
          maxPreserveNewlines: 10,
          preserveNewlines: true,
          spaceBeforeConditional: true,
          spaceInParen: false,
          unescapeStrings: false,
          wrapLineLength: 80,
          endWithNewline: true
        }
      }
    },

    eslint: {
      target: ['src/*.js']
    },

    'closure-compiler': {
      frontend: {
        closurePath: '.',
        js: [
          'dist/<%= pkg.name %>-<%= pkg.version %>.js',
          'exports.js'
        ],
        jsOutputFile: 'dist/<%= pkg.name %>-<%= pkg.version %>.min.js',
        maxBuffer: 500,
        options: {
          compilation_level: 'ADVANCED_OPTIMIZATIONS',
          language_in: 'ECMASCRIPT5_STRICT'
        }
      },
      frontend_debug: {
        closurePath: '.',
        js: 'dist/<%= pkg.name %>-<%= pkg.version %>.js',
        jsOutputFile: 'dist/<%= pkg.name %>-<%= pkg.version %>.debug.js',
        options: {
          debug: true,
          formatting: 'PRETTY_PRINT'
        }
      }
    },
  });

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-preprocess');
  grunt.loadNpmTasks('grunt-eslint');
  grunt.loadNpmTasks('grunt-jsbeautifier');
  grunt.loadNpmTasks('grunt-closure-compiler');
  grunt.loadNpmTasks('grunt-contrib-jasmine');

  // Default task(s).
  grunt.registerTask('default', ['concat', 'preprocess', 'eslint', 'jsbeautifier'/*, 'closure-compiler'*/, 'karma']);

  // Build only task
  grunt.registerTask('build', ['concat', 'preprocess', 'eslint', 'jsbeautifier'/*, 'closure-compiler'*/]);
  grunt.registerTask('test', ['karma']);
};
<|endoftext|>


<commit_before>/* Licensed under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 * Copyright (c) 2010 Mr.doob, rhyolight, bebraw
 */
function ProxyCanvas(canvasId) {
    this.init(canvasId);
}
ProxyCanvas.prototype = {
    init: function (canvasId) {
        this.canvas = document.getElementById(canvasId);
        this.context = this.canvas.getContext("2d");

        this.width = this.canvas.width;
        this.height = this.canvas.height;
    },
    destroy: function () {},
    saveAs: function (format) {
        // note that this spawns a save dialog!

        if(format == 'png') {
            Canvas2Image.saveAsPNG(this.canvas);
        }

        if(format == 'jpeg' || format == 'jpg') {
            Canvas2Image.saveAsJPEG(this.canvas);
        }

        if(format == 'bmp') {
            Canvas2Image.saveAsBMP(this.canvas);
        }
    },
    getData: function () {
        return this.context.getImageData(0, 0, this.width, this.height);
    },
    setData: function (data) {
        this.context.putImageData(data, 0, 0);
    },
    fill: function (colorName) {
        this.context.fillStyle = colorName;
        this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
    },
    text: function (label, colorName, font, x, y) {
        this.context.fillStyle = colorName;
        this.context.font = font;
        this.context.fillText(label, x, y);
    },
    stroke: function (startLoc, endLoc, color, alpha) {
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.moveTo(startLoc.x, startLoc.y);
        this.context.lineTo(endLoc.x, endLoc.y);
        this.context.stroke();
    },
    rect: function (xy1, xy2, xy3, xy4, color, alpha) {
        this.context.fillStyle = "rgb(255, 255, 255)"; // XXX: replace with fillColor
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.moveTo(xy1.x, xy1.y);
        this.context.lineTo(xy2.x, xy2.y);
        this.context.lineTo(xy3.x, xy3.y);
        this.context.lineTo(xy4.x, xy4.y);
        this.context.lineTo(xy1.x, xy1.y);
        this.context.fill();
        this.context.stroke();
    },
    bezierCurve: function (begin, cp1, cp2, end, color, alpha) {
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.moveTo(begin.x, begin.y);
        this.context.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y);
        this.context.stroke();
    },
    quadraticCurve: function (begin, cp, end, color, alpha) {
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.moveTo(begin.x, begin.y);
        this.context.quadraticCurveTo(cp.x, cp.y, end.x, end.y);
        this.context.stroke();
    },
    circle: function (center, radius, color, alpha) {
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.arc(center.x, center.y, radius, 0, Math.PI * 2, true);
        this.context.stroke()
    },
    getPointsInside: function (radius, location) {
        points = panels['canvas'].points;
        ret = [];

        for (var i = 0; i < points.length; i++) {
            point = points[i];

            if( Math.pow((location.x - point.x), 2) +
                    Math.pow((location.y - point.y), 2) <
                    Math.pow(radius, 2) ) {
                ret.push(point);
            }
        }

        return ret;
    }
}
<commit_msg>Made export work in Chrome.<commit_after>/* Licensed under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 * Copyright (c) 2010 Mr.doob, rhyolight, bebraw
 */
function ProxyCanvas(canvasId) {
    this.init(canvasId);
}
ProxyCanvas.prototype = {
    init: function (canvasId) {
        this.canvas = document.getElementById(canvasId);
        this.context = this.canvas.getContext("2d");

        this.width = this.canvas.width;
        this.height = this.canvas.height;
    },
    destroy: function () {},
    saveAs: function (format) {
        var isChrome =  navigator.userAgent.toLowerCase().indexOf('chrome')  > -1;

        if( isChrome ) {
            // apparently this work just with png?
            window.open(this.canvas.toDataURL('image/png'), 'mywindow');
        }
        else {
            // note that this spawns a save dialog! doesn't work in chrome!
            if(format == 'png') {
                Canvas2Image.saveAsPNG(this.canvas);
            }

            if(format == 'jpeg' || format == 'jpg') {
                Canvas2Image.saveAsJPEG(this.canvas);
            }

            if(format == 'bmp') {
                Canvas2Image.saveAsBMP(this.canvas);
            }
        }
    },
    getData: function () {
        return this.context.getImageData(0, 0, this.width, this.height);
    },
    setData: function (data) {
        this.context.putImageData(data, 0, 0);
    },
    fill: function (colorName) {
        this.context.fillStyle = colorName;
        this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
    },
    text: function (label, colorName, font, x, y) {
        this.context.fillStyle = colorName;
        this.context.font = font;
        this.context.fillText(label, x, y);
    },
    stroke: function (startLoc, endLoc, color, alpha) {
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.moveTo(startLoc.x, startLoc.y);
        this.context.lineTo(endLoc.x, endLoc.y);
        this.context.stroke();
    },
    rect: function (xy1, xy2, xy3, xy4, color, alpha) {
        this.context.fillStyle = "rgb(255, 255, 255)"; // XXX: replace with fillColor
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.moveTo(xy1.x, xy1.y);
        this.context.lineTo(xy2.x, xy2.y);
        this.context.lineTo(xy3.x, xy3.y);
        this.context.lineTo(xy4.x, xy4.y);
        this.context.lineTo(xy1.x, xy1.y);
        this.context.fill();
        this.context.stroke();
    },
    bezierCurve: function (begin, cp1, cp2, end, color, alpha) {
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.moveTo(begin.x, begin.y);
        this.context.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y);
        this.context.stroke();
    },
    quadraticCurve: function (begin, cp, end, color, alpha) {
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.moveTo(begin.x, begin.y);
        this.context.quadraticCurveTo(cp.x, cp.y, end.x, end.y);
        this.context.stroke();
    },
    circle: function (center, radius, color, alpha) {
        this.context.strokeStyle = "rgba(" + color[0] + ", " + color[1] +
            ", " + color[2] + ", " + alpha + ")";
        this.context.beginPath();
        this.context.arc(center.x, center.y, radius, 0, Math.PI * 2, true);
        this.context.stroke()
    },
    getPointsInside: function (radius, location) {
        points = panels['canvas'].points;
        ret = [];

        for (var i = 0; i < points.length; i++) {
            point = points[i];

            if( Math.pow((location.x - point.x), 2) +
                    Math.pow((location.y - point.y), 2) <
                    Math.pow(radius, 2) ) {
                ret.push(point);
            }
        }

        return ret;
    }
}
<|endoftext|>