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

var loopPool;

var testSound, testRange;
var testSound2, testRange2;
var nop = function(){ return true; };

beforeEach(function(){
  loopPool = new LoopPool('name', nop, nop, nop);

  testSound = 'testSound';
  testRange = { min: 0.1, max: 0.5};
  testSound2 = 'testSound2';
  testRange2 = { min: 0.6, max: 0.9};
});

describe('LoopPool', function(){

  describe('LoopPool()', function(){

    it('should set properties', function(){
      var v = function(){};
      var t = function(){};
      var time = function(){};

      loopPool = new LoopPool('name', v, t, time);
      loopPool.name.should.equal('name');
      loopPool.getTime.should.equal(time);
      loopPool.verify.should.equal(v);
      loopPool.trigger.should.equal(t);
      loopPool.value.should.equal(0);
      loopPool.events.should.deep.equal({});

    });

  });

  describe('.addSound', function(){

    it('should add soundinfo to recognizedEvents object',
      function(){
        loopPool.addSound(testSound, testRange);
        loopPool.events.should.deep.equal(
          {'testSound':{sound:testSound, range:testRange}}
        );
      }
    );

    it('should add only handle if given file info', function(){
      var testSound = {handle: 'testSound'};
      loopPool.addSound(testSound, testRange);
      loopPool.events.should.deep.equal(
        {'testSound':{sound:testSound.handle, range:testRange}}
      );
    });

    it('should throw error if verify returns false', function(){
      var verify = function(){ return false; };
      loopPool = new LoopPool('name', verify);
      expect(function(){
        loopPool.addSound(testSound, testRange);
      }).to.throw(
        'ClipConductor.LoopPool: cannot verify handle: testSound'
      );
    });

  });

  describe('.setSound', function(){
    it('should alias setSound', function(){
      LoopPool.prototype.addSound.should.equal(
        LoopPool.prototype.setSound);
    });
  });

  describe('.getSound', function(){

    beforeEach(function(){
      loopPool.addSound(testSound, testRange);
      loopPool.addSound(testSound2, testRange2);
    });

    it('should return the sound whose range encompasses value',
      function(){
        var result = loopPool.getSound(0.2);
        result.should.deep.equal(testSound);
      }
    );

    it('should return sound whose range is nearest value if '+
       ' no range encompasses value',
       function(){
         var result = loopPool.getSound(0.59);
         result.should.deep.equal(testSound2);
       }
    );

    it('should return undefined if pool is empty', function(){
      loopPool.events = {};
      expect(loopPool.getSound(0.2)).to.be.undefined;
    });

    it('should return a random matching value if mulitple'+
       ' sound ranges encompass value',
        function(){
          var testSound3 = {
            handle: 'testSound3',
            sound:'testSound3.mp3'
          };

          sinon.stub(Math, 'random').returns(0.75);

          loopPool.addSound(testSound3, testRange);
          loopPool.getSound(0.2).should.equal('testSound3');
        }
    );
  });

  describe('.removeSound', function(){
    it('should remove the sound', function(){
      loopPool.addSound(testSound, testRange);
      loopPool.removeSound(testSound);
      loopPool.events.should.deep.equal({});
    });

    it('should remove sound if given file info', function(){
      var testSound = {handle:'testSound'};
      loopPool.addSound(testSound, testRange);
      loopPool.removeSound(testSound);
      loopPool.events.should.deep.equal({});
    });
  });

  describe('.playSound', function(){
    it('should call trigger immediately', function(){
      var trigger = sinon.spy(function(){ return 3;});
      loopPool = new LoopPool('name', nop, trigger, nop);

      loopPool.playing = true;
      loopPool.addSound(testSound, {min:0, max: 1});

      loopPool.playSound(0);
      trigger.args[0].should.deep.equal([testSound, 0]);
    });

    it('should call itself after duration given '+
        'by file scaled by buffer',
      function(){
        var timeout = sinon.spy(window, 'setTimeout');
        var fb = sinon.spy(Function.prototype, 'bind');
        var trigger = function(){ return 3;};
        loopPool = new LoopPool('name', nop, trigger, nop);
        loopPool.addSound(testSound, testRange);
        loopPool.playing = true;

        loopPool.playSound(0);

        timeout.args[0][1].should.equal(3000);
        fb.args[0][1].should.equal(3);

        setTimeout.restore();
        Function.prototype.bind.restore();
      }
    );

    it('should not trigger if stop has been called',
      function(){
        var trigger = sinon.spy();
        loopPool = new LoopPool('name', nop, trigger, nop);
        loopPool.stop(); // playing=false
        loopPool.playSound(0);
        trigger.called.should.be.false;
      });
  });

  describe('.start', function(){
    it('should set playing to true', function(){
      loopPool.start();
      loopPool.playing.should.be.true;
    });

    it('should call playsound with currentTime+buffer',
      function(){
        var getTime = trigger = function(){return 3;};

        loopPool = new LoopPool('name', nop, trigger, getTime);
        var spy = sinon.spy(loopPool, 'playSound');
        loopPool.addSound(testSound, {min:0, max:1});
        loopPool.start();
        // 3.1 = getTime()+BUFFER
        spy.calledWith(3.1).should.equal(true);
        loopPool.playSound.restore();
      }
    );

    it('should not play if there are no sounds in cue', function(){
      var trigger = sinon.spy();
      loopPool = new LoopPool('name', nop, trigger, nop);
      loopPool.playing = true;
      loopPool.playSound();

      trigger.called.should.be.false;
    });

    it('should set timeout to min duration if less than min duration',
      function(){
        var timeout = sinon.spy(window, 'setTimeout');
        var trigger = function(){ return 0; };
        loopPool = new LoopPool('name', nop, trigger, nop);
        loopPool.addSound(testSound, {min:0, max:1});
        loopPool.start();

        expect(timeout.args[0][1]).to.equal(10);
        // value should be about 10
        // = minduration*1000ms
        // = 0.01*1000

        setTimeout.restore();
      }
    );

    it('should throw if duration returns non number', function(){
      var trigger = function(){ return undefined; };
      loopPool = new LoopPool('name', nop, trigger, nop);
      loopPool.addSound(testSound, {min:0, max:1});
      expect(function(){ loopPool.start(); })
        .to.throw('ClipConductor.LoopPool: duration must be a number');

    });

  });

  describe('.stop', function(){
    it('should set playing to false', function(){
      loopPool.stop();
      loopPool.playing.should.be.false;
    });
  });

  describe('.set', function(){
    it('should set current value', function(){
      loopPool.set(0.5);
      loopPool.value.should.equal(0.5);
    });
  });

});
<commit_msg>Added changes to loopPool tes<commit_after>var LoopPool = require('./LoopPool');

var loopPool;

var testSound, testRange;
var testSound2, testRange2;
var nop = function(){ return true; };

beforeEach(function(){
  loopPool = new LoopPool('name', nop, nop, nop);

  testSound = 'testSound';
  testRange = { min: 0.1, max: 0.5};
  testSound2 = 'testSound2';
  testRange2 = { min: 0.6, max: 0.9};
});

describe('LoopPool', function(){

  describe('LoopPool()', function(){

    it('should set properties', function(){
      var v = function(){};
      var t = function(){};
      var time = function(){};

      loopPool = new LoopPool('name', v, t, time);
      loopPool.name.should.equal('name');
      loopPool.getTime.should.equal(time);
      loopPool.verify.should.equal(v);
      loopPool.trigger.should.equal(t);
      loopPool.value.should.equal(0);
      loopPool.events.should.deep.equal({});

    });

  });

  describe('.addSound', function(){

    it('should add soundinfo to recognizedEvents object',
      function(){
        loopPool.addSound(testSound, testRange);
        loopPool.events.should.deep.equal(
          {'testSound':{sound:testSound, range:testRange}}
        );
      }
    );

    it('should add only handle if given file info', function(){
      var testSound = {handle: 'testSound'};
      loopPool.addSound(testSound, testRange);
      loopPool.events.should.deep.equal(
        {'testSound':{sound:testSound.handle, range:testRange}}
      );
    });

    it('should throw error if verify returns false', function(){
      var verify = function(){ return false; };
      loopPool = new LoopPool('name', verify);
      expect(function(){
        loopPool.addSound(testSound, testRange);
      }).to.throw(
        'ClipConductor.LoopPool: cannot verify handle: testSound'
      );
    });

  });

  describe('.setSound', function(){
    it('should alias setSound', function(){
      LoopPool.prototype.addSound.should.equal(
        LoopPool.prototype.setSound);
    });
  });

  describe('.getSound', function(){

    beforeEach(function(){
      loopPool.addSound(testSound, testRange);
      loopPool.addSound(testSound2, testRange2);
    });

    it('should return the sound whose range encompasses value',
      function(){
        var result = loopPool.getSound(0.2);
        result.should.deep.equal(testSound);
      }
    );

    it('should return sound whose range is nearest value if '+
       ' no range encompasses value',
       function(){
         var result = loopPool.getSound(0.59);
         result.should.deep.equal(testSound2);
       }
    );

    it('should return undefined if pool is empty', function(){
      loopPool.events = {};
      expect(loopPool.getSound(0.2)).to.be.undefined;
    });

    it('should return a random matching value if mulitple'+
       ' sound ranges encompass value',
        function(){
          var testSound3 = {
            handle: 'testSound3',
            sound:'testSound3.mp3'
          };

          sinon.stub(Math, 'random').returns(0.75);

          loopPool.addSound(testSound3, testRange);
          loopPool.getSound(0.2).should.equal('testSound3');
        }
    );
  });

  describe('.removeSound', function(){
    it('should remove the sound', function(){
      loopPool.addSound(testSound, testRange);
      loopPool.removeSound(testSound);
      loopPool.events.should.deep.equal({});
    });

    it('should remove sound if given file info', function(){
      var testSound = {handle:'testSound'};
      loopPool.addSound(testSound, testRange);
      loopPool.removeSound(testSound);
      loopPool.events.should.deep.equal({});
    });
  });

  describe('.playSound', function(){
    it('should call trigger immediately', function(){
      var trigger = sinon.spy(function(){ return 3;});
      loopPool = new LoopPool('name', nop, trigger, nop);

      loopPool.playing = true;
      loopPool.addSound(testSound, {min:0, max: 1});

      loopPool.playSound(0);
      trigger.args[0].should.deep.equal([testSound, 0]);
    });

    it('should call itself after duration given '+
        'by file scaled by buffer',
      function(){
        var timeout = sinon.spy(window, 'setTimeout');
        var fb = sinon.spy(Function.prototype, 'bind');
        var trigger = function(){ return 3;};
        loopPool = new LoopPool('name', nop, trigger, nop);
        loopPool.addSound(testSound, testRange);
        loopPool.playing = true;

        loopPool.playSound(0);

        timeout.args[0][1].should.equal(3000);
        fb.args[0][1].should.equal(3);

        setTimeout.restore();
        Function.prototype.bind.restore();
      }
    );

    it('should not trigger if stop has been called',
      function(){
        var trigger = sinon.spy();
        loopPool = new LoopPool('name', nop, trigger, nop);
        loopPool.stop(); // playing=false
        loopPool.playSound(0);
        trigger.called.should.be.false;
      });
  });

  describe('.start', function(){
    it('should set playing to true', function(){
      loopPool.start();
      loopPool.playing.should.be.true;
    });

    it('should call playsound with currentTime+buffer',
      function(){
        var getTime = trigger = function(){return 3;};

        loopPool = new LoopPool('name', nop, trigger, getTime);
        var spy = sinon.spy(loopPool, 'playSound');
        loopPool.addSound(testSound, {min:0, max:1});
        loopPool.start();
        // 3.1 = getTime()+BUFFER
        spy.calledWith(3.1).should.equal(true);
        loopPool.playSound.restore();
      }
    );

    it('should not play if there are no sounds in cue', function(){
      var trigger = sinon.spy();
      loopPool = new LoopPool('name', nop, trigger, nop);
      loopPool.playing = true;
      loopPool.playSound();

      trigger.called.should.be.false;
    });

    it('should set timeout to min duration if less than min duration',
      function(){
        var timeout = sinon.spy(window, 'setTimeout');
        var trigger = function(){ return 0; };
        loopPool = new LoopPool('name', nop, trigger, nop);
        loopPool.addSound(testSound, {min:0, max:1});
        loopPool.start();

        expect(timeout.args[0][1]).to.equal(10);
        // value should be about 10
        // = minduration*1000ms
        // = 0.01*1000

        setTimeout.restore();
      }
    );

    it('should throw if duration returns non number', function(){
      var trigger = function(){ return undefined; };
      loopPool = new LoopPool('name', nop, trigger, nop);
      loopPool.addSound(testSound, {min:0, max:1});
      expect(function(){ loopPool.start(); })
        .to.throw('ClipConductor.LoopPool: duration must be a number');

    });

  });

  describe('.stop', function(){
    it('should set playing to false', function(){
      loopPool.stop();
      loopPool.playing.should.be.false;
    });
  });

  describe('.set', function(){
    it('should set current value', function(){
      loopPool.set(0.5);
      loopPool.value.should.equal(0.5);
    });
  });

});
<|endoftext|>


