<commit_before>// this is mostly the editor implemented by @SergioBenitez for graydon/rust-www
// plus small modifications to accommodate a "Reset" button

// ECMAScript 6 Backwards compatability
if (typeof String.prototype.startsWith != 'function') {
  String.prototype.startsWith = function(str) {
    return this.slice(0, str.length) == str;
  };
}

// Regex for finding new lines
var newLineRegex = /(?:\r\n|\r|\n)/g;

// DOM items
var editorDiv;
var resetButton;
var runButton;
var resultDiv;

// Background colors for program result on success/error
var successColor = "#E2EEF6";
var errorColor = "#F6E2E2";
var warningColor = "#FFFBCB";

// Error message to return when there's a server failure
var errMsg = "The server encountered an error while running the program.";

// Stores ACE editor markers (highights) for errors
var markers = [];

// Status codes, because there are no enums in Javascript
var SUCCESS = 0;
var ERROR = 1;
var WARNING = 2;

// Ace editor
var editor;
var Range;

// Original source code
var originalCode;

// Maximum length of a response before it has to be truncated
var MAX_RESPONSE_LENGTH = 50000;

function initEditor() {
  // Fetching DOM items
  editorDiv = document.getElementById("editor");
  resetButton = document.getElementById("reset-code");
  runButton = document.getElementById("run-code");
  resultDiv = document.getElementById("result");

  if (editorDiv === null)
    return; // No editor on this page

  // Setup ace editor
  editor = ace.edit("editor");
  Range = ace.require('ace/range').Range;

  var executeCode = function(ev) {
    resultDiv.style.display = "block";
    resultDiv.innerHTML = "Running...";

    // Clear previous markers, if any
    markers.map(function(id) { editor.getSession().removeMarker(id); });

    // Get the code, run the program
    var program = editor.getValue();
    runProgram(program, handleResult);
  };

  ace.config.setModuleUrl('ace/mode/rust', '/gitbook/plugins/gitbook-plugin-rust-playpen/mode-rust.js');

  editor.setTheme("ace/theme/tomorrow");
  editor.getSession().setMode("ace/mode/rust");
  editor.setShowPrintMargin(false);
  editor.renderer.setShowGutter(false);
  editor.setHighlightActiveLine(false);
  editor.commands.addCommand({
      name: "run",
      bindKey: {
          win: "Ctrl-Enter",
          mac: "Ctrl-Enter"
      },
      exec: executeCode
  })

  originalCode = editor.getSession().getValue();

  // Set initial size to match initial content
  updateEditorHeight();

  // Registering handler for run button click
  runButton.addEventListener("click", executeCode);

  // Registering handler for reset button click
  resetButton.addEventListener("click", function(ev) {
    // Clear previous markers, if any
    markers.map(function(id) { editor.getSession().removeMarker(id); });

    editor.getSession().setValue(originalCode);
    resultDiv.style.display = "none";
  });

  editor.on('change', updateEditorHeight);

  // Highlight active line when focused
  editor.on('focus', function() {
    editor.setHighlightActiveLine(true);
  });

  // Don't when not
  editor.on('blur', function() {
    editor.setHighlightActiveLine(false);
  });
}

require(["gitbook"], function(gitbook) {
  gitbook.events.bind("page.change", function() {
    initEditor();
  })
});

// Changes the height of the editor to match its contents
function updateEditorHeight() {
  // http://stackoverflow.com/questions/11584061/
  var newHeight = editor.getSession().getScreenLength()
    * editor.renderer.lineHeight
    + editor.renderer.scrollBar.getWidth();

  editorDiv.style.height = Math.ceil(newHeight).toString() + "px";
  editor.resize();
};

//
// escapeHTML() borrowed from mustache.js:
// https://github.com/janl/mustache.js/blob/master/mustache.js#L43
//
// via:
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery/12034334#12034334
//
var entityMap = {
  "&": "&",
  "<": "<",
  ">": ">",
  '"': '"',
  "'": ''',
  "/": '/'
};

function escapeHTML(unsafe) {
  return String(unsafe).replace(/[&<>"'\/]/g, function(s) {
    return entityMap[s];
  });
}

// Dispatches a XMLHttpRequest to the Rust playpen, running the program, and
// issues a callback to `callback` with the result (or null on error)
function runProgram(program, callback) {
  var req = new XMLHttpRequest();
  var data = JSON.stringify({
    version: "master",
      optimize: "0",
      code: program
  });

  // console.log("Sending", data);
  req.open('POST', "https://play.rust-lang.org/evaluate.json", true);
  req.onload = function(e) {
    if (req.readyState === 4 && req.status === 200) {
      var result = JSON.parse(req.response).result;

      // Need server support to get an accurate version of this.
      var statusCode = SUCCESS;
      if (result.indexOf("error:") !== -1) {
        statusCode = ERROR;
      } else if (result.indexOf("warning:") !== -1) {
        statusCode = WARNING;
      }

      callback(statusCode, result);
    } else {
      callback(false, null);
    }
  };

  req.onerror = function(e) {
    callback(false, null);
  }

  req.setRequestHeader("Content-Type", "application/json");
  req.send(data);
}

// The callback to runProgram
function handleResult(statusCode, message) {

  // Check the size of the message, shorten it if
  // it's too big to be appended to the DOM.
  if ( message.length > MAX_RESPONSE_LENGTH ) {
    message = message.slice(0, MAX_RESPONSE_LENGTH / 2)
            + '\n\n--- THIS RESULT HAS BEEN SHORTENED ---\n\n'
            + message.slice(-MAX_RESPONSE_LENGTH / 2);
  }

  // Dispatch depending on result type
  if (result == null) {
    resultDiv.style.backgroundColor = errorColor;
    resultDiv.innerHTML = errMsg;
  } else if (statusCode == SUCCESS) {
    handleSuccess(message);
  } else if (statusCode == WARNING) {
    handleWarning(message);
  } else {
    handleError(message);
  }
}

// Called on successful program run
function handleSuccess(message) {
  resultDiv.style.backgroundColor = successColor;
  var lines = message.split(newLineRegex);
  message = lines.map(function(line) {
    return escapeHTML(line);
  }).join('
');
  resultDiv.innerHTML = message;
}

// Called when program run results in warning(s)
function handleWarning(message) {
  resultDiv.style.backgroundColor = warningColor;
  handleProblem(message, "warning");
}

// Called when program run results in error(s)
function handleError(message) {
  resultDiv.style.backgroundColor = errorColor;
  handleProblem(message, "error");
}

// Called on unsuccessful program run. Detects and prints problems (either
// warnings or errors) in program output and highlights relevant lines and text
// in the code.
function handleProblem(message, problem) {
  // Getting list of ranges with problems
  var lines = message.split(newLineRegex);

  // Cleaning up the message: keeps only relevant problem output
  var cleanMessage = lines.map(function(line) {
    if (line.startsWith("<anon>") || line.indexOf("^") !== -1) {
      var errIndex = line.indexOf(problem + ": ");
      if (errIndex !== -1) return line.slice(errIndex);
      return "";
    }

    // Discard playpen messages, keep the rest
    if (line.startsWith("playpen:")) return "";
    return line;
  }).filter(function(line) {
    return line !== "";
  }).map(function(line) {
    return escapeHTML(line);
  }).join("
");

  // Setting message
  resultDiv.innerHTML = cleanMessage;

  // Highlighting the lines
  var ranges = parseProblems(lines);
  markers = ranges.map(function(range) {
    return editor.getSession().addMarker(range, "ace-" + problem + "-line",
      "fullLine", false);
  });

  // Highlighting the specific text
  markers = markers.concat(ranges.map(function(range) {
    return editor.getSession().addMarker(range, "ace-" + problem + "-text",
      "text", false);
  }));
}

// Parses a problem message returning a list of ranges (row:col, row:col) where
// problems in the code have occured.
function parseProblems(lines) {
  var ranges = [];
  for (var i in lines) {
    var line = lines[i];
    if (line.startsWith("<anon>:") && line.indexOf(": ") !== -1) {
      var parts = line.split(/:\s?|\s+/, 5).slice(1, 5);
      var ip = parts.map(function(p) { return parseInt(p, 10) - 1; });
      // console.log("line:", line, parts, ip);
      ranges.push(new Range(ip[0], ip[1], ip[2], ip[3]));
    }
  }

  return ranges;
}
<commit_msg>Use nightly playpen<commit_after>// this is mostly the editor implemented by @SergioBenitez for graydon/rust-www
// plus small modifications to accommodate a "Reset" button

// ECMAScript 6 Backwards compatability
if (typeof String.prototype.startsWith != 'function') {
  String.prototype.startsWith = function(str) {
    return this.slice(0, str.length) == str;
  };
}

// Regex for finding new lines
var newLineRegex = /(?:\r\n|\r|\n)/g;

// DOM items
var editorDiv;
var resetButton;
var runButton;
var resultDiv;

// Background colors for program result on success/error
var successColor = "#E2EEF6";
var errorColor = "#F6E2E2";
var warningColor = "#FFFBCB";

// Error message to return when there's a server failure
var errMsg = "The server encountered an error while running the program.";

// Stores ACE editor markers (highights) for errors
var markers = [];

// Status codes, because there are no enums in Javascript
var SUCCESS = 0;
var ERROR = 1;
var WARNING = 2;

// Ace editor
var editor;
var Range;

// Original source code
var originalCode;

// Maximum length of a response before it has to be truncated
var MAX_RESPONSE_LENGTH = 50000;

function initEditor() {
  // Fetching DOM items
  editorDiv = document.getElementById("editor");
  resetButton = document.getElementById("reset-code");
  runButton = document.getElementById("run-code");
  resultDiv = document.getElementById("result");

  if (editorDiv === null)
    return; // No editor on this page

  // Setup ace editor
  editor = ace.edit("editor");
  Range = ace.require('ace/range').Range;

  var executeCode = function(ev) {
    resultDiv.style.display = "block";
    resultDiv.innerHTML = "Running...";

    // Clear previous markers, if any
    markers.map(function(id) { editor.getSession().removeMarker(id); });

    // Get the code, run the program
    var program = editor.getValue();
    runProgram(program, handleResult);
  };

  ace.config.setModuleUrl('ace/mode/rust', '/gitbook/plugins/gitbook-plugin-rust-playpen/mode-rust.js');

  editor.setTheme("ace/theme/tomorrow");
  editor.getSession().setMode("ace/mode/rust");
  editor.setShowPrintMargin(false);
  editor.renderer.setShowGutter(false);
  editor.setHighlightActiveLine(false);
  editor.commands.addCommand({
      name: "run",
      bindKey: {
          win: "Ctrl-Enter",
          mac: "Ctrl-Enter"
      },
      exec: executeCode
  })

  originalCode = editor.getSession().getValue();

  // Set initial size to match initial content
  updateEditorHeight();

  // Registering handler for run button click
  runButton.addEventListener("click", executeCode);

  // Registering handler for reset button click
  resetButton.addEventListener("click", function(ev) {
    // Clear previous markers, if any
    markers.map(function(id) { editor.getSession().removeMarker(id); });

    editor.getSession().setValue(originalCode);
    resultDiv.style.display = "none";
  });

  editor.on('change', updateEditorHeight);

  // Highlight active line when focused
  editor.on('focus', function() {
    editor.setHighlightActiveLine(true);
  });

  // Don't when not
  editor.on('blur', function() {
    editor.setHighlightActiveLine(false);
  });
}

require(["gitbook"], function(gitbook) {
  gitbook.events.bind("page.change", function() {
    initEditor();
  })
});

// Changes the height of the editor to match its contents
function updateEditorHeight() {
  // http://stackoverflow.com/questions/11584061/
  var newHeight = editor.getSession().getScreenLength()
    * editor.renderer.lineHeight
    + editor.renderer.scrollBar.getWidth();

  editorDiv.style.height = Math.ceil(newHeight).toString() + "px";
  editor.resize();
};

//
// escapeHTML() borrowed from mustache.js:
// https://github.com/janl/mustache.js/blob/master/mustache.js#L43
//
// via:
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery/12034334#12034334
//
var entityMap = {
  "&": "&",
  "<": "<",
  ">": ">",
  '"': '"',
  "'": ''',
  "/": '/'
};

function escapeHTML(unsafe) {
  return String(unsafe).replace(/[&<>"'\/]/g, function(s) {
    return entityMap[s];
  });
}

// Dispatches a XMLHttpRequest to the Rust playpen, running the program, and
// issues a callback to `callback` with the result (or null on error)
function runProgram(program, callback) {
  var req = new XMLHttpRequest();
  var data = JSON.stringify({
    version: "nightly",
      optimize: "0",
      code: program
  });

  // console.log("Sending", data);
  req.open('POST', "https://play.rust-lang.org/evaluate.json", true);
  req.onload = function(e) {
    if (req.readyState === 4 && req.status === 200) {
      var result = JSON.parse(req.response).result;

      // Need server support to get an accurate version of this.
      var statusCode = SUCCESS;
      if (result.indexOf("error:") !== -1) {
        statusCode = ERROR;
      } else if (result.indexOf("warning:") !== -1) {
        statusCode = WARNING;
      }

      callback(statusCode, result);
    } else {
      callback(false, null);
    }
  };

  req.onerror = function(e) {
    callback(false, null);
  }

  req.setRequestHeader("Content-Type", "application/json");
  req.send(data);
}

// The callback to runProgram
function handleResult(statusCode, message) {

  // Check the size of the message, shorten it if
  // it's too big to be appended to the DOM.
  if ( message.length > MAX_RESPONSE_LENGTH ) {
    message = message.slice(0, MAX_RESPONSE_LENGTH / 2)
            + '\n\n--- THIS RESULT HAS BEEN SHORTENED ---\n\n'
            + message.slice(-MAX_RESPONSE_LENGTH / 2);
  }

  // Dispatch depending on result type
  if (result == null) {
    resultDiv.style.backgroundColor = errorColor;
    resultDiv.innerHTML = errMsg;
  } else if (statusCode == SUCCESS) {
    handleSuccess(message);
  } else if (statusCode == WARNING) {
    handleWarning(message);
  } else {
    handleError(message);
  }
}

// Called on successful program run
function handleSuccess(message) {
  resultDiv.style.backgroundColor = successColor;
  var lines = message.split(newLineRegex);
  message = lines.map(function(line) {
    return escapeHTML(line);
  }).join('
');
  resultDiv.innerHTML = message;
}

// Called when program run results in warning(s)
function handleWarning(message) {
  resultDiv.style.backgroundColor = warningColor;
  handleProblem(message, "warning");
}

// Called when program run results in error(s)
function handleError(message) {
  resultDiv.style.backgroundColor = errorColor;
  handleProblem(message, "error");
}

// Called on unsuccessful program run. Detects and prints problems (either
// warnings or errors) in program output and highlights relevant lines and text
// in the code.
function handleProblem(message, problem) {
  // Getting list of ranges with problems
  var lines = message.split(newLineRegex);

  // Cleaning up the message: keeps only relevant problem output
  var cleanMessage = lines.map(function(line) {
    if (line.startsWith("<anon>") || line.indexOf("^") !== -1) {
      var errIndex = line.indexOf(problem + ": ");
      if (errIndex !== -1) return line.slice(errIndex);
      return "";
    }

    // Discard playpen messages, keep the rest
    if (line.startsWith("playpen:")) return "";
    return line;
  }).filter(function(line) {
    return line !== "";
  }).map(function(line) {
    return escapeHTML(line);
  }).join("
");

  // Setting message
  resultDiv.innerHTML = cleanMessage;

  // Highlighting the lines
  var ranges = parseProblems(lines);
  markers = ranges.map(function(range) {
    return editor.getSession().addMarker(range, "ace-" + problem + "-line",
      "fullLine", false);
  });

  // Highlighting the specific text
  markers = markers.concat(ranges.map(function(range) {
    return editor.getSession().addMarker(range, "ace-" + problem + "-text",
      "text", false);
  }));
}

// Parses a problem message returning a list of ranges (row:col, row:col) where
// problems in the code have occured.
function parseProblems(lines) {
  var ranges = [];
  for (var i in lines) {
    var line = lines[i];
    if (line.startsWith("<anon>:") && line.indexOf(": ") !== -1) {
      var parts = line.split(/:\s?|\s+/, 5).slice(1, 5);
      var ip = parts.map(function(p) { return parseInt(p, 10) - 1; });
      // console.log("line:", line, parts, ip);
      ranges.push(new Range(ip[0], ip[1], ip[2], ip[3]));
    }
  }

  return ranges;
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';

import Control from './Control';

class Checkbox extends Control {
  static propTypes = {
    className: PropTypes.string,
    id: PropTypes.string,
    name: PropTypes.string.isRequired,
    style: PropTypes.string,
  };

  static defaultProps = {
    type: 'text',
  };

  render() {
    const {id, name, className, style} = this.props;

    return (
      <input
        type="checkbox"
        className={className}
        style={style}
        id={id}
        name={name}
        checked={this._getValue() || false}
        onChange={(e) => this._onChange(e.target.checked)}
      />
    );
  }
}

export default Checkbox;
<commit_msg>Simplify checkbox to functional component and to use connect<commit_after>import React from 'react';
import PropTypes from 'prop-types';

import {updateValue} from '../actions/controls';
import {connect} from '../store';

const Checkbox = ({id, name, className, style, value, updateValue}) =>
  <input
    type="checkbox"
    className={className}
    style={style}
    id={id}
    name={name}
    checked={value || false}
    onChange={(e) => updateValue(name, e.target.checked)}
  />;

Checkbox.propTypes = {
  className: PropTypes.string,
  id: PropTypes.string,
  name: PropTypes.string.isRequired,
  style: PropTypes.string,
  value: PropTypes.bool,
};

const mapStateToProps = ({controls}, props) => ({
  value: controls.get(props.name),
});

const mapDispatchToProps = {
  updateValue,
};

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox);
<|endoftext|>


<commit_before>/* eslint-env mocha */
'use strict'

const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const signalling = require('libp2p-webrtc-star/src/sig-server')
const parallel = require('async/parallel')
const crypto = require('crypto')

const createNode = require('./utils/create-node')
const echo = require('./utils/echo')

describe('peer discovery', () => {
  let nodeA
  let nodeB
  let port = 24642
  let ss

  function setup (options) {
    before((done) => {
      port++
      parallel([
        (cb) => {
          signalling.start({ port: port }, (err, server) => {
            expect(err).to.not.exist()
            ss = server
            cb()
          })
        },
        (cb) => createNode([
          '/ip4/0.0.0.0/tcp/0',
          `/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
        ], options, (err, node) => {
          expect(err).to.not.exist()
          nodeA = node
          node.handle('/echo/1.0.0', echo)
          node.start(cb)
        }),
        (cb) => createNode([
          '/ip4/0.0.0.0/tcp/0',
          `/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
        ], options, (err, node) => {
          expect(err).to.not.exist()
          nodeB = node
          node.handle('/echo/1.0.0', echo)
          node.start(cb)
        })
      ], done)
    })

    after((done) => {
      parallel([
        (cb) => nodeA.stop(cb),
        (cb) => nodeB.stop(cb),
        (cb) => ss.stop(cb)
      ], done)
    })
  }

  describe('MulticastDNS', () => {
    setup({
      config: {
        peerDiscovery: {
          mdns: {
            enabled: true,
            // use a random tag to prevent CI collision
            serviceTag: crypto.randomBytes(10).toString('hex')
          }
        }
      }
    })

    it('find a peer', function (done) {
      this.timeout(15 * 1000)

      nodeA.once('peer:discovery', (peerInfo) => {
        expect(nodeB.peerInfo.id.toB58String())
          .to.eql(peerInfo.id.toB58String())
        done()
      })
    })
  })

  // TODO needs a delay (this test is already long)
  describe.skip('WebRTCStar', () => {
    setup({
      config: {
        peerDiscovery: {
          webRTCStar: {
            enabled: true
          }
        }
      }
    })

    it('find a peer', function (done) {
      this.timeout(15 * 1000)
      nodeA.once('peer:discovery', (peerInfo) => {
        expect(nodeB.peerInfo.id.toB58String())
          .to.eql(peerInfo.id.toB58String())
        done()
      })
    })
  })

  describe('MulticastDNS + WebRTCStar', () => {
    setup({
      config: {
        peerDiscovery: {
          mdns: {
            enabled: true,
            // use a random tag to prevent CI collision
            serviceTag: crypto.randomBytes(10).toString('hex')
          },
          webRTCStar: {
            enabled: true
          }
        }
      }
    })

    it('find a peer', function (done) {
      this.timeout(15 * 1000)
      nodeA.once('peer:discovery', (peerInfo) => {
        expect(nodeB.peerInfo.id.toB58String())
          .to.eql(peerInfo.id.toB58String())
        done()
      })
    })
  })
})
<commit_msg>test: add tests for peer discovery module registration<commit_after>/* eslint-env mocha */
'use strict'

const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const sinon = require('sinon')
const signalling = require('libp2p-webrtc-star/src/sig-server')
const parallel = require('async/parallel')
const crypto = require('crypto')

const createNode = require('./utils/create-node')
const echo = require('./utils/echo')

describe('peer discovery', () => {
  let nodeA
  let nodeB
  let port = 24642
  let ss

  function setup (options) {
    before((done) => {
      port++
      parallel([
        (cb) => {
          signalling.start({ port: port }, (err, server) => {
            expect(err).to.not.exist()
            ss = server
            cb()
          })
        },
        (cb) => createNode([
          '/ip4/0.0.0.0/tcp/0',
          `/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
        ], options, (err, node) => {
          expect(err).to.not.exist()
          nodeA = node
          node.handle('/echo/1.0.0', echo)
          node.start(cb)
        }),
        (cb) => createNode([
          '/ip4/0.0.0.0/tcp/0',
          `/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
        ], options, (err, node) => {
          expect(err).to.not.exist()
          nodeB = node
          node.handle('/echo/1.0.0', echo)
          node.start(cb)
        })
      ], done)
    })

    after((done) => {
      parallel([
        (cb) => nodeA.stop(cb),
        (cb) => nodeB.stop(cb),
        (cb) => ss.stop(cb)
      ], done)
    })
  }

  describe('module registration', () => {
    it('should enable module by default', (done) => {
      const mockDiscovery = {
        on: sinon.stub(),
        start: sinon.stub().callsArg(0),
        stop: sinon.stub().callsArg(0)
      }

      const options = { modules: { peerDiscovery: [ mockDiscovery ] } }

      createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
        expect(err).to.not.exist()

        node.start((err) => {
          expect(err).to.not.exist()
          expect(mockDiscovery.start.called).to.be.true()
          node.stop(done)
        })
      })
    })

    it('should enable module by configutation', (done) => {
      const mockDiscovery = {
        on: sinon.stub(),
        start: sinon.stub().callsArg(0),
        stop: sinon.stub().callsArg(0),
        tag: 'mockDiscovery'
      }

      const enabled = sinon.stub().returns(true)

      const options = {
        modules: { peerDiscovery: [ mockDiscovery ] },
        config: {
          peerDiscovery: {
            mockDiscovery: {
              get enabled () {
                return enabled()
              }
            }
          }
        }
      }

      createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
        expect(err).to.not.exist()

        node.start((err) => {
          expect(err).to.not.exist()
          expect(mockDiscovery.start.called).to.be.true()
          expect(enabled.called).to.be.true()
          node.stop(done)
        })
      })
    })

    it('should disable module by configutation', (done) => {
      const mockDiscovery = {
        on: sinon.stub(),
        start: sinon.stub().callsArg(0),
        stop: sinon.stub().callsArg(0),
        tag: 'mockDiscovery'
      }

      const disabled = sinon.stub().returns(false)

      const options = {
        modules: { peerDiscovery: [ mockDiscovery ] },
        config: {
          peerDiscovery: {
            mockDiscovery: {
              get enabled () {
                return disabled()
              }
            }
          }
        }
      }

      createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
        expect(err).to.not.exist()

        node.start((err) => {
          expect(err).to.not.exist()
          expect(mockDiscovery.start.called).to.be.false()
          expect(disabled.called).to.be.true()
          node.stop(done)
        })
      })
    })

    it('should register module passed as function', (done) => {
      const mockDiscovery = {
        on: sinon.stub(),
        start: sinon.stub().callsArg(0),
        stop: sinon.stub().callsArg(0)
      }

      const MockDiscovery = sinon.stub().returns(mockDiscovery)
      MockDiscovery.tag = 'mockDiscovery'

      const options = {
        modules: { peerDiscovery: [ MockDiscovery ] },
        config: {
          peerDiscovery: {
            mockDiscovery: {
              enabled: true,
              time: Date.now()
            }
          }
        }
      }

      createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
        expect(err).to.not.exist()

        node.start((err) => {
          expect(err).to.not.exist()
          expect(mockDiscovery.start.called).to.be.true()
          expect(MockDiscovery.called).to.be.true()
          // Ensure configuration was passed
          expect(MockDiscovery.firstCall.args[0])
            .to.deep.include(options.config.peerDiscovery.mockDiscovery)
          node.stop(done)
        })
      })
    })

    it('should register module passed as object', (done) => {
      const mockDiscovery = {
        on: sinon.stub(),
        start: sinon.stub().callsArg(0),
        stop: sinon.stub().callsArg(0),
        tag: 'mockDiscovery'
      }

      const options = {
        modules: { peerDiscovery: [ mockDiscovery ] },
        config: {
          peerDiscovery: {
            mockDiscovery: { enabled: true }
          }
        }
      }

      createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
        expect(err).to.not.exist()

        node.start((err) => {
          expect(err).to.not.exist()
          expect(mockDiscovery.start.called).to.be.true()
          node.stop(done)
        })
      })
    })
  })

  describe('MulticastDNS', () => {
    setup({
      config: {
        peerDiscovery: {
          mdns: {
            enabled: true,
            // use a random tag to prevent CI collision
            serviceTag: crypto.randomBytes(10).toString('hex')
          }
        }
      }
    })

    it('find a peer', function (done) {
      this.timeout(15 * 1000)

      nodeA.once('peer:discovery', (peerInfo) => {
        expect(nodeB.peerInfo.id.toB58String())
          .to.eql(peerInfo.id.toB58String())
        done()
      })
    })
  })

  // TODO needs a delay (this test is already long)
  describe.skip('WebRTCStar', () => {
    setup({
      config: {
        peerDiscovery: {
          webRTCStar: {
            enabled: true
          }
        }
      }
    })

    it('find a peer', function (done) {
      this.timeout(15 * 1000)
      nodeA.once('peer:discovery', (peerInfo) => {
        expect(nodeB.peerInfo.id.toB58String())
          .to.eql(peerInfo.id.toB58String())
        done()
      })
    })
  })

  describe('MulticastDNS + WebRTCStar', () => {
    setup({
      config: {
        peerDiscovery: {
          mdns: {
            enabled: true,
            // use a random tag to prevent CI collision
            serviceTag: crypto.randomBytes(10).toString('hex')
          },
          webRTCStar: {
            enabled: true
          }
        }
      }
    })

    it('find a peer', function (done) {
      this.timeout(15 * 1000)
      nodeA.once('peer:discovery', (peerInfo) => {
        expect(nodeB.peerInfo.id.toB58String())
          .to.eql(peerInfo.id.toB58String())
        done()
      })
    })
  })
})
<|endoftext|>