<commit_before>// Un-checked parent origin
const _addEventListener = addEventListener;
addEventListener = function () {
  var args = Array.prototype.slice.call(arguments);
  if (args[0] === 'message' && typeof args[1] === 'function') {
    const _listener = args[1];
    args[1] = function () {
      var eArgs = Array.prototype.slice.call(arguments);
      if (eArgs[0].source === parent) {
        eArgs[0] = {
          origin: '*', // Ignore origin check
          data: eArgs[0].data,
          source: eArgs[0].source
        };
      }
      return _listener.apply(window, eArgs);
    };
  }
  return _addEventListener.apply(window, args);
};

module.exports = require('postmate/build/postmate.min');
<commit_msg>add window<commit_after>// Un-checked parent origin
const _addEventListener = window.addEventListener;
window.addEventListener = function () {
  var args = Array.prototype.slice.call(arguments);
  if (args[0] === 'message' && typeof args[1] === 'function') {
    const _listener = args[1];
    args[1] = function () {
      var eArgs = Array.prototype.slice.call(arguments);
      if (eArgs[0].source === parent) {
        eArgs[0] = {
          origin: '*', // Ignore origin check
          data: eArgs[0].data,
          source: eArgs[0].source
        };
      }
      return _listener.apply(window, eArgs);
    };
  }
  return _addEventListener.apply(window, args);
};

module.exports = require('postmate/build/postmate.min');
<|endoftext|>


<commit_before>var FullScreenController = (function () {
    "use strict";

    function FullScreenController(screen) {
        this.requestFullscreen = (function (element) {
            if (element.requestFullscreen) {
                return element.requestFullscreen.bind(element);
            } else if (element.webkitRequestFullscreen) {
                return element.webkitRequestFullscreen.bind(element);
            } else if (element.mozRequestFullScreen) {
                return element.mozRequestFullScreen.bind(element);
            } else if (element.msRequestFullscreen) {
                return element.msRequestFullscreen.bind(element);
            }
            return null;
        })(screen);

        this.isSupported = this.requestFullscreen != null;
    }

    FullScreenController.prototype.request = function () {
        if (this.isSupported)
            this.requestFullscreen();
    };

    return FullScreenController;
})();<commit_msg>better full screen controller refs #35 - handle orientation #core (cherry picked from commit 79779cf)<commit_after>var FullScreenController = (function (document) {
    "use strict";

    function FullScreenController(screen) {
        this.screen = screen;

        this.isSupported = document.fullscreenEnabled || document.webkitFullscreenEnabled ||
        document.mozFullScreenEnabled || document.msFullscreenEnabled;
    }

    FullScreenController.prototype.request = function () {
        if (this.isSupported) {
            if (this.screen.requestFullscreen) {
                this.screen.requestFullscreen();
            } else if (this.screen.webkitRequestFullscreen) {
                this.screen.webkitRequestFullscreen();
            } else if (this.screen.mozRequestFullScreen) {
                this.screen.mozRequestFullScreen();
            } else if (this.screen.msRequestFullscreen) {
                this.screen.msRequestFullscreen();
            }
        }
        return this.isFullScreen();
    };

    FullScreenController.prototype.isFullScreen = function () {
        return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement ||
            document.msFullscreenElement;
    };

    FullScreenController.prototype.exit = function () {
        if (this.isSupported) {
            if (document.exitFullscreen) {
                document.exitFullscreen();
            } else if (document.webkitExitFullscreen) {
                document.webkitExitFullscreen();
            } else if (document.mozCancelFullScreen) {
                document.mozCancelFullScreen();
            } else if (document.msExitFullscreen) {
                document.msExitFullscreen();
            }
        }

        return !this.isFullScreen();
    };

    document.addEventListener("fullscreenchange", fullScreenDebugHandler);
    document.addEventListener("webkitfullscreenchange", fullScreenDebugHandler);
    document.addEventListener("mozfullscreenchange", fullScreenDebugHandler);
    document.addEventListener("MSFullscreenChange", fullScreenDebugHandler);

    function fullScreenDebugHandler() {
        console.log('full screen event fired');
        var isFs = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement ||
            document.msFullscreenElement;
        console.log('is full screen: ' + isFs);
    }

    return FullScreenController;
})(window.document);<|endoftext|>


<commit_before>'use strict';

const functionHelper = require('./functionHelper.js');
const LambdaContext = require('./LambdaContext.js');
const { createUniqueId } = require('./utils/index.js');
const { DEFAULT_LAMBDA_TIMEOUT } = require('./config/index.js');

const { now } = Date;

module.exports = class LambdaFunction {
  constructor(config, options) {
    this._awsRequestId = null;
    this._config = config;
    this._executionTimeEnded = null;
    this._executionTimeStarted = null;
    this._options = options;
  }

  _startExecutionTimer() {
    this._executionTimeStarted = now();
  }

  _stopExecutionTimer() {
    this._executionTimeEnded = now();
  }

  addEvent(event) {
    this._event = event;
  }

  getExecutionTimeInMillis() {
    return this._executionTimeEnded - this._executionTimeStarted;
  }

  getAwsRequestId() {
    return this._awsRequestId;
  }

  async runHandler() {
    const {
      functionName,
      lambdaName,
      memorySize,
      timeout = DEFAULT_LAMBDA_TIMEOUT,
    } = this._config;

    this._requestId = createUniqueId();

    const lambdaContext = new LambdaContext({
      awsRequestId: this._awsRequestId,
      getRemainingTimeInMillis: () => {
        const timeEnd = this._executionTimeStarted + timeout * 1000;
        const time = timeEnd - now();

        // just return 0 for now if we are beyond alotted time (timeout)
        return time > 0 ? time : 0;
      },
      lambdaName,
      memorySize,
    });

    let callback;

    const callbackCalled = new Promise((resolve, reject) => {
      callback = (err, data) => {
        if (err) {
          reject(err);
        }
        resolve(data);
      };

      lambdaContext.once('contextCalled', callback);
    });

    const context = lambdaContext.getContext();

    this._startExecutionTimer();

    const handler = functionHelper.createHandler(this._config, this._options);

    let result;

    try {
      result = handler(this._event, context, callback);
    } catch (err) {
      // this only executes when we have an exception caused by syncronous code
      // TODO logging
      console.log(err);
      throw new Error(`Uncaught error in '${functionName}' handler.`);
    }

    // // not a Promise, which is not supported by aws
    // if (result == null || typeof result.then !== 'function') {
    //   throw new Error(`Syncronous function execution is not supported.`);
    // }

    const callbacks = [callbackCalled];

    // Promise was returned
    if (result != null && typeof result.then === 'function') {
      callbacks.push(result);
    }

    let callbackResult;

    try {
      callbackResult = await Promise.race(callbacks);
    } catch (err) {
      // TODO logging
      console.log(err);
      throw err;
    }

    this._stopExecutionTimer();

    return callbackResult;
  }
};
<commit_msg>Fix lambda timer calculation<commit_after>'use strict';

const functionHelper = require('./functionHelper.js');
const LambdaContext = require('./LambdaContext.js');
const { createUniqueId } = require('./utils/index.js');
const { DEFAULT_LAMBDA_TIMEOUT } = require('./config/index.js');

const { now } = Date;

module.exports = class LambdaFunction {
  constructor(config, options) {
    this._awsRequestId = null;
    this._config = config;
    this._executionTimeEnded = null;
    this._executionTimeStarted = null;
    this._executionTimeout = null;
    this._options = options;
  }

  _startExecutionTimer() {
    const { timeout = DEFAULT_LAMBDA_TIMEOUT } = this._config;

    this._executionTimeStarted = now();
    this._executionTimeout = this._executionTimeStarted + timeout * 1000;
  }

  _stopExecutionTimer() {
    this._executionTimeEnded = now();
  }

  addEvent(event) {
    this._event = event;
  }

  getExecutionTimeInMillis() {
    return this._executionTimeEnded - this._executionTimeStarted;
  }

  getAwsRequestId() {
    return this._awsRequestId;
  }

  async runHandler() {
    const { functionName, lambdaName, memorySize } = this._config;

    this._requestId = createUniqueId();

    const lambdaContext = new LambdaContext({
      awsRequestId: this._awsRequestId,
      getRemainingTimeInMillis: () => {
        const time = this._executionTimeout - now();

        // just return 0 for now if we are beyond alotted time (timeout)
        return time > 0 ? time : 0;
      },
      lambdaName,
      memorySize,
    });

    let callback;

    const callbackCalled = new Promise((resolve, reject) => {
      callback = (err, data) => {
        if (err) {
          reject(err);
        }
        resolve(data);
      };

      lambdaContext.once('contextCalled', callback);
    });

    const context = lambdaContext.getContext();

    this._startExecutionTimer();

    const handler = functionHelper.createHandler(this._config, this._options);

    let result;

    try {
      result = handler(this._event, context, callback);
    } catch (err) {
      // this only executes when we have an exception caused by syncronous code
      // TODO logging
      console.log(err);
      throw new Error(`Uncaught error in '${functionName}' handler.`);
    }

    // // not a Promise, which is not supported by aws
    // if (result == null || typeof result.then !== 'function') {
    //   throw new Error(`Syncronous function execution is not supported.`);
    // }

    const callbacks = [callbackCalled];

    // Promise was returned
    if (result != null && typeof result.then === 'function') {
      callbacks.push(result);
    }

    let callbackResult;

    try {
      callbackResult = await Promise.race(callbacks);
    } catch (err) {
      // TODO logging
      console.log(err);
      throw err;
    }

    this._stopExecutionTimer();

    return callbackResult;
  }
};
<|endoftext|>