<commit_before>/***************
http://github.com/francescortiz/pacaclass

****************/

/**
 * Simple logger
 */
var log = function(){
    var stderr = document.getElementById('stderr');
    if (stderr) {
        var m = "";
        for (var i = 0; i < arguments.length; i++) {
            m += arguments[i] + ", ";
        }
        stderr.innerHTML += m + "
";
    } else {
        try {
            console.log(arguments);
        } catch (e) {
            var m = "";
            for (var i = 0; i < arguments.length; i++) {
                m += arguments[i] + ", ";
            }
            alert(m);
        }
    }
};

/**
 * delegate a function to an objec.
 * @param method {Function}
 * @param instance {Object}
 * @param [args] {Array} If provided, the function will receive this array as arguments instead of the provided by the caller.
 * @return {Function}
 */
var delegate = function (method, instance, args ) {
    return function() {
        if (args) {
            return method.apply(instance, args);
        } else {
            return method.apply(instance, arguments);
        }
    }
}

var getClassName = function (classReference) {
    // search through the global object for a name that resolves to this object
    for (var name in this)
        if (this[name] == classReference)
            return name
}

/**
 *
 * @return {Function}
 * @constructor
 */
var PacaClass = function() {

    var args = arguments;

    var pacaclass = function(){
        this.constructor && this.constructor.apply(this,arguments);
    };
    pacaclass.supers = [];
    pacaclass.prototype.__class__ = pacaclass;
    pacaclass.prototype.destroy = function() {
        // empty destructor
    }
    pacaclass.prototype.getSuper = function(requestedSuper){

        var len = this.__class__.supers.length;
        for (var i = 0; i < len; i++) {
            var _super = this.__class__.supers[i];
            if (_super == requestedSuper) {
                return _super.prototype;
            }
        }

        throw new Error("getSuper: " + getClassName(requestedSuper) + " is not a superclass of " + getClassName(this.__class__))

    }

    pacaclass.prototype.delegate = function(method, args) {
        return delegate(method, this, args);
    }

    pacaclass.prototype.isInstance = function(requestedSuper) {
        if (this instanceof requestedSuper) {
            return true;
        }
        var len = this.__class__.supers.length;
        for (var i = 0; i < len; i++) {
            var _super = this.__class__.supers[i];
            if (_super == requestedSuper) {
                return true;
            }
            if (_super.prototype.isInstance && _super.prototype.isInstance(requestedSuper)) {
                return true;
            }
        }
        return false;
    }
    if (typeof args[0] == "string") {
        pacaclass.__name__ = args[0];
        var na = []
        for (var i = 1; i < args.length; i++) {
            na.push(args[i]);
        }
        args = na;
    }

    if (!args.length) {
        return pacaclass;
    }

    var copyProto = function(sub, _super) {
        var thinF = function(){};
        thinF.prototype = _super.prototype;
        var newProto = new thinF();
        for (var i in sub.prototype) {
            newProto[i] = sub.prototype[i];
        }
        sub.prototype = newProto;
    }

    //var supers = [];
    var single = function(sub, _super) {
        copyProto(sub, _super);

        if( _super.prototype.constructor == Object.prototype.constructor ){
            _super.prototype.constructor = _super;
        }

    }

    var multi = function(sub,_super){

        var proto = _super.prototype;
        for (var f in proto) {
            if (sub.prototype[f] === undefined) {
                if (proto[f] == "function") {
                    sub.prototype[f] = function() {
                        return proto[f].apply(this,arguments);
                    }
                } else {
                    sub.prototype[f] = proto[f];
                }
            }
        }
    }

    single(pacaclass, args[0]);
    pacaclass.supers.push(args[0]);
    if (args[0].supers.length) {
        pacaclass.supers = pacaclass.supers.concat(args[0].supers);
    }
    for( var i = 1; i < args.length; i++){
        multi(pacaclass, args[i]);
        pacaclass.supers.push(args[i]);
        if (args[i].supers.length) {
            pacaclass.supers = pacaclass.supers.concat(args[i].supers);
        }
    }

    return pacaclass;

};

PacaClass.settings = {
    /**
     * JS include base path. Makes code portable.
     */
    JS_PATH:''
};

/**
 * Dynamically include js files
 * @param src {String}
 * @param [async] {Boolean}
 * @param [async_listener] {Function}
 */
PacaClass.include = function(src, async, async_listener) {

    if (!async) {
        async = false;
    }
    var async_listener = async_listener;

    function GetHttpRequest() {
        if ( window.XMLHttpRequest ) // Gecko
            return new XMLHttpRequest();
        else if ( window.ActiveXObject ) // IE
            return new ActiveXObject("MsXml2.XmlHttp") ;
    }
    function IncludeJS(sId, fileUrl, source) {
        if (source != null && !document.getElementById(sId)) {
            var oHead = document.getElementsByTagName('HEAD').item(0);
            var oScript = document.createElement("script");
            oScript.language = "javascript";
            oScript.type = "text/javascript";
            oScript.id = sId;
            oScript.defer = true;
            oScript.text = source;
            oHead.appendChild(oScript);
        }
    }
    function AjaxPage(sId, url, async) {
        var sId = sId;
        var async = async;
        var oXmlHttp = GetHttpRequest();
        oXmlHttp.OnReadyStateChange = function() {
            if (oXmlHttp.readyState == 4) {
                if (oXmlHttp.status == 200 || oXmlHttp.status == 304) {
                    if (async) {
                        IncludeJS(sId, url, oXmlHttp.responseText);
                        if (async_listener) {
                            async_listener(sId);
                        }
                    }
                } else {
                    log( 'XML request error: ' + oXmlHttp.statusText + ' (' + oXmlHttp.status + ')' ) ;
                }
            }
        }
        oXmlHttp.open('GET', url, async);
        oXmlHttp.send(null);
        if (!async) {
            IncludeJS(sId, url, oXmlHttp.responseText);
        }
    }
    if (src.indexOf("http") != -1) {
        AjaxPage(src, src, async);
    } else {
        AjaxPage(src, PacaClass.settings.JS_PATH + src, async);
    }
}
<commit_msg>make class variable be named after the class name<commit_after>/***************
 http://github.com/francescortiz/pacaclass

 ****************/

/**
 * Simple logger
 */
var log = function () {
    var stderr = document.getElementById('stderr');
    if (stderr) {
        var m = "";
        for (var i = 0; i < arguments.length; i++) {
            m += arguments[i] + ", ";
        }
        stderr.innerHTML += m + "
";
    } else {
        try {
            console.log(arguments);
        } catch (e) {
            var m = "";
            for (var i = 0; i < arguments.length; i++) {
                m += arguments[i] + ", ";
            }
            alert(m);
        }
    }
};

/**
 * delegate a function to an objec.
 * @param method {Function}
 * @param instance {Object}
 * @param [args] {Array} If provided, the function will receive this array as arguments instead of the provided by the caller.
 * @return {Function}
 */
var delegate = function (method, instance, args) {
    return function () {
        if (args) {
            return method.apply(instance, args);
        } else {
            return method.apply(instance, arguments);
        }
    }
}

var getClassName = function (classReference) {
    // search through the global object for a name that resolves to this object
    for (var name in this)
        if (this[name] == classReference)
            return name;
}

/**
 *
 * @return {Function}
 * @constructor
 */
var PacaClass = function () {

    var className = "PacaClass";

    var args = arguments ? arguments : [];

    if (typeof args[0] == "string") {
        var className = args[0];
        var na = [];
        for (var i = 1; i < args.length; i++) {
            na.push(args[i]);
        }
        args = na;
    }

    var pacaclass;
    eval("var " + className + " = function(){this.constructor && this.constructor.apply(this,arguments);};");
    eval("pacaclass = " + className);
    pacaclass.__name__ = className;
    pacaclass.supers = [];
    pacaclass.prototype.__class__ = pacaclass;
    pacaclass.prototype.destroy = function () {
        // empty destructor
    }
    pacaclass.prototype.getSuper = function (requestedSuper) {

        var len = this.__class__.supers.length;
        for (var i = 0; i < len; i++) {
            var _super = this.__class__.supers[i];
            if (_super == requestedSuper) {
                return _super.prototype;
            }
        }

        throw new Error("getSuper: " + getClassName(requestedSuper) + " is not a superclass of " + getClassName(this.__class__))

    }

    pacaclass.prototype.delegate = function (method, args) {
        return delegate(method, this, args);
    }

    pacaclass.prototype.isInstance = function (requestedSuper) {
        if (this instanceof requestedSuper) {
            return true;
        }
        var len = this.__class__.supers.length;
        for (var i = 0; i < len; i++) {
            var _super = this.__class__.supers[i];
            if (_super == requestedSuper) {
                return true;
            }
            if (_super.prototype.isInstance && _super.prototype.isInstance(requestedSuper)) {
                return true;
            }
        }
        return false;
    }

    if (!args.length) {
        return pacaclass;
    }

    var copyProto = function (sub, _super) {
        var thinF = function () {
        };
        thinF.prototype = _super.prototype;
        var newProto = new thinF();
        for (var i in sub.prototype) {
            newProto[i] = sub.prototype[i];
        }
        sub.prototype = newProto;
    }

    //var supers = [];
    var single = function (sub, _super) {
        copyProto(sub, _super);

        if (_super.prototype.constructor == Object.prototype.constructor) {
            _super.prototype.constructor = _super;
        }

    }

    var multi = function (sub, _super) {

        var proto = _super.prototype;
        for (var f in proto) {
            if (sub.prototype[f] === undefined) {
                if (proto[f] == "function") {
                    sub.prototype[f] = function () {
                        return proto[f].apply(this, arguments);
                    }
                } else {
                    sub.prototype[f] = proto[f];
                }
            }
        }
    }

    single(pacaclass, args[0]);
    pacaclass.supers.push(args[0]);
    if (args[0].supers.length) {
        pacaclass.supers = pacaclass.supers.concat(args[0].supers);
    }
    for (var i = 1; i < args.length; i++) {
        multi(pacaclass, args[i]);
        pacaclass.supers.push(args[i]);
        if (args[i].supers.length) {
            pacaclass.supers = pacaclass.supers.concat(args[i].supers);
        }
    }

    return pacaclass;

};

PacaClass.settings = {
    /**
     * JS include base path. Makes code portable.
     */
    JS_PATH: ''
};

/**
 * Dynamically include js files
 * @param src {String}
 * @param [async] {Boolean}
 * @param [async_listener] {Function}
 */
PacaClass.include = function (src, async, async_listener) {

    if (!async) {
        async = false;
    }
    var async_listener = async_listener;

    function GetHttpRequest() {
        if (window.XMLHttpRequest) // Gecko
            return new XMLHttpRequest();
        else if (window.ActiveXObject) // IE
            return new ActiveXObject("MsXml2.XmlHttp");
    }

    function IncludeJS(sId, fileUrl, source) {
        if (source != null && !document.getElementById(sId)) {
            var oHead = document.getElementsByTagName('HEAD').item(0);
            var oScript = document.createElement("script");
            oScript.language = "javascript";
            oScript.type = "text/javascript";
            oScript.id = sId;
            oScript.defer = true;
            oScript.text = source;
            oHead.appendChild(oScript);
        }
    }

    function AjaxPage(sId, url, async) {
        var sId = sId;
        var async = async;
        var oXmlHttp = GetHttpRequest();
        oXmlHttp.OnReadyStateChange = function () {
            if (oXmlHttp.readyState == 4) {
                if (oXmlHttp.status == 200 || oXmlHttp.status == 304) {
                    if (async) {
                        IncludeJS(sId, url, oXmlHttp.responseText);
                        if (async_listener) {
                            async_listener(sId);
                        }
                    }
                } else {
                    log('XML request error: ' + oXmlHttp.statusText + ' (' + oXmlHttp.status + ')');
                }
            }
        }
        oXmlHttp.open('GET', url, async);
        oXmlHttp.send(null);
        if (!async) {
            IncludeJS(sId, url, oXmlHttp.responseText);
        }
    }

    if (src.indexOf("http") != -1) {
        AjaxPage(src, src, async);
    } else {
        AjaxPage(src, PacaClass.settings.JS_PATH + src, async);
    }
}
<|endoftext|>


<commit_before>/**
 * jQuery DFP v1.0.6
 * http://github.com/coop182/jquery.dfp.js
 *
 * Copyright 2013 Matt Cooper
 * Released under the MIT license
 */