<commit_before>L.Control.Buffer = L.Control.extend({
    includes: L.Mixin.Events,
    options: {
        unit: 'kilometers',
        textRadio: 'Ingrese el tamaño del Radio',
        position: 'topleft',
        toggle: false
    },

    onAdd: function (map) {
        this._map = map;
        this._active = false;
        this._container = L.DomUtil.create('div', 'leaflet-control-buffer leaflet-bar leaflet-control');
        this._container.title = "Buffer to specific area";
        this._link = L.DomUtil.create('a', 'leaflet-control-buffer-button leaflet-bar-part', this._container);
        this._link.href = '#';

        if (!this.options.toggle) {
            map.on('createBuffer', this.deactivate, this);
        }

        L.DomEvent
            .on(this._container, 'dblclick', L.DomEvent.stop)
            .on(this._container, 'click', L.DomEvent.stop)
            .on(this._container, 'click', function(){
                this._active = !this._active;
                if (this._active){
                    map.on('click', this._onCreateBuffer, this);
                    this.activate();
                }
                else {
                    map.off('click', this._onCreateBuffer, this);
                    this.deactivate();
                }
            }, this);

        return this._container;
    },
    activate: function() {
        L.DomUtil.addClass(this._container, 'active');
        this._map.dragging.disable();
        L.DomUtil.addClass(this._map.getContainer(), 'leaflet-control-buffer-crosshair');
    },
    deactivate: function() {
        L.DomUtil.removeClass(this._container, 'active');
        this._map.dragging.enable();
        L.DomUtil.removeClass(this._map.getContainer(), 'leaflet-control-buffer-crosshair');
        this._active = false;

    },
    _onCreateBuffer: function(e){
        var marker = L.marker(e.latlng, {});
        var pointMarker = marker.toGeoJSON();
        var radio = prompt(this.options.textRadio);
        var buffered = turf.buffer(pointMarker, radio, this.options.unit);

        var feature = L.geoJson(buffered);
        feature.addTo(map);

        this._map.onCreateBuffer(buffered);
    },

    addTo: function (map) {
			L.Control.prototype.addTo.call(this, map);
			return this;
		}

});
L.Map.include({
    onCreateBuffer: function(buffered){

        this.fire('createBuffer', { buffered: buffered });
    }
});

L.Map.addInitHook(function(){
    var onCreateBuffer = L.bind(this._onCreateBuffer, this);

        this.whenReady(function () {
            L.DomEvent.on(document, 'createBuffer', onCreateBuffer);
        });

        this.on('unload', function () {
            L.DomEvent.off(document, 'createBuffer', onCreateBuffer);
        });
});

L.control.buffer = function (options) {
    return new L.Control.Buffer(options);
};<commit_msg>resolving issue<commit_after>L.Control.Buffer = L.Control.extend({
    includes: L.Mixin.Events,
    options: {
        unit: 'kilometers',
        textRadio: 'Ingrese el tamaño del Radio',
        position: 'topleft',
        toggle: false
    },

    onAdd: function (map) {
        this._map = map;
        this._active = false;
        this._container = L.DomUtil.create('div', 'leaflet-control-buffer leaflet-bar leaflet-control');
        this._container.title = "Buffer to specific area";
        this._link = L.DomUtil.create('a', 'leaflet-control-buffer-button leaflet-bar-part', this._container);
        this._link.href = '#';

        if (!this.options.toggle) {
            map.on('createBuffer', this.deactivate, this);
        }

        L.DomEvent
            .on(this._container, 'dblclick', L.DomEvent.stop)
            .on(this._container, 'click', L.DomEvent.stop)
            .on(this._container, 'click', function(){
                this._active = !this._active;
                if (this._active){
                    map.on('click', this._onCreateBuffer, this);
                    this.activate();
                }
                else {
                    map.off('click', this._onCreateBuffer, this);
                    this.deactivate();
                }
            }, this);

        return this._container;
    },
    activate: function() {
        L.DomUtil.addClass(this._container, 'active');
        this._map.dragging.disable();
        L.DomUtil.addClass(this._map.getContainer(), 'leaflet-control-buffer-crosshair');
    },
    deactivate: function() {
        L.DomUtil.removeClass(this._container, 'active');
        this._map.dragging.enable();
        L.DomUtil.removeClass(this._map.getContainer(), 'leaflet-control-buffer-crosshair');
        this._active = false;

    },
    _onCreateBuffer: function(e){
        var marker = L.marker(e.latlng, {});
        var pointMarker = marker.toGeoJSON();
        var radio = prompt(this.options.textRadio);
        var buffered = turf.buffer(pointMarker, radio, this.options.unit);

        var feature = L.geoJson(buffered);
        feature.addTo(this._map);

        this._map.onCreateBuffer(buffered);
    },

    addTo: function (map) {
			L.Control.prototype.addTo.call(this, map);
			return this;
		}

});
L.Map.include({
    onCreateBuffer: function(buffered){

        this.fire('createBuffer', { buffered: buffered });
    }
});

L.Map.addInitHook(function(){
    var onCreateBuffer = L.bind(this._onCreateBuffer, this);

        this.whenReady(function () {
            L.DomEvent.on(document, 'createBuffer', onCreateBuffer);
        });

        this.on('unload', function () {
            L.DomEvent.off(document, 'createBuffer', onCreateBuffer);
        });
});

L.control.buffer = function (options) {
    return new L.Control.Buffer(options);
};<|endoftext|>


<commit_before>import {
  NativeModules,
  NativeEventEmitter,
} from 'react-native';

import { createErrorFromErrorData } from './utils';

const RNAdMobRewarded = NativeModules.RNAdMobRewarded;

const eventEmitter = new NativeEventEmitter(RNAdMobRewarded);

const eventMap = {
  adLoaded: 'rewardedVideoAdLoaded',
  adFailedToLoad: 'rewardedVideoAdFailedToLoad',
  adOpened: 'rewardedVideoAdOpened',
  adClosed: 'rewardedVideoAdClosed',
  adLeftApplication: 'rewardedVideoAdLeftApplication',
  rewarded: 'rewardedVideoAdRewarded',
  videoStarted: 'rewardedVideoAdVideoStarted',
};

const _subscriptions = new Map();

const addEventListener = (event, handler) => {
  const mappedEvent = eventMap[event];
  if (mappedEvent) {
    let listener;
    if (event === 'adFailedToLoad') {
      listener = eventEmitter.addListener(mappedEvent, error => handler(createErrorFromErrorData(error)));
    } else {
      listener = eventEmitter.addListener(mappedEvent, handler);
    }
    _subscriptions.set(handler, listener);
    return {
      remove: () => removeEventListener(event, handler)
    };
  } else {
    console.warn(`Trying to subscribe to unknown event: "${event}"`);
    return {
      remove: () => {},
    };
  }
};

const removeEventListener = (type, handler) => {
  const listener = _subscriptions.get(handler);
  if (!listener) {
    return;
  }
  listener.remove();
  _subscriptions.delete(handler);
};

const removeAllListeners = () => {
  _subscriptions.forEach((listener, key, map) => {
    listener.remove();
    map.delete(key);
  });
};

export default {
  ...RNAdMobRewarded,
  addEventListener,
  removeEventListener,
  removeAllListeners,
};
<commit_msg>add event alias for videoCompleted<commit_after>import {
  NativeModules,
  NativeEventEmitter,
} from 'react-native';

import { createErrorFromErrorData } from './utils';

const RNAdMobRewarded = NativeModules.RNAdMobRewarded;

const eventEmitter = new NativeEventEmitter(RNAdMobRewarded);

const eventMap = {
  adLoaded: 'rewardedVideoAdLoaded',
  adFailedToLoad: 'rewardedVideoAdFailedToLoad',
  adOpened: 'rewardedVideoAdOpened',
  adClosed: 'rewardedVideoAdClosed',
  adLeftApplication: 'rewardedVideoAdLeftApplication',
  rewarded: 'rewardedVideoAdRewarded',
  videoStarted: 'rewardedVideoAdVideoStarted',
  videoCompleted: 'rewardedVideoAdVideoCompleted',
};

const _subscriptions = new Map();

const addEventListener = (event, handler) => {
  const mappedEvent = eventMap[event];
  if (mappedEvent) {
    let listener;
    if (event === 'adFailedToLoad') {
      listener = eventEmitter.addListener(mappedEvent, error => handler(createErrorFromErrorData(error)));
    } else {
      listener = eventEmitter.addListener(mappedEvent, handler);
    }
    _subscriptions.set(handler, listener);
    return {
      remove: () => removeEventListener(event, handler)
    };
  } else {
    console.warn(`Trying to subscribe to unknown event: "${event}"`);
    return {
      remove: () => {},
    };
  }
};

const removeEventListener = (type, handler) => {
  const listener = _subscriptions.get(handler);
  if (!listener) {
    return;
  }
  listener.remove();
  _subscriptions.delete(handler);
};

const removeAllListeners = () => {
  _subscriptions.forEach((listener, key, map) => {
    listener.remove();
    map.delete(key);
  });
};

export default {
  ...RNAdMobRewarded,
  addEventListener,
  removeEventListener,
  removeAllListeners,
};
<|endoftext|>


<commit_before>var kaart = Titanium.UI.createWindow();

var annotations1 = Ti.Map.createAnnotation({
        latitude: 52.370216,
        longitude: 4.895168,
        title: 'Title A',
        subtitle: 'Subtitle A',
        animate: true,
        image:'pin.png',
        leftButton: 'google.jpg'
   });

var annotations2 = Ti.Map.createAnnotation({
        latitude: 52.361536,
        longitude: 4.907894,
        title: 'Title B',
        subtitle: 'Subtitle B',
        image:'pin.png',
        animate: true,
   });

var annotations = [annotations1, annotations2];

var mapview = Titanium.Map.createView({
    mapType: Titanium.Map.STANDARD_TYPE,
    region: {latitude:52.370216, longitude:4.895168,
            latitudeDelta:0.01, longitudeDelta:0.01},
    animate:true,
    regionFit:true,
    userLocation:true,
    annotations: annotations
});

kaart.add(mapview);

// points = [
	// {latitude:52.370216,longitude:4.895168},
	// {latitude:52.361536,longitude:4.907894}
// ]

var allPoints = somePoints.concat(someOtherPoints);
var route = {
	name:"Test Route",
	points:allPoints,
	color:"red",
	width:2
};
    mapview.addRoute(route);
<commit_msg>Kaart met route (points conflict)<commit_after>var kaart = Titanium.UI.createWindow();

var annotations1 = Ti.Map.createAnnotation({
        latitude: 52.370216,
        longitude: 4.895168,
        title: 'Title A',
        subtitle: 'Subtitle A',
        animate: true,
        image:'pin.png',
        leftButton: 'google.jpg'
   });

var annotations2 = Ti.Map.createAnnotation({
        latitude: 52.361536,
        longitude: 4.907894,
        title: 'Title B',
        subtitle: 'Subtitle B',
        image:'pin.png',
        animate: true,
   });

var annotations = [annotations1, annotations2];

var mapview = Titanium.Map.createView({
    mapType: Titanium.Map.STANDARD_TYPE,
    region: {latitude:52.370216, longitude:4.895168,
            latitudeDelta:0.01, longitudeDelta:0.01},
    animate:true,
    regionFit:true,
    userLocation:true,
    annotations: annotations
});