(function ($, window) {

    "use strict";

    // Save Scope
    var dfpScript = this;

    // DFP account ID
    var dfpID = '';

    // Count of ads
    var count = 0;

    // Count of rendered ads
    var rendered = 0;

    // Default DFP jQuery selector
    var dfpSelector = '.adunit';

    /**
     * Init function sets required params and loads Google's DFP script
     * @param  String id       The DFP account ID
     * @param  String selector The adunit selector
     * @param  Object options  Custom options to apply
     */
    var init = function (id, selector, options) {

        dfpID = id || dfpID;
        dfpSelector = selector || dfpSelector;
        options = options || {};
        dfpLoader();
        $(function () { createAds(options); });

    };

    /**
     * Main function to find and create all Ads
     * @param Object options Custom options to apply
     */
    var createAds = function (options) {

        // Array to Store AdUnits
        var adUnitArray = [];

        // Default DFP options
        var URLTargets = getURLTargets();

        var dfpOptions = {
            'setTargeting': {
                'inURL': URLTargets.inURL,
                'URLIs': URLTargets.URLIs,
                'Query': URLTargets.Query,
                'Domain': window.location.host
            },
            'enableSingleRequest': true,
            'collapseEmptyDivs': 'original'
        };

        // Make sure the default setTargeting is not lost in the object merge
        if (typeof options.setTargeting !== 'undefined' && typeof dfpOptions.setTargeting !== 'undefined') {
            options.setTargeting = $.extend(options.setTargeting, dfpOptions.setTargeting);
        }

        // Merge options objects
        dfpOptions = $.extend(dfpOptions, options);

        // Loops through on page Ad units and gets ads for them.
        $(dfpSelector).each(function () {

            var adUnit = this;

            count++;

            // adUnit name
            var adUnitName = getName(adUnit);

            // adUnit id - this will use an existing id or an auto generated one.
            var adUnitID = getID(adUnit, adUnitName, count);

            // get dimensions of the adUnit
            var dimensions = getDimensions(adUnit);

            // get existing content
            var $existingContent = $(adUnit).html();

            // wipe html clean ready for ad and set the default display class.
            $(adUnit).html('').addClass('display-none');

            // Store AdUnits
            adUnitArray.push(adUnitID);

            // Push commands to DFP to create ads
            window.googletag.cmd.push(function () {

                // Create the ad
                var googleAdUnit = window.googletag.defineSlot('/' + dfpID + '/' + adUnitName, [dimensions.width, dimensions.height], adUnitID).addService(window.googletag.pubads());

                // Sets custom targeting for just THIS ad unit if it has been specified
                if (typeof $(adUnit).data("targeting") === 'object') {
                    $.each($(adUnit).data("targeting"), function (k, v) {
                        googleAdUnit.setTargeting(k, v);
                    });
                }

                // The following hijacks an internal google method to check if the div has been
                // collapsed after the ad has been attempted to be loaded.
                googleAdUnit.oldRenderEnded = googleAdUnit.renderEnded;
                googleAdUnit.renderEnded = function () {

                    rendered++;

                    var display = $(adUnit).css('display');

                    // if the div has been collapsed but there was existing content expand the
                    // div and reinsert the existing content.
                    if (display === 'none' && $.trim($existingContent).length > 0 && dfpOptions.collapseEmptyDivs === 'original') {
                        $(adUnit).show().html($existingContent);
                        display = 'block display-original';
                    }

                    $(adUnit).removeClass('display-none').addClass('display-' + display);

                    googleAdUnit.oldRenderEnded();

                    // Excute afterEachAdLoaded callback if provided
                    if (typeof dfpOptions.afterEachAdLoaded === 'function') {
                        dfpOptions.afterEachAdLoaded.call(this, adUnit);
                    }

                    // Excute afterAllAdsLoaded callback if provided
                    if (typeof dfpOptions.afterAllAdsLoaded === 'function' && rendered === count) {
                        dfpOptions.afterAllAdsLoaded.call(this, $(dfpSelector));
                    }

                };

            });

        });

        // Push DFP config options
        window.googletag.cmd.push(function () {

            if (dfpOptions.enableSingleRequest === true) {
                window.googletag.pubads().enableSingleRequest();
            }
            $.each(dfpOptions.setTargeting, function (k, v) {
                window.googletag.pubads().setTargeting(k, v);
            });
            if (dfpOptions.collapseEmptyDivs === true || dfpOptions.collapseEmptyDivs === 'original') {
                window.googletag.pubads().collapseEmptyDivs();
            }
            window.googletag.enableServices();

        });

        // Display each ad
        $.each(adUnitArray, function (k, v) {

            window.googletag.cmd.push(function () { window.googletag.display(v); });

        });

    };

    /**
     * Create an array of paths so that we can target DFP ads to Page URI's
     * @return Array an array of URL parts that can be targeted.
     */
    var getURLTargets = function () {

        // Get the paths for targeting against
        var paths = window.location.pathname.replace(/\/$/, '');
        var patt = new RegExp('\/([^\/]*)', 'ig');
        var pathsMatches = paths.match(patt);
        var targetPaths = ['/'];
        var longestpath = '';
        if (paths !== '/' && pathsMatches !== null) {
            var target = '';
            var size = pathsMatches.length;
            if (size > 0) {
                for (var i = 0; i < size; i++) {
                    target = pathsMatches[i];
                    targetPaths.push(target);
                    for (var j = i + 1; j < size; j++) {
                        target += pathsMatches[j];
                        targetPaths.push(target);
                    }
                    if (i === 0) {
                        targetPaths.splice(-1, 1);
                        longestpath = target;
                    }
                }
            }
            targetPaths.push(longestpath);
        }

        targetPaths = targetPaths.reverse();

        // Get the query params for targeting against
        var url = window.location.toString().replace(/\=/ig, ':').match(/\?(.+)$/);
        var params = RegExp.$1.split("&");

        return {
            'inURL': targetPaths,
            'URLIs': targetPaths[0],
            'Query': params
        };

    };

    /**
     * Get the id of the adUnit div or generate a unique one.
     * @param  Object adUnit     The adunit to work with
     * @param  String adUnitName The name of the adunit
     * @param  Integer count     The current count of adunit, for uniqueness
     * @return String             The ID of the adunit or a unique autogenerated ID
     */
    var getID = function (adUnit, adUnitName, count) {

        var id = adUnit.id;
        if (id === '')
        {
            id = adUnit.id = adUnitName + '-auto-gen-id-' + count;
        }

        return id;

    };

    /**
     * Get the name of the Ad unit, either use the div id or
     * check for the optional attribute data-adunit
     * @param  Object adUnit The adunit to work with
     * @return String        The name of the adunit, will be the same as inside DFP
     */
    var getName = function (adUnit) {

        var name = adUnit.id;
        if (typeof $(adUnit).data('adunit') !== 'undefined') {

            name = $(adUnit).data('adunit');

        }

        return name;

    };

    /**
     * Get the dimensions of the ad unit using the cotainer div dimensions or
     * check for the optional attribute data-dimensions
     * @param  Object adUnit The adunit to work with
     * @return Array         The dimensions of the adunit (width, height)
     */
    var getDimensions = function (adUnit) {

        var width = $(adUnit).width();
        var height = $(adUnit).height();

        // check if dimensions are hardcoded and overide the size
        if (typeof $(adUnit).data('dimensions') !== 'undefined') {

            var dimensions = $(adUnit).data('dimensions').split('x');
            width = parseInt(dimensions[0], 10);
            height = parseInt(dimensions[1], 10);

        }

        return {width: width, height: height};

    };

    /**
     * Call the google DFP script - there is a little bit of error detection in here to detect
     * if the dfp script has failed to load either through an error or it being blocked by an ad
     * blocker... if it does not load we execute a dummy script to replace the real DFP.
     */
    var dfpLoader = function () {

        window.googletag = window.googletag || {};
        window.googletag.cmd = window.googletag.cmd || [];

        var gads = document.createElement('script');
        gads.async = true;
        gads.type = 'text/javascript';

        // Adblock blocks the load of Ad scripts... so we check for that
        gads.onerror = function () {
            dfpBlocked();
        };

        var useSSL = 'https:' === document.location.protocol;
        gads.src = (useSSL ? 'https:' : 'http:') +
        '//www.googletagservices.com/tag/js/gpt.js';
        var node = document.getElementsByTagName('script')[0];
        node.parentNode.insertBefore(gads, node);

        // Adblock plus seems to hide blocked scripts... so we check for that
        if (gads.style.display === 'none') {
            dfpBlocked();
        }

    };

    /**
     * This function gets called if DFP has been blocked by an adblocker
     * it implements a dummy version of the dfp object and allows the script to excute its callbacks
     * regardless of wheather DFP is actually loaded or not... it is basically only useful for situations
     * where you are laying DFP over existing content and need to init things like slide shows after the loading
     * is completed.
     */
    var dfpBlocked = function () {

        // Get the stored dfp commands
        var commands = window.googletag.cmd;

        // SetTimeout is a bit dirty but the script does not execute in the correct order without it
        setTimeout(function () {

            // overwrite the dfp object - replacing the command array with a function and defining missing functions
            window.googletag = {
                cmd: {
                    push: function (callback) {
                        callback.call(dfpScript);
                    }
                },
                ads: [],
                pubads: function () { return this; },
                enableSingleRequest: function () { return this; },
                setTargeting: function () { return this; },
                collapseEmptyDivs: function () { return this; },
                enableServices: function () { return this; },
                defineSlot: function (name, dimensions, id) {
                    window.googletag.ads.push(id);
                    window.googletag.ads[id] = {
                        renderEnded: function () {},
                        addService: function () { return this; }
                    };
                    return window.googletag.ads[id];
                },
                display: function (id) {
                    window.googletag.ads[id].renderEnded.call(dfpScript);
                    return this;
                }

            };

            // Execute any stored commands
            $.each(commands, function (k, v) {
                window.googletag.cmd.push(v);
            });

        }, 50);

    };

    /**
     * Add function to the jQuery namespace
     * @param  String id      (Optional) The DFP account ID
     * @param  Object options (Optional) Custom options to apply
     */
    $.dfp = $.fn.dfp = function (id, options) {

        options = options || {};

        if (typeof id === 'undefined') {
            id = dfpID;
        }

        if (typeof id === 'object') {
            options = id;
            id = options.dfpID || dfpID;
        }

        var selector = this;

        if (typeof this === 'function') {
            selector = dfpSelector;
        }

        init(id, selector, options);

    };

})(window.jQuery, window);
<commit_msg>add check so gpt.js is only loaded once<commit_after>/**
 * jQuery DFP v1.0.6
 * http://github.com/coop182/jquery.dfp.js
 *
 * Copyright 2013 Matt Cooper
 * Released under the MIT license
 */
(function ($, window) {

    "use strict";

    // Save Scope
    var dfpScript = this;

    // DFP account ID
    var dfpID = '';

    // Count of ads
    var count = 0;

    // Count of rendered ads
    var rendered = 0;

    // Default DFP jQuery selector
    var dfpSelector = '.adunit';

    // Keep track of if we've already tried to load gpt.js before
    var dfpIsLoaded = false;

    /**
     * Init function sets required params and loads Google's DFP script
     * @param  String id       The DFP account ID
     * @param  String selector The adunit selector
     * @param  Object options  Custom options to apply
     */
    var init = function (id, selector, options) {

        dfpID = id || dfpID;
        dfpSelector = selector || dfpSelector;
        options = options || {};
        dfpLoader();
        $(function () { createAds(options); });

    };

    /**
     * Main function to find and create all Ads
     * @param Object options Custom options to apply
     */
    var createAds = function (options) {

        // Array to Store AdUnits
        var adUnitArray = [];

        // Default DFP options
        var URLTargets = getURLTargets();

        var dfpOptions = {
            'setTargeting': {
                'inURL': URLTargets.inURL,
                'URLIs': URLTargets.URLIs,
                'Query': URLTargets.Query,
                'Domain': window.location.host
            },
            'enableSingleRequest': true,
            'collapseEmptyDivs': 'original'
        };

        // Make sure the default setTargeting is not lost in the object merge
        if (typeof options.setTargeting !== 'undefined' && typeof dfpOptions.setTargeting !== 'undefined') {
            options.setTargeting = $.extend(options.setTargeting, dfpOptions.setTargeting);
        }

        // Merge options objects
        dfpOptions = $.extend(dfpOptions, options);

        // Loops through on page Ad units and gets ads for them.
        $(dfpSelector).each(function () {

            var adUnit = this;

            count++;

            // adUnit name
            var adUnitName = getName(adUnit);

            // adUnit id - this will use an existing id or an auto generated one.
            var adUnitID = getID(adUnit, adUnitName, count);

            // get dimensions of the adUnit
            var dimensions = getDimensions(adUnit);

            // get existing content
            var $existingContent = $(adUnit).html();

            // wipe html clean ready for ad and set the default display class.
            $(adUnit).html('').addClass('display-none');

            // Store AdUnits
            adUnitArray.push(adUnitID);

            // Push commands to DFP to create ads
            window.googletag.cmd.push(function () {

                // Create the ad
                var googleAdUnit = window.googletag.defineSlot('/' + dfpID + '/' + adUnitName, [dimensions.width, dimensions.height], adUnitID).addService(window.googletag.pubads());

                // Sets custom targeting for just THIS ad unit if it has been specified
                if (typeof $(adUnit).data("targeting") === 'object') {
                    $.each($(adUnit).data("targeting"), function (k, v) {
                        googleAdUnit.setTargeting(k, v);
                    });
                }

                // The following hijacks an internal google method to check if the div has been
                // collapsed after the ad has been attempted to be loaded.
                googleAdUnit.oldRenderEnded = googleAdUnit.renderEnded;
                googleAdUnit.renderEnded = function () {

                    rendered++;

                    var display = $(adUnit).css('display');

                    // if the div has been collapsed but there was existing content expand the
                    // div and reinsert the existing content.
                    if (display === 'none' && $.trim($existingContent).length > 0 && dfpOptions.collapseEmptyDivs === 'original') {
                        $(adUnit).show().html($existingContent);
                        display = 'block display-original';
                    }

                    $(adUnit).removeClass('display-none').addClass('display-' + display);

                    googleAdUnit.oldRenderEnded();

                    // Excute afterEachAdLoaded callback if provided
                    if (typeof dfpOptions.afterEachAdLoaded === 'function') {
                        dfpOptions.afterEachAdLoaded.call(this, adUnit);
                    }

                    // Excute afterAllAdsLoaded callback if provided
                    if (typeof dfpOptions.afterAllAdsLoaded === 'function' && rendered === count) {
                        dfpOptions.afterAllAdsLoaded.call(this, $(dfpSelector));
                    }

                };

            });

        });

        // Push DFP config options
        window.googletag.cmd.push(function () {

            if (dfpOptions.enableSingleRequest === true) {
                window.googletag.pubads().enableSingleRequest();
            }
            $.each(dfpOptions.setTargeting, function (k, v) {
                window.googletag.pubads().setTargeting(k, v);
            });
            if (dfpOptions.collapseEmptyDivs === true || dfpOptions.collapseEmptyDivs === 'original') {
                window.googletag.pubads().collapseEmptyDivs();
            }
            window.googletag.enableServices();

        });

        // Display each ad
        $.each(adUnitArray, function (k, v) {

            window.googletag.cmd.push(function () { window.googletag.display(v); });

        });

    };

    /**
     * Create an array of paths so that we can target DFP ads to Page URI's
     * @return Array an array of URL parts that can be targeted.
     */
    var getURLTargets = function () {

        // Get the paths for targeting against
        var paths = window.location.pathname.replace(/\/$/, '');
        var patt = new RegExp('\/([^\/]*)', 'ig');
        var pathsMatches = paths.match(patt);
        var targetPaths = ['/'];
        var longestpath = '';
        if (paths !== '/' && pathsMatches !== null) {
            var target = '';
            var size = pathsMatches.length;
            if (size > 0) {
                for (var i = 0; i < size; i++) {
                    target = pathsMatches[i];
                    targetPaths.push(target);
                    for (var j = i + 1; j < size; j++) {
                        target += pathsMatches[j];
                        targetPaths.push(target);
                    }
                    if (i === 0) {
                        targetPaths.splice(-1, 1);
                        longestpath = target;
                    }
                }
            }
            targetPaths.push(longestpath);
        }

        targetPaths = targetPaths.reverse();

        // Get the query params for targeting against
        var url = window.location.toString().replace(/\=/ig, ':').match(/\?(.+)$/);
        var params = RegExp.$1.split("&");

        return {
            'inURL': targetPaths,
            'URLIs': targetPaths[0],
            'Query': params
        };

    };

    /**
     * Get the id of the adUnit div or generate a unique one.
     * @param  Object adUnit     The adunit to work with
     * @param  String adUnitName The name of the adunit
     * @param  Integer count     The current count of adunit, for uniqueness
     * @return String             The ID of the adunit or a unique autogenerated ID
     */
    var getID = function (adUnit, adUnitName, count) {

        var id = adUnit.id;
        if (id === '')
        {
            id = adUnit.id = adUnitName + '-auto-gen-id-' + count;
        }

        return id;

    };

    /**
     * Get the name of the Ad unit, either use the div id or
     * check for the optional attribute data-adunit
     * @param  Object adUnit The adunit to work with
     * @return String        The name of the adunit, will be the same as inside DFP
     */
    var getName = function (adUnit) {

        var name = adUnit.id;
        if (typeof $(adUnit).data('adunit') !== 'undefined') {

            name = $(adUnit).data('adunit');

        }

        return name;

    };

    /**
     * Get the dimensions of the ad unit using the cotainer div dimensions or
     * check for the optional attribute data-dimensions
     * @param  Object adUnit The adunit to work with
     * @return Array         The dimensions of the adunit (width, height)
     */
    var getDimensions = function (adUnit) {

        var width = $(adUnit).width();
        var height = $(adUnit).height();

        // check if dimensions are hardcoded and overide the size
        if (typeof $(adUnit).data('dimensions') !== 'undefined') {

            var dimensions = $(adUnit).data('dimensions').split('x');
            width = parseInt(dimensions[0], 10);
            height = parseInt(dimensions[1], 10);

        }

        return {width: width, height: height};

    };

    /**
     * Call the google DFP script - there is a little bit of error detection in here to detect
     * if the dfp script has failed to load either through an error or it being blocked by an ad
     * blocker... if it does not load we execute a dummy script to replace the real DFP.
     */
    var dfpLoader = function () {

        // make sure we don't load gpt.js multiple times
        dfpIsLoaded = dfpIsLoaded || $('script[src*="googletagservices.com/tag/js/gpt.js"]').length;
        if (dfpIsLoaded){
            return;
        }

        window.googletag = window.googletag || {};
        window.googletag.cmd = window.googletag.cmd || [];

        var gads = document.createElement('script');
        gads.async = true;
        gads.type = 'text/javascript';

        // Adblock blocks the load of Ad scripts... so we check for that
        gads.onerror = function () {
            dfpBlocked();
        };

        var useSSL = 'https:' === document.location.protocol;
        gads.src = (useSSL ? 'https:' : 'http:') +
        '//www.googletagservices.com/tag/js/gpt.js';
        var node = document.getElementsByTagName('script')[0];
        node.parentNode.insertBefore(gads, node);

        // Adblock plus seems to hide blocked scripts... so we check for that
        if (gads.style.display === 'none') {
            dfpBlocked();
        }

    };

    /**
     * This function gets called if DFP has been blocked by an adblocker
     * it implements a dummy version of the dfp object and allows the script to excute its callbacks
     * regardless of wheather DFP is actually loaded or not... it is basically only useful for situations
     * where you are laying DFP over existing content and need to init things like slide shows after the loading
     * is completed.
     */
    var dfpBlocked = function () {

        // Get the stored dfp commands
        var commands = window.googletag.cmd;

        // SetTimeout is a bit dirty but the script does not execute in the correct order without it
        setTimeout(function () {

            // overwrite the dfp object - replacing the command array with a function and defining missing functions
            window.googletag = {
                cmd: {
                    push: function (callback) {
                        callback.call(dfpScript);
                    }
                },
                ads: [],
                pubads: function () { return this; },
                enableSingleRequest: function () { return this; },
                setTargeting: function () { return this; },
                collapseEmptyDivs: function () { return this; },
                enableServices: function () { return this; },
                defineSlot: function (name, dimensions, id) {
                    window.googletag.ads.push(id);
                    window.googletag.ads[id] = {
                        renderEnded: function () {},
                        addService: function () { return this; }
                    };
                    return window.googletag.ads[id];
                },
                display: function (id) {
                    window.googletag.ads[id].renderEnded.call(dfpScript);
                    return this;
                }

            };

            // Execute any stored commands
            $.each(commands, function (k, v) {
                window.googletag.cmd.push(v);
            });

        }, 50);

    };

    /**
     * Add function to the jQuery namespace
     * @param  String id      (Optional) The DFP account ID
     * @param  Object options (Optional) Custom options to apply
     */
    $.dfp = $.fn.dfp = function (id, options) {

        options = options || {};

        if (typeof id === 'undefined') {
            id = dfpID;
        }

        if (typeof id === 'object') {
            options = id;
            id = options.dfpID || dfpID;
        }

        var selector = this;

        if (typeof this === 'function') {
            selector = dfpSelector;
        }

        init(id, selector, options);

    };

})(window.jQuery, window);
<|endoftext|>


<commit_before>Registrants = new Meteor.Collection("registrants");
Registrants.attachSchema(new SimpleSchema({
    'first_name' :{
        type: String,
        label: "First Name",
        max: 200
    },
    'last_name': {
        type: String,
        label: "Last Name",
        max: 200
    },
    ageGroup: {
        type: String,
        allowedValues: [
            'child',
            'youth',
            'teen',
            'youngAdult',
            'adult'
        ]
    },
    registrationType: {
        type: String,
        allowedValues: [
            'commuter',
            'daily',
            'weekly'
        ]
    },
    accommodations: {
        type: String,
        allowedValues: [
            'camping',
            'semiprivate',
            'private',
            'jym',
            'yaf'
        ],
        optional: true,
        custom: function () {
            // Required if registration is daily or weekly
            if ( !this.isSet
                &&
                (
                this.field('registrationType').value === "daily"
                ||
                this.field('registrationType').value === "weekly")
               ) {
                return "required";
            }
        }
    },
    days: {
        type: [String],
        optional: true,
        autoform: {
            type: "select-checkbox-inline",
            options: function () {
                return [
                    {label: "Monday", value: "Monday"},
                    {label: "Tuesday", value: "Tuesday"},
                    {label: "Wednesday", value: "Wednesday"},
                    {label: "Thursday", value: "Thursday"},
                    {label: "Friday", value: "Friday"},
                    {label: "Saturday", value: "Saturday"}
                ];
            }
        }
    }
}));