kaart.add(mapview);

points = [
	{latitude:52.370216,longitude:4.895168},
	{latitude:52.361536,longitude:4.907894}
]

var allPoints = somePoints.concat(someOtherPoints);
var route = {
	name:"Test Route",
	points:points,
	color:"red",
	width:2
};
    mapview.addRoute(route);
<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');

var Board = function(rows) {

    var opposite = function(turn) {
	return turn === 'B' ? 'W' : 'B';
    };

    this.isValidMove = function(i,j, turn) {
	if (rows[i][j] !== '-')
	    return false;

	// Walk left
	var w = j-1;
	while (w >= 0 && rows[i][w] === opposite(turn))
	    w--;

	if (w >= 0) {
	    return (rows[i][w] === turn);
	}
    };

    this.legalMoves = function(turn) {

	var moves = [];

	for (var i=0;i<rows.length;++i)
	    for (var j=0;j<rows[i].length;++j)
		if (this.isValidMove(i,j,turn))
		    moves.push({row: i, col: j});

	return moves;
    };

    return this;
};

var createBoard = function(rows) {
    return new Board(rows);
};

describe('reversi', function() {
    it('should create a board', function() {
	var board = createBoard(['BW','BW']);
	assert(board !== undefined);
    });

    it('should return no valid moves', function() {
	var board = createBoard(['BW',
				 'BW']);

	assert.equal(0, board.legalMoves('B').length);
    });

    it.only('should return the single valid move', function() {
	var board = createBoard(['BW-',
				 'BBB',
				 'BBB'], 'B');

	assert.equal(1, board.legalMoves('B').length);
    });

    it('should not return any valid moves', function() {
	var board = createBoard(['BW-',
				 'BBB',
				 'BBB'], 'W');

	assert.equal(0, board.legalMoves('W').length);
    });
});
<commit_msg>now fails a single test again<commit_after>"use strict";

var assert = require('assert');

var Board = function(rows) {

    var opposite = function(turn) {
	return turn === 'B' ? 'W' : 'B';
    };

    this.isValidMove = function(i,j, turn) {
	if (rows[i][j] !== '-')
	    return false;

	// Walk left
	var w = j-1;
	while (w >= 0 && rows[i][w] === opposite(turn))
	    w--;

	if (w >= 0) {
	    return (rows[i][w] === turn);
	}
    };

    this.legalMoves = function(turn) {

	var moves = [];

	for (var i=0;i<rows.length;++i)
	    for (var j=0;j<rows[i].length;++j)
		if (this.isValidMove(i,j,turn))
		    moves.push({row: i, col: j});

	return moves;
    };

    return this;
};

var createBoard = function(rows) {
    return new Board(rows);
};

describe('reversi', function() {
    it('should create a board', function() {
	var board = createBoard(['BW','BW']);
	assert(board !== undefined);
    });

    it('should return no valid moves', function() {
	var board = createBoard(['BW',
				 'BW']);

	assert.equal(0, board.legalMoves('B').length);
    });

    it('should return the single valid move', function() {
	var board = createBoard(['BW-',
				 'BBB',
				 'BBB']);

	assert.equal(1, board.legalMoves('B').length);
    });

    it('should not return any valid moves', function() {
	var board = createBoard(['BW-',
				 'BBB',
				 'BBB']);

	assert.equal(0, board.legalMoves('W').length);
    });
});
<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');

describe('reversi', function() {
  describe('acceptance test', function() {

    var sampleInput = '........\n' +
                      '........\n' +
                      '........\n' +
                      '...BW...\n' +
                      '...WB...\n' +
                      '........\n' +
                      '........\n' +
                      '........\n' +
                      'B\n';

    var sampleOutput = '........\n' +
                       '........\n' +
                       '....0...\n' +
                       '...BW0..\n' +
                       '..0WB...\n' +
                       '...0....\n' +
                       '........\n' +
                       '........\n' +
                       'B\n';

    it('should produce the expected output', function() {
      assert.equal(sampleOutput, drive(sampleInput));
    });
  });
});
<commit_msg>stub the drive function<commit_after>"use strict";

var assert = require('assert');

describe('reversi', function() {
  describe('acceptance test', function() {

    var sampleInput = '........\n' +
                      '........\n' +
                      '........\n' +
                      '...BW...\n' +
                      '...WB...\n' +
                      '........\n' +
                      '........\n' +
                      '........\n' +
                      'B\n';

    var sampleOutput = '........\n' +
                       '........\n' +
                       '....0...\n' +
                       '...BW0..\n' +
                       '..0WB...\n' +
                       '...0....\n' +
                       '........\n' +
                       '........\n' +
                       'B\n';

    var drive = function(input) {

    };

    it('should produce the expected output', function() {
      assert.equal(sampleOutput, drive(sampleInput));
    });
  });
});
<|endoftext|>


<commit_before>var React = require('react');

var PropertyDetail = React.createClass({
  // getInitialState: function() {
  //   return {
  //     url: "https://www.realo.be/en/laroussesquare-6-1190-forest/5467664?cl=2053559774%2C655577061%2C522693116%2C630891910%2C1779274120\n",
  //     location: "Laroussesquare 6, 1190 Forest",
  //     price: "200000€",
  //     description: "Idéalement situé à proximité de la place Saint-Job et du Lycée Français, dans un cadre calme et verdoyant, magnifique appartement d'une superficie de +/-100m² comprenant: hall d'entrée, lumineux séjour avec feu ouvert, salle à manger, 3 chambres (14, 10, 10m²), salle de bains, wc séparé. Cave. Terrasse.  Parking commun. PEB: C. A VISITER! Plus d'infos: www.bonnivers.be",
  //     properties: ["4 bedrooms"],
  //     image: ["http://lorempixel.com/image_output/city-q-c-400-200-4.jpg",
  //         "http://lorempixel.com/image_output/city-q-c-400-200-9.jpg"],
  //     coordinates: [
  //       50.8205965,
  //       4.3508388
  //     ]
  //   }
  // },
  createURLWithCoordinates: function(){
    return(
        "http://www.google.com/maps/place/"+this.props.estate.coordinates
    );
  },
  render: function(){
    console.log("this.props.estate");
    console.log(this.props.estate);
    return(

{this.props.estate.location}

                Previous

                Next

{this.props.estate.price}

{this.props.estate.properties[0]}

{this.props.estate.properties[1]}

            Locate on Map

{this.props.estate.description}

                <button type="button" className="btn btn-primary buttonMA">Make Appointment</button>

                 <button type="button" className="btn btn-primary buttonLA">Loan Advice</button>

    );
  }
});

module.exports = PropertyDetail;<commit_msg>Link from list to detail<commit_after>var React = require('react');
var $ = require('jquery');
var PropertyDetail = React.createClass({
  getInitialState: function() {
    return {estate: {image: [], properties:[]}};
  },
  componentWillMount: function() {
    var estateId = this.props.params.id;
    var url = "http://estates-api.herokuapp.com/estates"+"/"+estateId;
    $.get(url, function(data) {
         this.setState({estate: data});
      }.bind(this));
  },

  createURLWithCoordinates: function(){
    return(
        "http://www.google.com/maps/place/"+this.state.estate.coordinates
    );
  },
  render: function(){
    return(

{this.state.estate.location}

                Previous

                Next

{this.state.estate.price}

{this.state.estate.properties[0]}

{this.state.estate.properties[0]}

            Locate on Map

{this.state.estate.description}

                <button type="button" className="btn btn-primary buttonMA">Make Appointment</button>

                 <button type="button" className="btn btn-primary buttonLA">Loan Advice</button>

    );
  }
});

module.exports = PropertyDetail;<|endoftext|>


<commit_before>let sortRxx = Symbol();
let sortPartxx = Symbol();
let calculateExtensionType = Symbol();
let fileNamesProperty = Symbol();

let rxxExtension =  /\.r(\d\d)$|.rar$/;
let rarExtension = /.rar$/;
let partRxxExtension = /.part(\d\d).rar/;

export default class RarFileBundle {
  constructor(fileNames){
    if(!fileNames){
      throw new Error("Invalid Arguments, fileNames need to be passed to the constructor");
    }
    this[fileNamesProperty] = fileNames;
    this[calculateExtensionType]();

    this.filter();
    this.sort();
  }
  [calculateExtensionType](){
    let anyPartXXTypes = this[fileNamesProperty].filter(part => part.match(partRxxExtension));

    if(anyPartXXTypes.length > 0){
      this.extensionType = "partxx";
    }else{
      this.extensionType =  "rxx"
    }
  }
  filter(){
    if(this.extensionType === "rxx"){
      this[fileNamesProperty] = this[fileNamesProperty].filter(part => part.match(rxxExtension));
    }else{
      this[fileNamesProperty] = this[fileNamesProperty].filter(part => part.match(partRxxExtension));
    }
  }
  sort(){
    if(this.extensionType === "rxx"){
      this[sortRxx]();
    }else{
      this[sortPartxx]();
    }
  }
  [sortPartxx](){
    this[fileNamesProperty].sort((first, second) => {
      let firstMatch = first.match(partRxxExtension);
      let secondMatch = second.match(partRxxExtension);
      let firstNumber = +(firstMatch && firstMatch[1] || 0);
      let secondNumber = +(secondMatch && secondMatch[1] || 0);
      return  firstNumber - secondNumber;
    });
  }
  [sortRxx](){
    this[fileNamesProperty].sort((first, second) => {
      if (first.match(rarExtension)) {
        return -1;
      } else if (second.match(rarExtension)) {
        return 1;
      } else {
        let firstMatch = first.match(rxxExtension);
        let secondMatch = second.match(rxxExtension);
        let firstNumber = +(firstMatch && firstMatch[1] || 0);
        let secondNumber = +(secondMatch && secondMatch[1] || 0);
        return  firstNumber - secondNumber;
      }
    });
  }
  get length(){
    return this[fileNamesProperty].length;
  }
  *[Symbol.iterator] (){
    yield* this[fileNamesProperty];
  }
};<commit_msg>Refactored RarFileBundle<commit_after>const RXX_EXTENSION =  /\.R(\d\d)$|.RAR$/i;
const RAR_EXTENSION = /.RAR$/i;
const PART_RXX_EXTENSION = /.PART(\d\d).RAR/i;

export default class RarFileBundle {
  constructor(fileNames){
    if(!fileNames){
      throw new Error("Invalid Arguments, fileNames need to be passed to the constructor");
    }
    this._fileNames = fileNames;
    this._calculateExtensionType();

    this.filter();
    this.sort();
  }
  filter(){
    if(this._extensionType === "rxx"){
      this._fileNames = this._fileNames.filter(part => part.match(RXX_EXTENSION));
    }else{
      this._fileNames = this._fileNames.filter(part => part.match(PART_RXX_EXTENSION));
    }
  }
  sort(){
    if(this._extensionType === "rxx"){
      this._sortRxx();
    }else{
      this._sortPartxx();
    }
  }
  _calculateExtensionType(){
    let anyPartXXTypes = this._fileNames.filter(part => part.match(PART_RXX_EXTENSION));

    if(anyPartXXTypes.length > 0){
      this._extensionType = "partxx";
    }else{
      this._extensionType =  "rxx"
    }
  }
  _sortPartxx(){
    this._fileNames.sort((first, second) => {
      let firstMatch = first.match(PART_RXX_EXTENSION);
      let secondMatch = second.match(PART_RXX_EXTENSION);
      let firstNumber = +(firstMatch && firstMatch[1] || 0);
      let secondNumber = +(secondMatch && secondMatch[1] || 0);
      return firstNumber - secondNumber;
    });
  }
  _sortRxx(){
    this._fileNames.sort((first, second) => {
      if (first.match(RAR_EXTENSION)) {
        return -1;
      } else if (second.match(RAR_EXTENSION)) {
        return 1;
      } else {
        let firstMatch = first.match(RXX_EXTENSION);
        let secondMatch = second.match(RXX_EXTENSION);
        let firstNumber = +(firstMatch && firstMatch[1] || 0);
        let secondNumber = +(secondMatch && secondMatch[1] || 0);
        return  firstNumber - secondNumber;
      }
    });
  }
  get length(){
    return this._fileNames.length;
  }
  *[Symbol.iterator] (){
    yield* this._fileNames;
  }
};<|endoftext|>