// Permissions
Registrants.allow({
    insert: function () {
        // TODO: consider whether user should be logged in to register
        // otherwise, collect registration details on registration form
        return true;
    },
    update: function () {
        // TODO: change permissions
        // e.g. if user.role === 'registrair' or user._id === registration.ownerId
        return true;
    },
    remove: function () {
        // TODO: change permissions
        // e.g. if user.role === 'registrair' or user._id === registration.ownerId
        return true;
    }
});

SimpleSchema.messages({
    departAfterArrive: "The departure date must be after the arrival date."
});
<commit_msg>Added fee auto value.<commit_after>Registrants = new Meteor.Collection("registrants");
Registrants.attachSchema(new SimpleSchema({
    'first_name' :{
        type: String,
        label: "First Name",
        max: 200
    },
    'last_name': {
        type: String,
        label: "Last Name",
        max: 200
    },
    ageGroup: {
        type: String,
        allowedValues: [
            'child',
            'youth',
            'teen',
            'youngAdult',
            'adult'
        ]
    },
    registrationType: {
        type: String,
        allowedValues: [
            'commuter',
            'daily',
            'weekly'
        ]
    },
    accommodations: {
        type: String,
        allowedValues: [
            'camping',
            'semiprivate',
            'private',
            'jym',
            'yaf'
        ],
        optional: true,
        custom: function () {
            // Required if registration is daily or weekly
            if ( !this.isSet
                &&
                (
                this.field('registrationType').value === "daily"
                ||
                this.field('registrationType').value === "weekly")
               ) {
                return "required";
            }
        }
    },
    days: {
        type: [String],
        optional: true,
        autoform: {
            type: "select-checkbox-inline",
            options: function () {
                return [
                    {label: "Monday", value: "Monday"},
                    {label: "Tuesday", value: "Tuesday"},
                    {label: "Wednesday", value: "Wednesday"},
                    {label: "Thursday", value: "Thursday"},
                    {label: "Friday", value: "Friday"},
                    {label: "Saturday", value: "Saturday"}
                ];
            }
        }
    },
    'fee' : {
        type: Number,
        label: "Fee",
        optional: true,
        autoValue: function (doc ) {
            // Set up an empty registration object
            // to hold values from the submitted registration
            var registration = {};

            // get values from submitted registration and
            // set attributes on the registration object
            registration.ageGroup = this.field("ageGroup").value;
            registration.type = this.field("registrationType").value;
            registration.accommodations = this.field("accommodations").value;
            registration.days =  this.field("days").value;

            // calculate the registration fee
            // based on the submitted registration
            return calculateRegistrationPrice(registration);
        }
    }
}));

// Permissions
Registrants.allow({
    insert: function () {
        // TODO: consider whether user should be logged in to register
        // otherwise, collect registration details on registration form
        return true;
    },
    update: function () {
        // TODO: change permissions
        // e.g. if user.role === 'registrair' or user._id === registration.ownerId
        return true;
    },
    remove: function () {
        // TODO: change permissions
        // e.g. if user.role === 'registrair' or user._id === registration.ownerId
        return true;
    }
});

SimpleSchema.messages({
    departAfterArrive: "The departure date must be after the arrival date."
});
<|endoftext|>


<commit_before>var GitHubStrategy = require('passport-github').Strategy;
var User            = require('../models/user');
var env = require('../env.js');

module.exports = function(passport){
  passport.use(new GitHubStrategy({
    clientID: env.clientID,
    clientSecret: env.clientSecret,
    callbackURL: env.callbackURL
  }, function(token, secret, profile, done){
    process.nextTick(function(){
      User.findOne({'github.id': profile.id}, function(err, user){
        if(err) return done(err);

        // If the user already exists, just return that user.
        if(user){
          return done(null, user);
        } else {
          // Otherwise, create a brand new user using information passed from GH.
          var newUser = new User();
          // Here we're saving information passed to us from GH.
          newUser.github.id = profile.id;
          newUser.github.token = token;
          newUser.github.username = profile.username;
          newUser.github.displayName = profile.displayName;

          newUser.save(function(err){
            if(err) throw err;
            return done(null, newUser);
          })
        }
      })
    })
  }));

  // }, function(accessToken, refreshToken, profile, done) {
  //   process.nextTick(function() {
  //     console.log(profile)
  //     return done(null, profile);
  //   });
  // }));
  passport.serializeUser(function(user, done) {
    done(null, user);
  });
  passport.deserializeUser(function(obj, done) {
    done(null, obj);
  });
}
<commit_msg>add profile from passport.js<commit_after>var GitHubStrategy = require('passport-github').Strategy;
var User            = require('../models/user');
var env = require('../env.js');
var Profile = require("../models/profile");
var Stamp = require("../models/stamp");
var Functions = require("../db/schemaMethods");

module.exports = function(passport){
  passport.use(new GitHubStrategy({
    clientID: env.clientID,
    clientSecret: env.clientSecret,
    callbackURL: env.callbackURL
  }, function(token, secret, profile, done){
    process.nextTick(function(){
      User.findOne({'github.id': profile.id}, function(err, user){
        if(err) return done(err);

        // If the user already exists, just return that user.
        if(user){
          return done(null, user);
        } else {
          // Otherwise, create a brand new user using information passed from GH.
          var newUser = new User();
          // Here we're saving information passed to us from GH.
          newUser.github.id = profile.id;
          newUser.github.token = token;
          newUser.github.username = profile.username;
          newUser.github.displayName = profile.displayName;

          Profile.findOne({'username': newUser.github.username}, function(err, profile){
            if(err) return err;

            if (profile){
              console.log(newUser.github.username + " already in the database")
              // followProfile(req.user._id,profile,res)
            }else{
              var newProfile = new Profile({'username': newUser.github.username}).save(function(err, newProfile){
                if(!err){
                  console.log(newUser.github.username + " saved in the database")
                }
                newUser.follows.push(newProfile._id)
                newUser.save(function(err){
                  if(err) throw err;
                  return done(null, newUser);
                })
              })
            }
          })
        }
      })
    })
  }));

  passport.serializeUser(function(user, done) {
    done(null, user);
  });
  passport.deserializeUser(function(obj, done) {
    done(null, obj);
  });
}
<|endoftext|>


<commit_before>import React from 'react';

import FileDropArea from './FileDropArea';
import PreviewImage from './PreviewImage';
import FileTransferButtons from './FileTransferButtons';

const CanvasExifOrientation = require('canvas-exif-orientation');

const ALLOW_FILE_TYPES = ['image/png', 'image/jpeg'];

const ORIENTATION_NUMBER = {
  0: 1,
  90: 6,
  180: 3,
  270: 8,
};

const createImageDataUrl = (image, mime) => {
  const canvas = document.createElement('canvas');
  canvas.width = image.width;
  canvas.height = image.height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(image, 0, 0, image.width, image.height);
  return canvas.toDataURL(mime);
};

const rotateImage = (currentImage, angle, mime) =>
  new Promise(resolve => {
    const orietationNumber = ORIENTATION_NUMBER[angle];
    const canvasElement = CanvasExifOrientation.drawImage(
      currentImage,
      orietationNumber
    );
    const dataUrl = createImageDataUrl(canvasElement, mime);
    const image = new Image();
    image.onload = () => resolve(image);
    image.src = dataUrl;
  });

const autoDownload = (url, fileName) => {
  const elem = document.createElement('a');
  elem.href = url;
  elem.download = fileName;
  elem.click();
};

const isAllowedFileType = (uploadedFileType, allowList) => {
  const result = allowList.filter(allowFile => allowFile === uploadedFileType);
  return !!(result.length > 0);
};

export default class ImageEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userSettings: {
        resizeRatio: 0.5,
        rotateAngle: 0,
      },
      uploadImageDataUrl: null,
      previewImageDataUrl: null,
      downloadImageFileName: null,
      fileMime: null,
      allowAutoDownload: true,
      errorMessage: null,
    };
    this.onImageSelected = this.onImageSelected.bind(this);
    this.onImageLoad = this.onImageLoad.bind(this);
  }

  onImageLoad(imageDataUrl, originalFileName, originalFileMime) {
    this.setState({
      uploadImageDataUrl: imageDataUrl,
      downloadImageFileName: originalFileName,
      fileMime: originalFileMime,
    });
    this.processImage();
  }

  onImageSelected(fileList) {
    const file = fileList[0];
    if (!isAllowedFileType(file.type, ALLOW_FILE_TYPES)) {
      this.setState({errorMessage: '対応しているファイル形式はjpegとpngのみです。'});
      return;
    }
    const fileReader = new FileReader();
    fileReader.onload = () => {
      this.onImageLoad(fileReader.result, file.name, file.type);
    };
    fileReader.readAsDataURL(file);
  }

  processImage() {
    const {rotateAngle, resizeRatio} = this.state.userSettings;
    this.restoreUploadedImage()
      .then(res => rotateImage(res, rotateAngle, this.state.fileMime))
      .then(res => {
        res.width *= resizeRatio;
        res.height *= resizeRatio;
        return res;
      })
      .then(res => {
        this.setState({
          previewImageDataUrl: createImageDataUrl(res, this.state.fileMime),
        });
        if (!this.state.allowAutoDownload) return;
        autoDownload(
          this.state.previewImageDataUrl,
          this.state.downloadImageFileName
        );
      });
  }

  restoreUploadedImage() {
    return new Promise(resolve => {
      const image = new Image();
      image.onload = () => {
        resolve(image);
      };
      image.src = this.state.uploadImageDataUrl;
    });
  }

  changeUserSettings(key, value) {
    const newUserSettings = Object.assign({}, this.state.userSettings, {
      [key]: value,
    });
    this.setState({userSettings: newUserSettings});
    if (!this.state.uploadImageDataUrl) return;
    this.processImage();
  }

  render() {
    const {
      previewImageDataUrl,
      downloadImageFileName,
      allowAutoDownload,
      errorMessage,
    } = this.state;
    return (

        <FileTransferButtons
          onImageSelected={e => {
            this.onImageSelected(e.target.files);
          }}
          previewImageDataUrl={previewImageDataUrl}
          downloadImageFileName={downloadImageFileName}
        />
        {previewImageDataUrl && (

            画像にドロップすることでも、新しい画像をアップロードできます。

            画像をクリックすると右回りで90度回転します。

        )}
        <form className="option-setting-area">
          <select
            defaultValue={this.state.userSettings.resizeRatio}
            onChange={e => {
              const {options} = e.target;
              this.changeUserSettings(
                'resizeRatio',
                +options[options.selectedIndex].value
              );
            }}
          >
            <option value={0.25}>25%</option>
            <option value={0.5}>50%</option>
            <option value={1}>100%</option>
            <option value={1.5}>150%</option>
            <option value={2}>200%</option>
          </select>
          <select
            defaultValue={this.state.userSettings.rotateAngle}
            onChange={e => {
              const {options} = e.target;
              this.changeUserSettings(
                'rotateAngle',
                +options[options.selectedIndex].value
              );
            }}
          >
            <option value={0}>回転しない</option>
            <option value={90}>時計回りに90度回転</option>
            <option value={180}>180度回転</option>
            <option value={270}>時計回りに270度回転</option>
          </select>

            <input
              id="option-setting"
              type="checkbox"
              checked={allowAutoDownload}
              onChange={e => {
                this.setState({allowAutoDownload: e.target.checked});
              }}
            />
            リサイズした画像を自動的にダウンロードする

        </form>
        {errorMessage &&
{errorMessage}
}
        {!previewImageDataUrl && <FileDropArea onDrop={this.onImageSelected} />}
        {previewImageDataUrl && (
          <PreviewImage
            src={previewImageDataUrl}
            onDrop={this.onImageSelected}
          />
        )}

    );
  }
}
<commit_msg>processImageには必ず最新の値が渡されるようにした。<commit_after>import React from 'react';