<commit_before>/*
 * Copyright 2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Converts a Javascript value to a Java object.
 */
function convert_value(value) {
  var type = typeof value;
  switch (type) {
    case 'string':
    case 'boolean':
    case 'undefined':
    case 'org.vertx.java.core.buffer.Buffer':
      break;
    case 'number':
      value = new java.lang.Double(value);
      break;
    case 'object':
      // If null then we just wrap it as an empty JSON message
      // We don't do this if it's a Java class (it has the getClass) method
      // since it may be a Buffer which we want to let through
      if (value == null || typeof value.getClass === "undefined") {
        // Not a Java object - assume JSON message
        value = new org.vertx.java.core.json.JsonObject(JSON.stringify(value));
      }
      break;
    default:
      throw 'Invalid type: ' + type;
  }
  return value;
}
<commit_msg>Remove helpers module.<commit_after><|endoftext|>


<commit_before>/* @flow */
'use strict';

import type Options from './index';
import type Logger from './Logger';

export type ImageElement = Image | HTMLCanvasElement;
export type Resource = ImageElement;
type ResourceCache = {[string]: Promise<Resource>};

import FEATURES from './Feature';
import {Proxy} from './Proxy';

export default class ResourceLoader {
    origin: string;
    options: Options;
    _link: HTMLAnchorElement;
    cache: ResourceCache;
    logger: Logger;
    _index: number;
    _window: WindowProxy;

    constructor(options: Options, logger: Logger, window: WindowProxy) {
        this.options = options;
        this._window = window;
        this.origin = this.getOrigin(window.location.href);
        this.cache = {};
        this.logger = logger;
        this._index = 0;
    }

    loadImage(src: string): ?string {
        if (this.hasResourceInCache(src)) {
            return src;
        }

        if (!isSVG(src) || FEATURES.SUPPORT_SVG_DRAWING) {
            if (this.options.allowTaint === true || isInlineImage(src) || this.isSameOrigin(src)) {
                return this.addImage(src, src, false);
            } else if (!this.isSameOrigin(src)) {
                if (typeof this.options.proxy === 'string') {
                    this.cache[src] = Proxy(src, this.options).then(src =>
                        loadImage(src, this.options.imageTimeout || 0)
                    );
                    return src;
                } else if (this.options.useCORS === true && FEATURES.SUPPORT_CORS_IMAGES) {
                    return this.addImage(src, src, true);
                }
            }
        }
    }

    inlineImage(src: string): Promise<Resource> {
        if (isInlineImage(src)) {
            return loadImage(src, this.options.imageTimeout || 0);
        }
        if (this.hasResourceInCache(src)) {
            return this.cache[src];
        }
        if (!this.isSameOrigin(src) && typeof this.options.proxy === 'string') {
            return (this.cache[src] = Proxy(src, this.options).then(src =>
                loadImage(src, this.options.imageTimeout || 0)
            ));
        }

        return this.xhrImage(src);
    }

    xhrImage(src: string): Promise<Resource> {
        this.cache[src] = new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    if (xhr.status !== 200) {
                        reject(
                            `Failed to fetch image ${src.substring(
                                0,
                                256
                            )} with status code ${xhr.status}`
                        );
                    } else {
                        const reader = new FileReader();
                        reader.addEventListener(
                            'load',
                            () => {
                                // $FlowFixMe
                                const result: string = reader.result;
                                resolve(result);
                            },
                            false
                        );
                        reader.addEventListener('error', (e: Event) => reject(e), false);
                        reader.readAsDataURL(xhr.response);
                    }
                }
            };
            xhr.responseType = 'blob';
            if (this.options.imageTimeout) {
                const timeout = this.options.imageTimeout;
                xhr.timeout = timeout;
                xhr.ontimeout = () =>
                    reject(
                        __DEV__ ? `Timed out (${timeout}ms) fetching ${src.substring(0, 256)}` : ''
                    );
            }
            xhr.open('GET', src, true);
            xhr.send();
        }).then(src => loadImage(src, this.options.imageTimeout || 0));

        return this.cache[src];
    }

    loadCanvas(node: HTMLCanvasElement): string {
        const key = String(this._index++);
        this.cache[key] = Promise.resolve(node);
        return key;
    }

    hasResourceInCache(key: string): boolean {
        return typeof this.cache[key] !== 'undefined';
    }

    addImage(key: string, src: string, useCORS: boolean): string {
        if (__DEV__) {
            this.logger.log(`Added image ${key.substring(0, 256)}`);
        }

        const imageLoadHandler = (supportsDataImages: boolean): Promise<Image> =>
            new Promise((resolve, reject) => {
                const img = new Image();
                img.onload = () => resolve(img);
                //ios safari 10.3 taints canvas with data urls unless crossOrigin is set to anonymous
                if (!supportsDataImages || useCORS) {
                    img.crossOrigin = 'anonymous';
                }

                img.onerror = reject;
                img.src = src;
                if (img.complete === true) {
                    // Inline XML images may fail to parse, throwing an Error later on
                    setTimeout(() => {
                        resolve(img);
                    }, 500);
                }
                if (this.options.imageTimeout) {
                    const timeout = this.options.imageTimeout;
                    setTimeout(
                        () =>
                            reject(
                                __DEV__
                                    ? `Timed out (${timeout}ms) fetching ${src.substring(0, 256)}`
                                    : ''
                            ),
                        timeout
                    );
                }
            });

        this.cache[key] =
            isInlineBase64Image(src) && !isSVG(src)
                ? // $FlowFixMe
                  FEATURES.SUPPORT_BASE64_DRAWING(src).then(imageLoadHandler)
                : imageLoadHandler(true);
        return key;
    }

    isSameOrigin(url: string): boolean {
        return this.getOrigin(url) === this.origin;
    }

    getOrigin(url: string): string {
        const link = this._link || (this._link = this._window.document.createElement('a'));
        link.href = url;
        link.href = link.href; // IE9, LOL! - http://jsfiddle.net/niklasvh/2e48b/
        return link.protocol + link.hostname + link.port;
    }

    ready(): Promise<ResourceStore> {
        const keys: Array<string> = Object.keys(this.cache);
        const values: Array<Promise<?Resource>> = keys.map(str =>
            this.cache[str].catch(e => {
                if (__DEV__) {
                    this.logger.log(`Unable to load image`, e);
                }
                return null;
            })
        );
        return Promise.all(values).then((images: Array<?Resource>) => {
            if (__DEV__) {
                this.logger.log(`Finished loading ${images.length} images`, images);
            }
            return new ResourceStore(keys, images);
        });
    }
}

export class ResourceStore {
    _keys: Array<string>;
    _resources: Array<?Resource>;

    constructor(keys: Array<string>, resources: Array<?Resource>) {
        this._keys = keys;
        this._resources = resources;
    }

    get(key: string): ?Resource {
        const index = this._keys.indexOf(key);
        return index === -1 ? null : this._resources[index];
    }
}

const INLINE_SVG = /^data:image\/svg\+xml/i;
const INLINE_BASE64 = /^data:image\/.*;base64,/i;
const INLINE_IMG = /^data:image\/.*/i;

const isInlineImage = (src: string): boolean => INLINE_IMG.test(src);
const isInlineBase64Image = (src: string): boolean => INLINE_BASE64.test(src);

const isSVG = (src: string): boolean =>
    src.substr(-3).toLowerCase() === 'svg' || INLINE_SVG.test(src);

const loadImage = (src: string, timeout: number): Promise<Image> => {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = reject;
        img.src = src;
        if (img.complete === true) {
            // Inline XML images may fail to parse, throwing an Error later on
            setTimeout(() => {
                resolve(img);
            }, 500);
        }
        if (timeout) {
            setTimeout(
                () => reject(__DEV__ ? `Timed out (${timeout}ms) loading image` : ''),
                timeout
            );
        }
    });
};
<commit_msg>support blob image resources in non-foreignObjectRendering mode<commit_after>/* @flow */
'use strict';

import type Options from './index';
import type Logger from './Logger';

export type ImageElement = Image | HTMLCanvasElement;
export type Resource = ImageElement;
type ResourceCache = {[string]: Promise<Resource>};

import FEATURES from './Feature';
import {Proxy} from './Proxy';

export default class ResourceLoader {
    origin: string;
    options: Options;
    _link: HTMLAnchorElement;
    cache: ResourceCache;
    logger: Logger;
    _index: number;
    _window: WindowProxy;

    constructor(options: Options, logger: Logger, window: WindowProxy) {
        this.options = options;
        this._window = window;
        this.origin = this.getOrigin(window.location.href);
        this.cache = {};
        this.logger = logger;
        this._index = 0;
    }

    loadImage(src: string): ?string {
        if (this.hasResourceInCache(src)) {
            return src;
        }
        if (isBlobImage(src)) {
            this.cache[src] = loadImage(src, this.options.imageTimeout || 0);
            return src;
        }

        if (!isSVG(src) || FEATURES.SUPPORT_SVG_DRAWING) {
            if (this.options.allowTaint === true || isInlineImage(src) || this.isSameOrigin(src)) {
                return this.addImage(src, src, false);
            } else if (!this.isSameOrigin(src)) {
                if (typeof this.options.proxy === 'string') {
                    this.cache[src] = Proxy(src, this.options).then(src =>
                        loadImage(src, this.options.imageTimeout || 0)
                    );
                    return src;
                } else if (this.options.useCORS === true && FEATURES.SUPPORT_CORS_IMAGES) {
                    return this.addImage(src, src, true);
                }
            }
        }
    }

    inlineImage(src: string): Promise<Resource> {
        if (isInlineImage(src)) {
            return loadImage(src, this.options.imageTimeout || 0);
        }
        if (this.hasResourceInCache(src)) {
            return this.cache[src];
        }
        if (!this.isSameOrigin(src) && typeof this.options.proxy === 'string') {
            return (this.cache[src] = Proxy(src, this.options).then(src =>
                loadImage(src, this.options.imageTimeout || 0)
            ));
        }

        return this.xhrImage(src);
    }