import FileDropArea from './FileDropArea';
import PreviewImage from './PreviewImage';
import FileTransferButtons from './FileTransferButtons';

const CanvasExifOrientation = require('canvas-exif-orientation');

const ALLOW_FILE_TYPES = ['image/png', 'image/jpeg'];

const ORIENTATION_NUMBER = {
  0: 1,
  90: 6,
  180: 3,
  270: 8,
};

const createImageDataUrl = (image, mime) => {
  const canvas = document.createElement('canvas');
  canvas.width = image.width;
  canvas.height = image.height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(image, 0, 0, image.width, image.height);
  return canvas.toDataURL(mime);
};

const rotateImage = (currentImage, angle, mime) =>
  new Promise(resolve => {
    const orietationNumber = ORIENTATION_NUMBER[angle];
    const canvasElement = CanvasExifOrientation.drawImage(
      currentImage,
      orietationNumber
    );
    const dataUrl = createImageDataUrl(canvasElement, mime);
    const image = new Image();
    image.onload = () => resolve(image);
    image.src = dataUrl;
  });

const autoDownload = (url, fileName) => {
  const elem = document.createElement('a');
  elem.href = url;
  elem.download = fileName;
  elem.click();
};

const isAllowedFileType = (uploadedFileType, allowList) => {
  const result = allowList.filter(allowFile => allowFile === uploadedFileType);
  return !!(result.length > 0);
};

export default class ImageEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userSettings: {
        resizeRatio: 0.5,
        rotateAngle: 0,
      },
      uploadImageDataUrl: null,
      previewImageDataUrl: null,
      downloadImageFileName: null,
      fileMime: null,
      allowAutoDownload: true,
      errorMessage: null,
    };
    this.onImageSelected = this.onImageSelected.bind(this);
    this.onImageLoad = this.onImageLoad.bind(this);
  }

  onImageLoad(imageDataUrl, originalFileName, originalFileMime) {
    this.setState({
      uploadImageDataUrl: imageDataUrl,
      downloadImageFileName: originalFileName,
      fileMime: originalFileMime,
    });
    this.processImage(this.state.userSettings);
  }

  onImageSelected(fileList) {
    const file = fileList[0];
    if (!isAllowedFileType(file.type, ALLOW_FILE_TYPES)) {
      this.setState({errorMessage: '対応しているファイル形式はjpegとpngのみです。'});
      return;
    }
    const fileReader = new FileReader();
    fileReader.onload = () => {
      this.onImageLoad(fileReader.result, file.name, file.type);
    };
    fileReader.readAsDataURL(file);
  }

  processImage(userSettings) {
    const {rotateAngle, resizeRatio} = userSettings;
    this.restoreUploadedImage()
      .then(res => rotateImage(res, rotateAngle, this.state.fileMime))
      .then(res => {
        res.width *= resizeRatio;
        res.height *= resizeRatio;
        return res;
      })
      .then(res => {
        this.setState({
          previewImageDataUrl: createImageDataUrl(res, this.state.fileMime),
        });
        if (!this.state.allowAutoDownload) return;
        autoDownload(
          this.state.previewImageDataUrl,
          this.state.downloadImageFileName
        );
      });
  }

  restoreUploadedImage() {
    return new Promise(resolve => {
      const image = new Image();
      image.onload = () => {
        resolve(image);
      };
      image.src = this.state.uploadImageDataUrl;
    });
  }

  changeUserSettings(key, value) {
    const newUserSettings = Object.assign({}, this.state.userSettings, {
      [key]: value,
    });
    this.setState({userSettings: newUserSettings});
    if (!this.state.uploadImageDataUrl) return;
    this.processImage(newUserSettings);
  }

  render() {
    const {
      previewImageDataUrl,
      downloadImageFileName,
      allowAutoDownload,
      errorMessage,
    } = this.state;
    return (

        <FileTransferButtons
          onImageSelected={e => {
            this.onImageSelected(e.target.files);
          }}
          previewImageDataUrl={previewImageDataUrl}
          downloadImageFileName={downloadImageFileName}
        />
        {previewImageDataUrl && (

            画像にドロップすることでも、新しい画像をアップロードできます。

            画像をクリックすると右回りで90度回転します。

        )}
        <form className="option-setting-area">
          <select
            defaultValue={this.state.userSettings.resizeRatio}
            onChange={e => {
              const {options} = e.target;
              this.changeUserSettings(
                'resizeRatio',
                +options[options.selectedIndex].value
              );
            }}
          >
            <option value={0.25}>25%</option>
            <option value={0.5}>50%</option>
            <option value={1}>100%</option>
            <option value={1.5}>150%</option>
            <option value={2}>200%</option>
          </select>
          <select
            defaultValue={this.state.userSettings.rotateAngle}
            onChange={e => {
              const {options} = e.target;
              this.changeUserSettings(
                'rotateAngle',
                +options[options.selectedIndex].value
              );
            }}
          >
            <option value={0}>回転しない</option>
            <option value={90}>時計回りに90度回転</option>
            <option value={180}>180度回転</option>
            <option value={270}>時計回りに270度回転</option>
          </select>

            <input
              id="option-setting"
              type="checkbox"
              checked={allowAutoDownload}
              onChange={e => {
                this.setState({allowAutoDownload: e.target.checked});
              }}
            />
            リサイズした画像を自動的にダウンロードする

        </form>
        {errorMessage &&
{errorMessage}
}
        {!previewImageDataUrl && <FileDropArea onDrop={this.onImageSelected} />}
        {previewImageDataUrl && (
          <PreviewImage
            src={previewImageDataUrl}
            onDrop={this.onImageSelected}
          />
        )}

    );
  }
}
<|endoftext|>


<commit_before>$(document).ready(function() {
  $("#sign_in_user").on("ajax:success", function(e, data, status, xhr) {
    window.location = '/'
  })
  $("#sign_in_user").on("ajax:error", function(e, data, status, xhr) {
    console.log("Failed to log in", data.responseJSON)
    $(".login-flashes p").remove()
    $(".login-flashes").append("
Invalid E-mail or Password
")
  })
  $("#sign_up_user").on("ajax:success", function(e, data, status, xhr) {
    console.log("Successfully registered user")
    $(".login-flashes p").remove()
    $(".login-flashes").append("
Check your e-mail for a link to confirm your account
")
    $(".login-flashes").append("
You must confirm your account before you can log in
")
  })
  $("#sign_up_user").on("ajax:error", function(e, data, status, xhr) {
    console.log("Failed to register user", data.responseJSON)
    console.log(data.responseJSON)
    $(".login-flashes p").remove()
    if (data.responseJSON.errors.email) {
      $(".login-flashes").append("
E-mail already in use or invalid
")
    }
    if (data.responseJSON.errors.user_name) {
      $(".login-flashes").append("
User name already in use or invalid
")
    }
  })
  $("#reset_password").on("ajax:success", function(e, data, status, xhr) {
    console.log("Successfully reset password")
    $(".login-flashes p").remove()
    $(".login-flashes").append("
Check your e-mail for a link to reset your password
")
  })
  $("#reset_password").on("ajax:error", function(e, data, status, xhr) {
    console.log("Failed to reset_password", data.responseJSON)
    $(".login-flashes p").remove()
    $(".login-flashes").append("
Invalid e-mail address
")
    $(".login-flashes").append("
Please verify it is correct and try again
")
  })
})
<commit_msg>This resolves the issue for AJAX sign-ins. Itdoes not change the behavior if they end up at the login page from redirect because that may break things in other devise plugins<commit_after>$(document).ready(function() {
  $("#sign_in_user").on("ajax:success", function(e, data, status, xhr) {
    window.location.reload(true)
  })
  $("#sign_in_user").on("ajax:error", function(e, data, status, xhr) {
    console.log("Failed to log in", data.responseJSON)
    $(".login-flashes p").remove()
    $(".login-flashes").append("
Invalid E-mail or Password
")
  })
  $("#sign_up_user").on("ajax:success", function(e, data, status, xhr) {
    console.log("Successfully registered user")
    $(".login-flashes p").remove()
    $(".login-flashes").append("
Check your e-mail for a link to confirm your account
")
    $(".login-flashes").append("
You must confirm your account before you can log in
")
  })
  $("#sign_up_user").on("ajax:error", function(e, data, status, xhr) {
    console.log("Failed to register user", data.responseJSON)
    console.log(data.responseJSON)
    $(".login-flashes p").remove()
    if (data.responseJSON.errors.email) {
      $(".login-flashes").append("
E-mail already in use or invalid
")
    }
    if (data.responseJSON.errors.user_name) {
      $(".login-flashes").append("
User name already in use or invalid
")
    }
  })
  $("#reset_password").on("ajax:success", function(e, data, status, xhr) {
    console.log("Successfully reset password")
    $(".login-flashes p").remove()
    $(".login-flashes").append("
Check your e-mail for a link to reset your password
")
  })
  $("#reset_password").on("ajax:error", function(e, data, status, xhr) {
    console.log("Failed to reset_password", data.responseJSON)
    $(".login-flashes p").remove()
    $(".login-flashes").append("
Invalid e-mail address
")
    $(".login-flashes").append("
Please verify it is correct and try again
")
  })
})
<|endoftext|>