    xhrImage(src: string): Promise<Resource> {
        this.cache[src] = new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            xhr.onreadystatechange = () => {
                if (xhr.readyState === 4) {
                    if (xhr.status !== 200) {
                        reject(
                            `Failed to fetch image ${src.substring(
                                0,
                                256
                            )} with status code ${xhr.status}`
                        );
                    } else {
                        const reader = new FileReader();
                        reader.addEventListener(
                            'load',
                            () => {
                                // $FlowFixMe
                                const result: string = reader.result;
                                resolve(result);
                            },
                            false
                        );
                        reader.addEventListener('error', (e: Event) => reject(e), false);
                        reader.readAsDataURL(xhr.response);
                    }
                }
            };
            xhr.responseType = 'blob';
            if (this.options.imageTimeout) {
                const timeout = this.options.imageTimeout;
                xhr.timeout = timeout;
                xhr.ontimeout = () =>
                    reject(
                        __DEV__ ? `Timed out (${timeout}ms) fetching ${src.substring(0, 256)}` : ''
                    );
            }
            xhr.open('GET', src, true);
            xhr.send();
        }).then(src => loadImage(src, this.options.imageTimeout || 0));

        return this.cache[src];
    }

    loadCanvas(node: HTMLCanvasElement): string {
        const key = String(this._index++);
        this.cache[key] = Promise.resolve(node);
        return key;
    }

    hasResourceInCache(key: string): boolean {
        return typeof this.cache[key] !== 'undefined';
    }

    addImage(key: string, src: string, useCORS: boolean): string {
        if (__DEV__) {
            this.logger.log(`Added image ${key.substring(0, 256)}`);
        }

        const imageLoadHandler = (supportsDataImages: boolean): Promise<Image> =>
            new Promise((resolve, reject) => {
                const img = new Image();
                img.onload = () => resolve(img);
                //ios safari 10.3 taints canvas with data urls unless crossOrigin is set to anonymous
                if (!supportsDataImages || useCORS) {
                    img.crossOrigin = 'anonymous';
                }

                img.onerror = reject;
                img.src = src;
                if (img.complete === true) {
                    // Inline XML images may fail to parse, throwing an Error later on
                    setTimeout(() => {
                        resolve(img);
                    }, 500);
                }
                if (this.options.imageTimeout) {
                    const timeout = this.options.imageTimeout;
                    setTimeout(
                        () =>
                            reject(
                                __DEV__
                                    ? `Timed out (${timeout}ms) fetching ${src.substring(0, 256)}`
                                    : ''
                            ),
                        timeout
                    );
                }
            });

        this.cache[key] =
            isInlineBase64Image(src) && !isSVG(src)
                ? // $FlowFixMe
                  FEATURES.SUPPORT_BASE64_DRAWING(src).then(imageLoadHandler)
                : imageLoadHandler(true);
        return key;
    }

    isSameOrigin(url: string): boolean {
        return this.getOrigin(url) === this.origin;
    }

    getOrigin(url: string): string {
        const link = this._link || (this._link = this._window.document.createElement('a'));
        link.href = url;
        link.href = link.href; // IE9, LOL! - http://jsfiddle.net/niklasvh/2e48b/
        return link.protocol + link.hostname + link.port;
    }

    ready(): Promise<ResourceStore> {
        const keys: Array<string> = Object.keys(this.cache);
        const values: Array<Promise<?Resource>> = keys.map(str =>
            this.cache[str].catch(e => {
                if (__DEV__) {
                    this.logger.log(`Unable to load image`, e);
                }
                return null;
            })
        );
        return Promise.all(values).then((images: Array<?Resource>) => {
            if (__DEV__) {
                this.logger.log(`Finished loading ${images.length} images`, images);
            }
            return new ResourceStore(keys, images);
        });
    }
}

export class ResourceStore {
    _keys: Array<string>;
    _resources: Array<?Resource>;

    constructor(keys: Array<string>, resources: Array<?Resource>) {
        this._keys = keys;
        this._resources = resources;
    }

    get(key: string): ?Resource {
        const index = this._keys.indexOf(key);
        return index === -1 ? null : this._resources[index];
    }
}

const INLINE_SVG = /^data:image\/svg\+xml/i;
const INLINE_BASE64 = /^data:image\/.*;base64,/i;
const INLINE_IMG = /^data:image\/.*/i;

const isInlineImage = (src: string): boolean => INLINE_IMG.test(src);
const isInlineBase64Image = (src: string): boolean => INLINE_BASE64.test(src);
const isBlobImage = (src: string): boolean => src.substr(0, 4) === 'blob';

const isSVG = (src: string): boolean =>
    src.substr(-3).toLowerCase() === 'svg' || INLINE_SVG.test(src);

const loadImage = (src: string, timeout: number): Promise<Image> => {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = reject;
        img.src = src;
        if (img.complete === true) {
            // Inline XML images may fail to parse, throwing an Error later on
            setTimeout(() => {
                resolve(img);
            }, 500);
        }
        if (timeout) {
            setTimeout(
                () => reject(__DEV__ ? `Timed out (${timeout}ms) loading image` : ''),
                timeout
            );
        }
    });
};
<|endoftext|>


<commit_before>/*
  A.hasOne(B)                 => B.aId
  A.belongsTo(B)              => A.bId
  A.hasMany(B)                => B.aId
  A.hasMany(B) + B.hasMany(A) => AB.aId + AB.bId
*/

SequelizeTable = function(sequelize, tableName, attributes) {
  var table = function(values) {
    var self = this
    SequelizeHelper.Hash.forEach(values, function(value, key) {
      if(attributes[key])
        self[key] = value
    })
    this.id = null // specify id as null to declare this object as unsaved and as not present in the database
    this.table = table
  }

  // class methods
  var classMethods = {
    associations: [],
    attributes: attributes,
    tableName: tableName,

    isCrossAssociatedWith: function(_table) {
      var result = false
      _table.associations.forEach(function(association) {
        if((association.table.tableName == table.tableName) && (association.type == 'hasMany'))
          result = true
      })
      return result
    },

    prepareAssociations: function() {
      table.associations.forEach(function(association) {
        switch(association.type) {
          case 'hasMany':
            if(association.table.isCrossAssociatedWith(association.table)) {
              // many to many relation

              SequelizeHelper.log(association)
              var _attributes = {}
              _attributes[table.identifier] = Sequelize.INTEGER
              _attributes[association.table.identifier] = Sequelize.INTEGER
              SequelizeHelper.log(table.tableName + association.table.tableName)
              sequelize.define(table.tableName + association.table.tableName, _attributes)
            } else {
              // one to many relation
              association.table.attributes[table.identifier] = Sequelize.INTEGER
            }

            break
          case 'hasOne':
            // e.g. assocTable.myTableId = Sequelize.INTEGER
            association.table.attributes[table.identifier] = Sequelize.INTEGER
            break
          case 'belongsTo':
            // e.g. table.dayId = Sequelize.INTEGER
            table.attributes[association.table.identifier] = Sequelize.INTEGER
            break
        }
      })
    },

    sync: function(callback) {
      table.prepareAssociations()

      var fields = ["id INT NOT NULL auto_increment PRIMARY KEY"]
      SequelizeHelper.Hash.forEach(table.attributes, function(type, name) {
        fields.push(name + " " + type)
      })

      sequelize.query(
        Sequelize.sqlQueryFor( 'create', { table: table.tableName, fields: fields.join(', ') } ),
        function() { if(callback) callback(table) }
      )
    },

    drop: function(callback) {
      sequelize.query(
        Sequelize.sqlQueryFor('drop', { table: table.tableName }),
        function() { if(callback) callback(table) }
      )
    },

    // TODO: mysql library currently doesn't support MYSQL_DATE!!! look for fix
    findAll: function(options, callback) {
      // use the first param as callback if it is no object (hash)
      var _callback = (typeof options == 'object') ? callback : options
      var queryOptions = (typeof options == 'object')
        ? SequelizeHelper.Hash.merge(options, { table: table.tableName })
        : { table: table.tableName }

      sequelize.query(
        Sequelize.sqlQueryFor('select', queryOptions),
        function(result) {
          var objects = []

          result.forEach(function(resultSet) {
            objects.push(table.sqlResultToObject(resultSet))

          })

          if(_callback) _callback(objects)
        }
      )
    },

    find: function(conditions, callback) {
      sequelize.query(
        Sequelize.sqlQueryFor('select', {
          table: table.tableName,
          where: SequelizeHelper.SQL.hashToWhereConditions(conditions, table.attributes),
          order: 'id DESC',
          limit: 1
        }), function(result) {
          var _result = result[0] ? table.sqlResultToObject(result[0]) : null
          if (callback) callback(_result)
        }
      )
    },

    // TODO: mysql library currently doesn't support MYSQL_DATE!!! don't merge if fixed
    sqlResultToObject: function(result) {
      if(typeof result == undefined) return null

      var object = new table(SequelizeHelper.Hash.merge({createdAt: new Date(), updatedAt: new Date()}, result, true))
      object.id = result.id
      return object
    },

    hasMany: function(assocName, _table) {
      table.associations.push({
        name: assocName,
        table: _table,
        type: 'hasMany'
      })

      table.prototype[assocName] = function(callback) {
        var whereConditions = [table.identifier, this.id].join("=")
        _table.findAll({where: whereConditions}, callback)
      }

      return table
    },

    hasOne: function(assocName, _table) {
      table.associations.push({
        name: assocName,
        table: _table,
        type: 'hasOne'
      })

      table.prototype[assocName] = function(callback) {
        var whereConditions = {}
        whereConditions[table.identifier] = this.id
        _table.find(whereConditions, callback)
      }

      return table
    },

    belongsTo: function(assocName, _table) {
      table.associations.push({
        name: assocName,
        table: _table,
        type: 'belongsTo'
      })

      table.prototype[assocName] = function(callback) {
        var whereConditions = ["id", this[_table.identifier]].join("=")
        _table.find({where: whereConditions}, callback)
      }

      return table
    }
  }
  // don't put this into the hash!
  classMethods.identifier = SequelizeHelper.SQL.asTableIdentifier(classMethods.tableName)

  // instance methods
  table.prototype = {
    get values() {
      var result = {}
      var self = this

      SequelizeHelper.Hash.keys(table.attributes).forEach(function(attribute) {
        result[attribute] = self[attribute]
      })

      return result
    },

    save: function(callback) {
      var query = null
      var self = this

      this.updatedAt = new Date()
      if(this.id == null) {
        this.createdAt = new Date()
        query = Sequelize.sqlQueryFor('insert', {
          table: table.tableName, fields: SequelizeHelper.SQL.fieldsForInsertQuery(this), values: SequelizeHelper.SQL.valuesForInsertQuery(this)
        })
      } else
        query = Sequelize.sqlQueryFor('update', { table: table.tableName, values: SequelizeHelper.SQL.valuesForUpdate(this), id: this.id })

      sequelize.query(query, function() {
        if(self.id == null) {
          table.find(self.values, function(result) {
            self.id = result.id
            if(callback) callback(self)
          })
        } else {
          if(callback) callback(self)
        }
      })
    },

    updateAttributes: function(newValues, callback) {
      var self = this
      SequelizeHelper.Hash.keys(table.attributes).forEach(function(attribute) {
        if(newValues[attribute])
          self[attribute] = newValues[attribute]
      })
      this.save(callback)
    },

    destroy: function(callback) {
      sequelize.query(
        Sequelize.sqlQueryFor('delete', { table: table.tableName, id: this.id }),
        callback
      )
    }
  }

  SequelizeHelper.Hash.forEach(classMethods, function(method, methodName) {
    table[methodName] = method
  })

  return table
}<commit_msg>many-to-many associations are almost working<commit_after>/*
  A.hasOne(B)                 => B.aId
  A.belongsTo(B)              => A.bId
  A.hasMany(B)                => B.aId
  A.hasMany(B) + B.hasMany(A) => AB.aId + AB.bId
*/

SequelizeTable = function(sequelize, tableName, attributes) {
  var table = function(values) {
    var self = this
    SequelizeHelper.Hash.forEach(values, function(value, key) {
      if(attributes[key])
        self[key] = value
    })
    this.id = null // specify id as null to declare this object as unsaved and as not present in the database
    this.table = table
  }

  // class methods
  var classMethods = {
    associations: [],
    attributes: attributes,
    tableName: tableName,

    isCrossAssociatedWith: function(associatedTable) {
      var result = false
      var myTableName = table.tableName

      associatedTable.associations.forEach(function(association) {
        if((association.table.tableName == myTableName) && (association.type == 'hasMany'))
          result = true
      })
      return result
    },

    prepareAssociations: function() {
      table.associations.forEach(function(association) {
        switch(association.type) {
          case 'hasMany':
            if(association.table.isCrossAssociatedWith(table)) {
              // many to many relation
              var _attributes = {}
              _attributes[table.identifier] = Sequelize.INTEGER
              _attributes[association.table.identifier] = Sequelize.INTEGER
              sequelize.define([table.tableName, association.table.tableName].sort().join(""), _attributes)
            } else {
              // one to many relation
              association.table.attributes[table.identifier] = Sequelize.INTEGER
            }
            break
          case 'hasOne':
            // e.g. assocTable.myTableId = Sequelize.INTEGER
            association.table.attributes[table.identifier] = Sequelize.INTEGER
            break
          case 'belongsTo':
            // e.g. table.dayId = Sequelize.INTEGER
            table.attributes[association.table.identifier] = Sequelize.INTEGER
            break
        }
      })
    },

    sync: function(callback) {
      var fields = ["id INT NOT NULL auto_increment PRIMARY KEY"]
      SequelizeHelper.Hash.forEach(table.attributes, function(type, name) {
        fields.push(name + " " + type)
      })

      sequelize.query(
        Sequelize.sqlQueryFor( 'create', { table: table.tableName, fields: fields.join(', ') } ),
        function() { if(callback) callback(table) }
      )
    },

    drop: function(callback) {
      sequelize.query(
        Sequelize.sqlQueryFor('drop', { table: table.tableName }),
        function() { if(callback) callback(table) }
      )
    },

    // TODO: mysql library currently doesn't support MYSQL_DATE!!! look for fix
    findAll: function(options, callback) {
      // use the first param as callback if it is no object (hash)
      var _callback = (typeof options == 'object') ? callback : options
      var queryOptions = (typeof options == 'object')
        ? SequelizeHelper.Hash.merge(options, { table: table.tableName })
        : { table: table.tableName }

      sequelize.query(
        Sequelize.sqlQueryFor('select', queryOptions),
        function(result) {
          var objects = []

          result.forEach(function(resultSet) {
            objects.push(table.sqlResultToObject(resultSet))

          })

          if(_callback) _callback(objects)
        }
      )
    },

    find: function(conditions, callback) {
      sequelize.query(
        Sequelize.sqlQueryFor('select', {
          table: table.tableName,
          where: SequelizeHelper.SQL.hashToWhereConditions(conditions, table.attributes),
          order: 'id DESC',
          limit: 1
        }), function(result) {
          var _result = result[0] ? table.sqlResultToObject(result[0]) : null
          if (callback) callback(_result)
        }
      )
    },

    // TODO: mysql library currently doesn't support MYSQL_DATE!!! don't merge if fixed
    sqlResultToObject: function(result) {
      if(typeof result == undefined) return null

      var object = new table(SequelizeHelper.Hash.merge({createdAt: new Date(), updatedAt: new Date()}, result, true))
      object.id = result.id
      return object
    },

    hasMany: function(assocName, _table) {
      table.associations.push({
        name: assocName,
        table: _table,
        type: 'hasMany'
      })

      table.prototype[assocName] = function(callback) {
        var whereConditions = [table.identifier, this.id].join("=")
        _table.findAll({where: whereConditions}, callback)
      }

      return table
    },

    hasOne: function(assocName, _table) {
      table.associations.push({
        name: assocName,
        table: _table,
        type: 'hasOne'
      })

      table.prototype[assocName] = function(callback) {
        var whereConditions = {}
        whereConditions[table.identifier] = this.id
        _table.find(whereConditions, callback)
      }

      return table
    },

    belongsTo: function(assocName, _table) {
      table.associations.push({
        name: assocName,
        table: _table,
        type: 'belongsTo'
      })

      table.prototype[assocName] = function(callback) {
        var whereConditions = ["id", this[_table.identifier]].join("=")
        _table.find({where: whereConditions}, callback)
      }

      return table
    }
  }
  // don't put this into the hash!
  classMethods.identifier = SequelizeHelper.SQL.asTableIdentifier(classMethods.tableName)

  // instance methods
  table.prototype = {
    get values() {
      var result = {}
      var self = this

      SequelizeHelper.Hash.keys(table.attributes).forEach(function(attribute) {
        result[attribute] = self[attribute]
      })

      return result
    },

    save: function(callback) {
      var query = null
      var self = this

      this.updatedAt = new Date()
      if(this.id == null) {
        this.createdAt = new Date()
        query = Sequelize.sqlQueryFor('insert', {
          table: table.tableName, fields: SequelizeHelper.SQL.fieldsForInsertQuery(this), values: SequelizeHelper.SQL.valuesForInsertQuery(this)
        })
      } else
        query = Sequelize.sqlQueryFor('update', { table: table.tableName, values: SequelizeHelper.SQL.valuesForUpdate(this), id: this.id })

      sequelize.query(query, function() {
        if(self.id == null) {
          table.find(self.values, function(result) {
            self.id = result.id
            if(callback) callback(self)
          })
        } else {
          if(callback) callback(self)
        }
      })
    },

    updateAttributes: function(newValues, callback) {
      var self = this
      SequelizeHelper.Hash.keys(table.attributes).forEach(function(attribute) {
        if(newValues[attribute])
          self[attribute] = newValues[attribute]
      })
      this.save(callback)
    },

    destroy: function(callback) {
      sequelize.query(
        Sequelize.sqlQueryFor('delete', { table: table.tableName, id: this.id }),
        callback
      )
    }
  }

  SequelizeHelper.Hash.forEach(classMethods, function(method, methodName) {
    table[methodName] = method
  })

  return table
}<|endoftext|>


<commit_before>//		a spectrum viewer
//
//	  Copyright  2015 Rappsilber Laboratory, Edinburgh University
//
// 		Licensed under the Apache License, Version 2.0 (the "License");
// 		you may not use this file except in compliance with the License.
// 		You may obtain a copy of the License at
//
// 		http://www.apache.org/licenses/LICENSE-2.0
//
//   	Unless required by applicable law or agreed to in writing, software
//   	distributed under the License is distributed on an "AS IS" BASIS,
//   	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   	See the License for the specific language governing permissions and
//   	limitations under the License.
//
//		authors: Lars Kolbowski
//
//
//		SpectrumView2.js

var xiSPEC = xiSPEC || {};
var CLMSUI = CLMSUI || {};

var SpectrumView = Backbone.View.extend({

	events : {},

	initialize: function(viewOptions) {

		var defaultOptions = {
			invert: false,
			hidden: false,
			xlabel: "m/z",
			ylabelLeft: "Intensity",
			ylabelRight: "% of base Peak",
			butterfly: false,
		};

		this.options = _.extend(defaultOptions, viewOptions);

		this.spinner = new Spinner({scale: 5});
		// this.svg = d3.select(this.el.getElementsByTagName("svg")[0]);
		this.svg = d3.select(this.el);

		//create graph
		this.graph = new Graph (this.svg, this.model, this.options);

		$(this.el).css('background-color', '#fff');

		this.listenTo(window, 'resize', _.debounce(this.resize));

		this.listenTo(this.model, 'change:JSONdata', this.render);
		this.listenTo(this.model, 'change:lockZoom', this.lockZoom);
		this.listenTo(this.model, 'change:measureMode', this.measuringTool);
		this.listenTo(this.model, 'change:moveLabels', this.moveLabels);
		this.listenTo(this.model, 'change:changedAnnotation', this.changedAnnotation);
		this.listenTo(this.model, 'change:highlightColor', this.updateHighlightColors);
		this.listenTo(this.model, 'changed:ColorScheme', this.updateColors);
		this.listenTo(this.model, 'change:mzRange', this.updateMzRange);

		this.listenTo(xiSPEC.vent, 'butterflyToggle', this.butterflyToggle);
		this.listenTo(xiSPEC.vent, 'downloadSpectrumSVG', this.downloadSVG);
		this.listenTo(xiSPEC.vent, 'resize:spectrum', this.resize);
		this.listenTo(xiSPEC.vent, 'clearSpectrumHighlights', this.clearHighlights);

		this.listenTo(this.model, 'resetZoom', this.resetZoom);
		this.listenTo(this.model, 'changed:Highlights', this.updateHighlights);
		this.listenTo(this.model, 'changed:lossyShown', this.showLossy);
		this.listenTo(this.model, 'request_annotation:pending', this.showSpinner);
		this.listenTo(this.model, 'request_annotation:done', this.hideSpinner);
		this.listenTo(this.model, 'changed:fragHighlighting', this.updatePeakHighlighting);
		//this.listenTo(this.model, 'destroy', this.remove);
	},

	render: function() {

		this.graph.clear();

		if(this.options.hidden){
			this.graph.hide();
			return this;
		}
		else{
			this.graph.show();
		}

		if (this.model.get("JSONdata")){
			this.graph.setData();
		}
		// this.hideSpinner();
		return this;
	},

	resetZoom: function(){
		this.graph.resize(this.model.xminPrimary, this.model.xmaxPrimary, this.model.ymin, this.model.ymaxPrimary);
	},

	updateMzRange: function(){
		//resize if the mzRange is not up to date
		var mzRange = this.model.get('mzRange');
		if (mzRange === undefined)
			return;
		if (mzRange[0] == this.graph.x.domain()[0] && mzRange[1] == this.graph.x.domain()[1])
			return;
		this.resize();
	},

	resize: function(){
		var mzRange = this.model.get('mzRange');
		if (mzRange === undefined)
			return;
		this.graph.resize(mzRange[0], mzRange[1], this.model.ymin, this.model.ymax);
	},

	showLossy: function(e){
		this.graph.lossyShown = this.model.lossyShown;
		this.graph.updatePeakLabels();
	},

	lockZoom: function(){

		if(this.model.get('lockZoom')){
			this.graph.disableZoom();
		}
		else{
			this.graph.enableZoom();
		}
	},

	clearHighlights: function(){
		this.model.clearStickyHighlights();
	},

	updateColors: function(){
		this.graph.updateColors();
	},

	updatePeakHighlighting: function(){
		this.graph.updatePeakLabels();
		this.graph.updatePeakColors();
	},

	updateHighlightColors: function(){
		this.graph.updateHighlightColors();
	},

	updateHighlights: function(){

		var peaks = this.graph.peaks;

		for(p = 0; p < peaks.length; p++){
			if(peaks[p].fragments.length > 0)
				peaks[p].highlight(false);

			var highlightFragments = _.intersection(peaks[p].fragments, this.model.highlights);
			if(highlightFragments.length != 0){
				peaks[p].highlight(true, highlightFragments);
			}
		}
		this.graph.updatePeakColors();
		this.graph.updatePeakLabels();
	},

	measuringTool: function(){
		this.graph.measure(this.model.get('measureMode'));
	},

	butterflyToggle: function(toggle){
		this.graph.options.butterfly = toggle;
		if(this.options.invert){
			this.model.clearStickyHighlights();
			this.options.hidden = !toggle;
			this.render();
		}
		this.resize();
	},

	moveLabels: function(){

		var peaks = this.graph.peaks;

		if (this.model.get('moveLabels')){
			// for(p = 0; p < peaks.length; p++){
			// 	if(peaks[p].labels){
			// 		for(l = 0; l < peaks[p].labels.length; l++){
			// 			peaks[p].labels[l].call(peaks[p].labelDrag);
			// 			peaks[p].labels[l].style("cursor", "pointer");
			// 		}
			// 	}
			// }
			for(p = 0; p < peaks.length; p++){
				if(peaks[p].labels.length){
						peaks[p].labels
							.call(peaks[p].labelDrag)
							//.style("cursor", "pointer");
				}
			}
		}
		else{
			for(p = 0; p < peaks.length; p++){
				if(peaks[p].labels.length){
					peaks[p].labels
						.on(".drag", null)
						//.style("cursor", "default")
					;
				}
			}
		}

	},

	downloadSVG: function(){
		var svgSel = d3.select(this.el.parentNode);
		var svgArr = svgSel[0];
		var svgStrings = CLMSUI.svgUtils.capture (svgArr);
		var svgXML = CLMSUI.svgUtils.makeXMLStr (new XMLSerializer(), svgStrings[0]);

		var charge = this.model.get("JSONdata").annotation.precursorCharge;
		var pepStrs = this.model.pepStrsMods;
		var linkSites = Array(this.model.get("JSONdata").LinkSite.length);

		this.model.get("JSONdata").LinkSite.forEach(function(ls){
			linkSites[ls.peptideId] = ls.linkSite;
		});

		//insert CL sites with #
		if (linkSites.length > 0){

			var ins_pepStrs = Array();
			pepStrs.forEach(function(pepStr, index){
				var positions = [];
				for(var i=0; i<pepStr.length; i++){
					if(pepStr[i].match(/[A-Z]/) != null){
						positions.push(i);
					};
				}
				var clAA_index = positions[linkSites[index]]+1;
				var ins_pepStr = pepStr.slice(0, clAA_index) + "#" + pepStr.slice(clAA_index, pepStr.length);
				pepStrs[index] = ins_pepStr;
			})
		}

		var svg_name = pepStrs.join("-") + "_z=" + charge;
		svg_name += svgSel.node().id;
		svg_name += ".svg";
		download (svgXML, 'application/svg', svg_name);
	},

	showSpinner: function(){
		this.graph.clear();
		this.spinner.spin(d3.select(this.el.parentNode).node());
	},

	hideSpinner: function(){
		this.spinner.stop();
	},

	changedAnnotation: function(){
		if(this.model.get('changedAnnotation')){
			$(this.el).css('background-color', 'rgb(210, 224, 255)');
		}
		else{
			$(this.el).css('background-color', '#fff');
		}
	},

});
<commit_msg>changedAnnotation background-color fix<commit_after>//		a spectrum viewer
//
//	  Copyright  2015 Rappsilber Laboratory, Edinburgh University
//
// 		Licensed under the Apache License, Version 2.0 (the "License");
// 		you may not use this file except in compliance with the License.
// 		You may obtain a copy of the License at
//
// 		http://www.apache.org/licenses/LICENSE-2.0
//
//   	Unless required by applicable law or agreed to in writing, software
//   	distributed under the License is distributed on an "AS IS" BASIS,
//   	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   	See the License for the specific language governing permissions and
//   	limitations under the License.
//
//		authors: Lars Kolbowski
//
//
//		SpectrumView2.js

var xiSPEC = xiSPEC || {};
var CLMSUI = CLMSUI || {};

var SpectrumView = Backbone.View.extend({

	events : {},

	initialize: function(viewOptions) {

		var defaultOptions = {
			invert: false,
			hidden: false,
			xlabel: "m/z",
			ylabelLeft: "Intensity",
			ylabelRight: "% of base Peak",
			butterfly: false,
		};

		this.options = _.extend(defaultOptions, viewOptions);

		this.spinner = new Spinner({scale: 5});
		// this.svg = d3.select(this.el.getElementsByTagName("svg")[0]);
		this.svg = d3.select(this.el);

		//create graph
		this.graph = new Graph (this.svg, this.model, this.options);

		$(this.el).css('background-color', '#fff');

		this.listenTo(window, 'resize', _.debounce(this.resize));

		this.listenTo(this.model, 'change:JSONdata', this.render);
		this.listenTo(this.model, 'change:lockZoom', this.lockZoom);
		this.listenTo(this.model, 'change:measureMode', this.measuringTool);
		this.listenTo(this.model, 'change:moveLabels', this.moveLabels);
		this.listenTo(this.model, 'change:changedAnnotation', this.changedAnnotation);
		this.listenTo(this.model, 'change:highlightColor', this.updateHighlightColors);
		this.listenTo(this.model, 'changed:ColorScheme', this.updateColors);
		this.listenTo(this.model, 'change:mzRange', this.updateMzRange);

		this.listenTo(xiSPEC.vent, 'butterflyToggle', this.butterflyToggle);
		this.listenTo(xiSPEC.vent, 'downloadSpectrumSVG', this.downloadSVG);
		this.listenTo(xiSPEC.vent, 'resize:spectrum', this.resize);
		this.listenTo(xiSPEC.vent, 'clearSpectrumHighlights', this.clearHighlights);

		this.listenTo(this.model, 'resetZoom', this.resetZoom);
		this.listenTo(this.model, 'changed:Highlights', this.updateHighlights);
		this.listenTo(this.model, 'changed:lossyShown', this.showLossy);
		this.listenTo(this.model, 'request_annotation:pending', this.showSpinner);
		this.listenTo(this.model, 'request_annotation:done', this.hideSpinner);
		this.listenTo(this.model, 'changed:fragHighlighting', this.updatePeakHighlighting);
		//this.listenTo(this.model, 'destroy', this.remove);
	},

	render: function() {

		this.graph.clear();

		if(this.options.hidden){
			this.graph.hide();
			return this;
		}
		else{
			this.graph.show();
		}

		if (this.model.get("JSONdata")){
			this.graph.setData();
		}
		// this.hideSpinner();
		return this;
	},

	resetZoom: function(){
		this.graph.resize(this.model.xminPrimary, this.model.xmaxPrimary, this.model.ymin, this.model.ymaxPrimary);
	},

	updateMzRange: function(){
		//resize if the mzRange is not up to date
		var mzRange = this.model.get('mzRange');
		if (mzRange === undefined)
			return;
		if (mzRange[0] == this.graph.x.domain()[0] && mzRange[1] == this.graph.x.domain()[1])
			return;
		this.resize();
	},

	resize: function(){
		var mzRange = this.model.get('mzRange');
		if (mzRange === undefined)
			return;
		this.graph.resize(mzRange[0], mzRange[1], this.model.ymin, this.model.ymax);
	},

	showLossy: function(e){
		this.graph.lossyShown = this.model.lossyShown;
		this.graph.updatePeakLabels();
	},

	lockZoom: function(){

		if(this.model.get('lockZoom')){
			this.graph.disableZoom();
		}
		else{
			this.graph.enableZoom();
		}
	},

	clearHighlights: function(){
		this.model.clearStickyHighlights();
	},

	updateColors: function(){
		this.graph.updateColors();
	},

	updatePeakHighlighting: function(){
		this.graph.updatePeakLabels();
		this.graph.updatePeakColors();
	},

	updateHighlightColors: function(){
		this.graph.updateHighlightColors();
	},

	updateHighlights: function(){

		var peaks = this.graph.peaks;

		for(p = 0; p < peaks.length; p++){
			if(peaks[p].fragments.length > 0)
				peaks[p].highlight(false);

			var highlightFragments = _.intersection(peaks[p].fragments, this.model.highlights);
			if(highlightFragments.length != 0){
				peaks[p].highlight(true, highlightFragments);
			}
		}
		this.graph.updatePeakColors();
		this.graph.updatePeakLabels();
	},

	measuringTool: function(){
		this.graph.measure(this.model.get('measureMode'));
	},

	butterflyToggle: function(toggle){
		this.graph.options.butterfly = toggle;
		if(this.options.invert){
			this.model.clearStickyHighlights();
			this.options.hidden = !toggle;
			this.render();
		}
		this.resize();
	},

	moveLabels: function(){

		var peaks = this.graph.peaks;

		if (this.model.get('moveLabels')){
			// for(p = 0; p < peaks.length; p++){
			// 	if(peaks[p].labels){
			// 		for(l = 0; l < peaks[p].labels.length; l++){
			// 			peaks[p].labels[l].call(peaks[p].labelDrag);
			// 			peaks[p].labels[l].style("cursor", "pointer");
			// 		}
			// 	}
			// }
			for(p = 0; p < peaks.length; p++){
				if(peaks[p].labels.length){
						peaks[p].labels
							.call(peaks[p].labelDrag)
							//.style("cursor", "pointer");
				}
			}
		}
		else{
			for(p = 0; p < peaks.length; p++){
				if(peaks[p].labels.length){
					peaks[p].labels
						.on(".drag", null)
						//.style("cursor", "default")
					;
				}
			}
		}

	},

	downloadSVG: function(){
		var svgSel = d3.select(this.el.parentNode);
		var svgArr = svgSel[0];
		var svgStrings = CLMSUI.svgUtils.capture (svgArr);
		var svgXML = CLMSUI.svgUtils.makeXMLStr (new XMLSerializer(), svgStrings[0]);

		var charge = this.model.get("JSONdata").annotation.precursorCharge;
		var pepStrs = this.model.pepStrsMods;
		var linkSites = Array(this.model.get("JSONdata").LinkSite.length);

		this.model.get("JSONdata").LinkSite.forEach(function(ls){
			linkSites[ls.peptideId] = ls.linkSite;
		});

		//insert CL sites with #
		if (linkSites.length > 0){

			var ins_pepStrs = Array();
			pepStrs.forEach(function(pepStr, index){
				var positions = [];
				for(var i=0; i<pepStr.length; i++){
					if(pepStr[i].match(/[A-Z]/) != null){
						positions.push(i);
					};
				}
				var clAA_index = positions[linkSites[index]]+1;
				var ins_pepStr = pepStr.slice(0, clAA_index) + "#" + pepStr.slice(clAA_index, pepStr.length);
				pepStrs[index] = ins_pepStr;
			})
		}

		var svg_name = pepStrs.join("-") + "_z=" + charge;
		svg_name += svgSel.node().id;
		svg_name += ".svg";
		download (svgXML, 'application/svg', svg_name);
	},

	showSpinner: function(){
		this.graph.clear();
		this.spinner.spin(d3.select(this.el.parentNode).node());
	},

	hideSpinner: function(){
		this.spinner.stop();
	},

	changedAnnotation: function(){
		if(this.model.get('changedAnnotation')){
			$(this.el.parentNode).attr('style', 'background-color:#9abaff;');
		}
		else{
			$(this.el.parentNode).attr('style', 'background-color:#fff;');
		}
	},

});
<|endoftext|>