<commit_before>
mc.models.xyChartBase = function xyChartBase(model) {

  model = model || {};

  //============================================================
  // Public Variables with Default Settings

  // Components
  model.xyBase       = mc.models.xyBase(model);

  // Settings
  model.name         = 'xyChartBase';
  model.renderLegend = false;
  model.renderAxes   = false;

  // Accessors

  // Setup Component Settings

  //------------------------------------------------------------

  chart.calc = function(instance, data) {

    model.xyBase.calc.call(this, instance, data);

    return chart;
  };

  chart.build = function(instance, data) {

    model.xyBase.build.call(this, instance, data); // This currently DOES NOTHING, but here incase someting is added

    //------------------------------------------------------------
    // Setup Chart Layers

    //TODO: deside on not rendering this is renderAxes/renderVoronoi false **this would prevent turning Axes back on (b/c gEnter) BUT if they are on, you can't currently turn them off anyway
    instance.gEnter.append('g').attr('class', 'mc-axes-wrap');
    //TODO: figure out best way to put legend on top of parent chart's layers
    instance.gEnter.append('g').attr('class', 'mc-legend-wrap');

    //------------------------------------------------------------

    //------------------------------------------------------------
    // Core Chart Code

    if (model.renderAxes) {
      instance.axesWrap = instance.g.select('.mc-axes-wrap');
      model.axes(instance.axesWrap, instance);
    }

    //TODO: create a legend wrapper chart to allow easy positioning of legend
    //      around the edged (inside and outside) of chart borders
    if (model.renderLegend) {
      instance.legendWrap = instance.g.select('.mc-legend-wrap')
        .attr('transform', 'translate(0,-20)');

      //TODO: legend width and height are not able to be set in parent charts
      model.legend
        .width(instance.width)
        .height(20)

      model.legend(instance.legendWrap);

      instance.legendWrap.chart().dispatch.on('click.toggleDisabled', toggleDisabled);
    }

    function toggleDisabled(d) {
      d.series.disabled = !d.series.disabled;

      //TODO: maybe haave the parent chart update itself?
      //TODO: consider dispatching event toggleDisable
      //TODO: **consider making a dispatch that multiple inherited charts can share
      instance.container.chart().update();
    }

    //------------------------------------------------------------

    return chart;
  };

  //TODO: this appears to be identical in all charts, should see if there is a way to automate this
  function chart(selection, instance) {
    selection.each(function(data) {
      instance = instance || {};

      chart.calc.call(this, instance, data);
      chart.build.call(this, instance, data);
    });

    return chart;
  }

  //============================================================
  // Expose Public API

  mc.rebind(chart, model.xyBase);

  chart.renderLegend = function(_) {
    if (!arguments.length) return model.renderLegend;
    model.renderLegend = _;

    if (_) {
      model.legend = mc.models.legend(); //TODO: decide if 'model' can/should be passed in (also debate on same thing with axes)
      model.legend
        .legendLabelWidth(85)
        .legendLabelHeight(20)
        .legendHorizontalAlign('right');

      d3.rebind(chart, model.legend, 'legendOrientation', 'legendHorizontalAlign', 'legendVerticalAlign', 'legendShape', 'legendLabelWidth', 'legendLabelHeight');
      //chart.legend = model.legend;
    }

    return chart;
  };

  chart.renderAxes = function(_) {
    if (!arguments.length) return model.renderAxes;
    model.renderAxes = _;

    if (_) {
      model.axes = mc.models.axes(model);      // chart axes
      mc.rebind(chart, model.axes);  //TODO: see if this works with o.axes.*Axis being directly on th chart
      //TODO: this rebinds to xyChartBase, not parent chart!.. figure out best way to handle this (currently need to call chart.rebind on parent)
    }

    return chart;
  };

  //------------------------------------------------------------

  return chart;
};
<commit_msg>utilize arrow functions whereever possible in xyChartBase.js<commit_after>
mc.models.xyChartBase = function xyChartBase(model) {

  model = model || {};

  //============================================================
  // Public Variables with Default Settings

  // Components
  model.xyBase       = mc.models.xyBase(model);

  // Settings
  model.name         = 'xyChartBase';
  model.renderLegend = false;
  model.renderAxes   = false;

  // Accessors

  // Setup Component Settings

  //------------------------------------------------------------

  chart.calc = function(instance, data) {

    model.xyBase.calc.call(this, instance, data);

    return chart;
  };

  chart.build = function(instance, data) {

    model.xyBase.build.call(this, instance, data); // This currently DOES NOTHING, but here incase someting is added

    //------------------------------------------------------------
    // Setup Chart Layers

    //TODO: deside on not rendering this is renderAxes/renderVoronoi false **this would prevent turning Axes back on (b/c gEnter) BUT if they are on, you can't currently turn them off anyway
    instance.gEnter.append('g').attr('class', 'mc-axes-wrap');
    //TODO: figure out best way to put legend on top of parent chart's layers
    instance.gEnter.append('g').attr('class', 'mc-legend-wrap');

    //------------------------------------------------------------

    //------------------------------------------------------------
    // Core Chart Code

    if (model.renderAxes) {
      instance.axesWrap = instance.g.select('.mc-axes-wrap');
      model.axes(instance.axesWrap, instance);
    }

    //TODO: create a legend wrapper chart to allow easy positioning of legend
    //      around the edged (inside and outside) of chart borders
    if (model.renderLegend) {
      instance.legendWrap = instance.g.select('.mc-legend-wrap')
        .attr('transform', 'translate(0,-20)');

      //TODO: legend width and height are not able to be set in parent charts
      model.legend
        .width(instance.width)
        .height(20)

      model.legend(instance.legendWrap);

      instance.legendWrap.chart().dispatch.on('click.toggleDisabled', toggleDisabled);
    }

    function toggleDisabled(d) {
      d.series.disabled = !d.series.disabled;

      //TODO: maybe haave the parent chart update itself?
      //TODO: consider dispatching event toggleDisable
      //TODO: **consider making a dispatch that multiple inherited charts can share
      instance.container.chart().update();
    }

    //------------------------------------------------------------

    return chart;
  };

  //TODO: this appears to be identical in all charts, should see if there is a way to automate this
  function chart(selection, instance) {
    selection.each(function(data) {
      instance = instance || {};

      chart.calc.call(this, instance, data);
      chart.build.call(this, instance, data);
    });

    return chart;
  }

  //============================================================
  // Expose Public API

  mc.rebind(chart, model.xyBase);

  chart.renderLegend = _ => {
    if (!arguments.length) return model.renderLegend;
    model.renderLegend = _;

    if (_) {
      model.legend = mc.models.legend(); //TODO: decide if 'model' can/should be passed in (also debate on same thing with axes)
      model.legend
        .legendLabelWidth(85)
        .legendLabelHeight(20)
        .legendHorizontalAlign('right');

      d3.rebind(chart, model.legend, 'legendOrientation', 'legendHorizontalAlign', 'legendVerticalAlign', 'legendShape', 'legendLabelWidth', 'legendLabelHeight');
      //chart.legend = model.legend;
    }

    return chart;
  };

  chart.renderAxes = _ => {
    if (!arguments.length) return model.renderAxes;
    model.renderAxes = _;

    if (_) {
      model.axes = mc.models.axes(model);      // chart axes
      mc.rebind(chart, model.axes);  //TODO: see if this works with o.axes.*Axis being directly on th chart
      //TODO: this rebinds to xyChartBase, not parent chart!.. figure out best way to handle this (currently need to call chart.rebind on parent)
    }

    return chart;
  };

  //------------------------------------------------------------

  return chart;
};
<|endoftext|>


<commit_before>function closeModals(){
    console.log('Closing all modals');
    $('modal').css('display', 'none');
}

$('document').ready(
    function () {

// Get the modal
//var modal = document.getElementById('myModal');

//Get modals
//         var modals = document.getElementsByClassName('modal');

// Get the button that opens the modal
//var btn = document.getElementById("myBtn");

// Get the <span> elements that close the modals
//         var closeButtons = document.getElementsByClassName("close");

// When the user clicks the button, open the modal
        /*btn.onclick = function() {
         modal.style.display = "block";
         }*/

// When the user clicks on <span> (x), close the modal
        $.each($('.close'), function(index, ele){
            ele.click(closeModals)
        });

        // When the user clicks anywhere outside of the modal, close it
        $(window).click(function(e){
            console.log("Clicked window", e);
            if(e.target.className.indexOf('modal')>=0){
                closeModals();
            }
        })

        /*

         //Modify the modal to include the review the user clicked
         function reviewModal(user) {
         modal.style.display = "block";
         document.getElementById("mh1").innerHTML = user["userName"];
         document.getElementById("cont").innerHTML = user["body"];
         document.getElementById("mh2").innerHTML = "Stars: " + user["stars"];
         }

         //Modify the modal to include the route the user clicked
         function routeModal(route) {
         modal.style.display = "block";
         document.getElementById("mh1").innerHTML = "Route ID: " + route["routeID"];
         document.getElementById("cont").innerHTML = route["bio"];
         document.getElementById("mh2").innerHTML = "Difficulty: " + route["difficulty"];
         }*/
    }
)<commit_msg>Fixed jquery stuff<commit_after>function closeModals(){
    console.log('Closing all modals');
    $('modal').css('display', 'none');
}

$('document').ready(
    function () {

// Get the modal
//var modal = document.getElementById('myModal');

//Get modals
//         var modals = document.getElementsByClassName('modal');

// Get the button that opens the modal
//var btn = document.getElementById("myBtn");

// Get the <span> elements that close the modals
//         var closeButtons = document.getElementsByClassName("close");

// When the user clicks the button, open the modal
        /*btn.onclick = function() {
         modal.style.display = "block";
         }*/

// When the user clicks on <span> (x), close the modal
        $.each($('.close'), function(index, ele){
            ele.click(closeModals)
        });

        // When the user clicks anywhere outside of the modal, close it
        $(window).click(function(e){
            console.log("Clicked window", e);
            if(e.target.className == 'modal'){
                closeModals();
            }
        })

        /*

         //Modify the modal to include the review the user clicked
         function reviewModal(user) {
         modal.style.display = "block";
         document.getElementById("mh1").innerHTML = user["userName"];
         document.getElementById("cont").innerHTML = user["body"];
         document.getElementById("mh2").innerHTML = "Stars: " + user["stars"];
         }

         //Modify the modal to include the route the user clicked
         function routeModal(route) {
         modal.style.display = "block";
         document.getElementById("mh1").innerHTML = "Route ID: " + route["routeID"];
         document.getElementById("cont").innerHTML = route["bio"];
         document.getElementById("mh2").innerHTML = "Difficulty: " + route["difficulty"];
         }*/
    }
)<|endoftext|>


<commit_before>describe('upload file', function() {
  /**
   * @type {Resumable}
   */
  var resumable;
  /**
   * @type {FakeXMLHttpRequest}
   */
  var xhr;
  /**
   * @type {FakeXMLHttpRequest[]}
   */
  var requests = [];

  beforeEach(function () {
    resumable = new Resumable({
      progressCallbacksInterval: 0,
      generateUniqueIdentifier: function (file) {
        return file.size;
      }
    });
    requests = [];

    xhr = sinon.useFakeXMLHttpRequest();
    xhr.onCreate = function (xhr) {
      requests.push(xhr);
    };
  });

  afterEach(function () {
    xhr.restore();
  });

  it('should pass query params', function() {
    resumable.opts.query = {};
    resumable.opts.target = 'file';
    resumable.addFile(new Blob(['123']));
    resumable.upload();
    expect(requests.length).toBe(1);
    expect(requests[0].url).toContain('file');

    resumable.opts.query = {a:1};
    resumable.files[0].retry();
    expect(requests.length).toBe(2);
    expect(requests[1].url).toContain('file');
    expect(requests[1].url).toContain('a=1');

    resumable.opts.query = function (file, chunk) {
      expect(file).toBe(resumable.files[0]);
      expect(chunk).toBe(resumable.files[0].chunks[0]);
      return {b:2};
    };
    resumable.files[0].retry();
    expect(requests.length).toBe(3);
    expect(requests[2].url).toContain('file');
    expect(requests[2].url).toContain('b=2');
    expect(requests[2].url).not.toContain('a=1');

    resumable.opts.query = undefined;
    resumable.files[0].retry();
    expect(requests.length).toBe(4);
    expect(requests[3].url).toContain('file');
    expect(requests[3].url).not.toContain('a=1');
    expect(requests[3].url).not.toContain('b=2');
  });

  it('should track file upload status with lots of chunks', function() {
    resumable.opts.chunkSize = 1;
    resumable.addFile(new Blob(['IIIIIIIIII']));
    var file = resumable.files[0];
    expect(file.chunks.length).toBe(10);
    resumable.upload();
    expect(file.progress()).toBe(0);
    for (var i = 0; i < 9; i++) {
      expect(requests[i]).toBeDefined();
      expect(file.isComplete()).toBeFalsy();
      expect(file.isUploading()).toBeTruthy();
      requests[i].respond(200);
      expect(file.progress()).toBe((i+1) / 10);
      expect(file.isComplete()).toBeFalsy();
      expect(file.isUploading()).toBeTruthy();
    }
    expect(requests[9]).toBeDefined();
    expect(file.isComplete()).toBeFalsy();
    expect(file.isUploading()).toBeTruthy();
    expect(file.progress()).toBe(0.9);
    requests[i].respond(200);
    expect(file.isComplete()).toBeTruthy();
    expect(file.isUploading()).toBeFalsy();
    expect(file.progress()).toBe(1);
    expect(resumable.progress()).toBe(1);
  });

  it('should throw expected events', function () {
    var events = [];
    resumable.on('catchAll', function (event) {
      events.push(event);
    });
    resumable.opts.chunkSize = 1;
    resumable.addFile(new Blob(['12']));
    var file = resumable.files[0];
    expect(file.chunks.length).toBe(2);
    resumable.upload();
    // Sync events
    expect(events.length).toBe(4);
    expect(events[0]).toBe('fileAdded');
    expect(events[1]).toBe('filesAdded');
    expect(events[2]).toBe('filesSubmitted');
    expect(events[3]).toBe('uploadStart');
    // Async
    requests[0].respond(200);
    expect(events.length).toBe(6);
    expect(events[4]).toBe('fileProgress');
    expect(events[5]).toBe('progress');
    requests[1].respond(400);
    expect(events.length).toBe(6);
    requests[2].progress(5, 10, true);
    expect(events.length).toBe(8);
    expect(events[6]).toBe('fileProgress');
    expect(events[7]).toBe('progress');
    requests[2].respond(200);
    expect(events.length).toBe(12);
    expect(events[8]).toBe('fileProgress');
    expect(events[9]).toBe('progress');
    expect(events[10]).toBe('fileSuccess');
    // Can be sync and async
    expect(events[11]).toBe('complete');
  });

  it('should pause and resume file', function () {
    resumable.opts.chunkSize = 1;
    resumable.opts.simultaneousUploads = 2;
    resumable.addFile(new Blob(['1234']));
    resumable.addFile(new Blob(['56']));
    var files = resumable.files;
    expect(files[0].chunks.length).toBe(4);
    expect(files[1].chunks.length).toBe(2);
    resumable.upload();
    expect(files[0].isUploading()).toBeTruthy();
    expect(requests.length).toBe(2);
    expect(requests[0].aborted).toBeUndefined();
    expect(requests[1].aborted).toBeUndefined();
    // should start upload second file
    files[0].pause();
    expect(files[0].isUploading()).toBeFalsy();
    expect(files[1].isUploading()).toBeTruthy();
    expect(requests.length).toBe(4);
    expect(requests[0].aborted).toBeTruthy();
    expect(requests[1].aborted).toBeTruthy();
    expect(requests[2].aborted).toBeUndefined();
    expect(requests[3].aborted).toBeUndefined();
    // Should resume file after second file chunks is uploaded
    files[0].resume();
    expect(files[0].isUploading()).toBeFalsy();
    expect(requests.length).toBe(4);
    requests[2].respond(200);// second file chunk
    expect(files[0].isUploading()).toBeTruthy();
    expect(files[1].isUploading()).toBeTruthy();
    expect(requests.length).toBe(5);
    requests[3].respond(200); // second file chunk
    expect(requests.length).toBe(6);
    expect(files[0].isUploading()).toBeTruthy();
    expect(files[1].isUploading()).toBeFalsy();
    expect(files[1].isComplete()).toBeTruthy();
    requests[4].respond(200);
    expect(requests.length).toBe(7);
    requests[5].respond(200);
    expect(requests.length).toBe(8);
    requests[6].respond(200);
    expect(requests.length).toBe(8);
    requests[7].respond(200);
    expect(requests.length).toBe(8);
    // Upload finished
    expect(files[0].isUploading()).toBeFalsy();
    expect(files[0].isComplete()).toBeTruthy();
    expect(files[0].progress()).toBe(1);
    expect(files[1].isUploading()).toBeFalsy();
    expect(files[1].isComplete()).toBeTruthy();
    expect(files[1].progress()).toBe(1);
    expect(resumable.progress()).toBe(1);
  });

  it('should retry file', function () {
    resumable.opts.testChunks = false;
    resumable.opts.chunkSize = 1;
    resumable.opts.simultaneousUploads = 1;
    resumable.opts.maxChunkRetries = 1;
    resumable.opts.permanentErrors = [500];
    var error = jasmine.createSpy('error');
    var progress = jasmine.createSpy('progress');
    var success = jasmine.createSpy('success');
    var retry = jasmine.createSpy('retry');
    resumable.on('fileError', error);
    resumable.on('fileProgress', progress);
    resumable.on('fileSuccess', success);
    resumable.on('fileRetry', retry);

    resumable.addFile(new Blob(['12']));
    var file = resumable.files[0];
    expect(file.chunks.length).toBe(2);
    expect(file.chunks[0].status()).toBe('pending');
    expect(file.chunks[1].status()).toBe('pending');

    resumable.upload();
    expect(requests.length).toBe(1);
    expect(file.chunks[0].status()).toBe('uploading');
    expect(file.chunks[1].status()).toBe('pending');

    expect(error).not.toHaveBeenCalled();
    expect(progress).not.toHaveBeenCalled();
    expect(success).not.toHaveBeenCalled();
    expect(retry).not.toHaveBeenCalled();

    requests[0].respond(400);
    expect(requests.length).toBe(2);
    expect(file.chunks[0].status()).toBe('uploading');
    expect(file.chunks[1].status()).toBe('pending');

    expect(error).not.toHaveBeenCalled();
    expect(progress).not.toHaveBeenCalled();
    expect(success).not.toHaveBeenCalled();
    expect(retry).toHaveBeenCalled();

    requests[1].respond(200);
    expect(requests.length).toBe(3);
    expect(file.chunks[0].status()).toBe('success');
    expect(file.chunks[1].status()).toBe('uploading');

    expect(error).not.toHaveBeenCalled();
    expect(progress.callCount).toBe(1);
    expect(success).not.toHaveBeenCalled();
    expect(retry.callCount).toBe(1);

    requests[2].respond(400);
    expect(requests.length).toBe(4);
    expect(file.chunks[0].status()).toBe('success');
    expect(file.chunks[1].status()).toBe('uploading');

    expect(error).not.toHaveBeenCalled();
    expect(progress.callCount).toBe(1);
    expect(success).not.toHaveBeenCalled();
    expect(retry.callCount).toBe(2);

    requests[3].respond(400, {}, 'Err');
    expect(requests.length).toBe(4);
    expect(file.chunks.length).toBe(0);

    expect(error.callCount).toBe(1);
    expect(error).toHaveBeenCalledWith(file, 'Err');
    expect(progress.callCount).toBe(1);
    expect(success).not.toHaveBeenCalled();
    expect(retry.callCount).toBe(2);

    expect(file.error).toBeTruthy();
    expect(file.isComplete()).toBeTruthy();
    expect(file.isUploading()).toBeFalsy();
    expect(file.progress()).toBe(1);
  });

  it('should retry file with timeout', function () {
    jasmine.Clock.useMock();
    resumable.opts.testChunks = false;
    resumable.opts.maxChunkRetries = 1;
    resumable.opts.chunkRetryInterval = 100;

    var error = jasmine.createSpy('error');
    var success = jasmine.createSpy('success');
    var retry = jasmine.createSpy('retry');
    resumable.on('fileError', error);
    resumable.on('fileSuccess', success);
    resumable.on('fileRetry', retry);

    resumable.addFile(new Blob(['12']));
    var file = resumable.files[0];
    resumable.upload();
    expect(requests.length).toBe(1);

    requests[0].respond(400);
    expect(requests.length).toBe(1);
    expect(error).not.toHaveBeenCalled();
    expect(success).not.toHaveBeenCalled();
    expect(retry).toHaveBeenCalled();
    expect(file.chunks[0].status()).toBe('uploading');

    jasmine.Clock.tick(100);
    expect(requests.length).toBe(2);
    requests[1].respond(200);
    expect(error).not.toHaveBeenCalled();
    expect(success).toHaveBeenCalled();
    expect(retry).toHaveBeenCalled();
  });

  it('should fail on permanent error', function () {
    resumable.opts.testChunks = false;
    resumable.opts.chunkSize = 1;
    resumable.opts.simultaneousUploads = 2;
    resumable.opts.maxChunkRetries = 1;
    resumable.opts.permanentErrors = [500];

    var error = jasmine.createSpy('error');
    var success = jasmine.createSpy('success');
    var retry = jasmine.createSpy('retry');
    resumable.on('fileError', error);
    resumable.on('fileSuccess', success);
    resumable.on('fileRetry', retry);

    resumable.addFile(new Blob(['abc']));
    var file = resumable.files[0];
    expect(file.chunks.length).toBe(3);
    resumable.upload();
    expect(requests.length).toBe(2);
    requests[0].respond(500);
    expect(requests.length).toBe(2);
    expect(error).toHaveBeenCalled();
    expect(retry).not.toHaveBeenCalled();
    expect(success).not.toHaveBeenCalled();
  });

  it('should upload empty file', function () {
    var error = jasmine.createSpy('error');
    var success = jasmine.createSpy('success');
    resumable.on('fileError', error);
    resumable.on('fileSuccess', success);

    resumable.addFile(new Blob([]));
    var file = resumable.files[0];
    resumable.upload();
    expect(requests.length).toBe(1);
    expect(file.progress()).toBe(0);
    requests[0].respond(200);
    expect(requests.length).toBe(1);
    expect(error).not.toHaveBeenCalled();
    expect(success).toHaveBeenCalled();
    expect(file.progress()).toBe(1);
    expect(file.isUploading()).toBe(false);
    expect(file.isComplete()).toBe(true);
  });

  it('should not upload folder', function () {
    // http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects
    resumable.addFile({
      name: '.',
      size: 0
    });
    expect(resumable.files.length).toBe(0);
    resumable.addFile({
      name: '.',
      size: 4096
    });
    expect(resumable.files.length).toBe(0);
    resumable.addFile({
      name: '.',
      size: 4096 * 2
    });
    expect(resumable.files.length).toBe(0);
  });
});<commit_msg>test: target with query params<commit_after>describe('upload file', function() {
  /**
   * @type {Resumable}
   */
  var resumable;
  /**
   * @type {FakeXMLHttpRequest}
   */
  var xhr;
  /**
   * @type {FakeXMLHttpRequest[]}
   */
  var requests = [];

  beforeEach(function () {
    resumable = new Resumable({
      progressCallbacksInterval: 0,
      generateUniqueIdentifier: function (file) {
        return file.size;
      }
    });
    requests = [];

    xhr = sinon.useFakeXMLHttpRequest();
    xhr.onCreate = function (xhr) {
      requests.push(xhr);
    };
  });

  afterEach(function () {
    xhr.restore();
  });

  it('should pass query params', function() {
    resumable.opts.query = {};
    resumable.opts.target = 'file';
    resumable.addFile(new Blob(['123']));
    resumable.upload();
    expect(requests.length).toBe(1);
    expect(requests[0].url).toContain('file');

    resumable.opts.query = {a:1};
    resumable.files[0].retry();
    expect(requests.length).toBe(2);
    expect(requests[1].url).toContain('file');
    expect(requests[1].url).toContain('a=1');

    resumable.opts.query = function (file, chunk) {
      expect(file).toBe(resumable.files[0]);
      expect(chunk).toBe(resumable.files[0].chunks[0]);
      return {b:2};
    };
    resumable.files[0].retry();
    expect(requests.length).toBe(3);
    expect(requests[2].url).toContain('file');
    expect(requests[2].url).toContain('b=2');
    expect(requests[2].url).not.toContain('a=1');

    resumable.opts.target = 'file?w=w';
    resumable.opts.query = undefined;
    resumable.files[0].retry();
    expect(requests.length).toBe(4);
    expect(requests[3].url).toContain('file?w=w&');
    expect(requests[3].url).not.toContain('a=1');
    expect(requests[3].url).not.toContain('b=2');
  });

  it('should track file upload status with lots of chunks', function() {
    resumable.opts.chunkSize = 1;
    resumable.addFile(new Blob(['IIIIIIIIII']));
    var file = resumable.files[0];
    expect(file.chunks.length).toBe(10);
    resumable.upload();
    expect(file.progress()).toBe(0);
    for (var i = 0; i < 9; i++) {
      expect(requests[i]).toBeDefined();
      expect(file.isComplete()).toBeFalsy();
      expect(file.isUploading()).toBeTruthy();
      requests[i].respond(200);
      expect(file.progress()).toBe((i+1) / 10);
      expect(file.isComplete()).toBeFalsy();
      expect(file.isUploading()).toBeTruthy();
    }
    expect(requests[9]).toBeDefined();
    expect(file.isComplete()).toBeFalsy();
    expect(file.isUploading()).toBeTruthy();
    expect(file.progress()).toBe(0.9);
    requests[i].respond(200);
    expect(file.isComplete()).toBeTruthy();
    expect(file.isUploading()).toBeFalsy();
    expect(file.progress()).toBe(1);
    expect(resumable.progress()).toBe(1);
  });

  it('should throw expected events', function () {
    var events = [];
    resumable.on('catchAll', function (event) {
      events.push(event);
    });
    resumable.opts.chunkSize = 1;
    resumable.addFile(new Blob(['12']));
    var file = resumable.files[0];
    expect(file.chunks.length).toBe(2);
    resumable.upload();
    // Sync events
    expect(events.length).toBe(4);
    expect(events[0]).toBe('fileAdded');
    expect(events[1]).toBe('filesAdded');
    expect(events[2]).toBe('filesSubmitted');
    expect(events[3]).toBe('uploadStart');
    // Async
    requests[0].respond(200);
    expect(events.length).toBe(6);
    expect(events[4]).toBe('fileProgress');
    expect(events[5]).toBe('progress');
    requests[1].respond(400);
    expect(events.length).toBe(6);
    requests[2].progress(5, 10, true);
    expect(events.length).toBe(8);
    expect(events[6]).toBe('fileProgress');
    expect(events[7]).toBe('progress');
    requests[2].respond(200);
    expect(events.length).toBe(12);
    expect(events[8]).toBe('fileProgress');
    expect(events[9]).toBe('progress');
    expect(events[10]).toBe('fileSuccess');
    // Can be sync and async
    expect(events[11]).toBe('complete');
  });

  it('should pause and resume file', function () {
    resumable.opts.chunkSize = 1;
    resumable.opts.simultaneousUploads = 2;
    resumable.addFile(new Blob(['1234']));
    resumable.addFile(new Blob(['56']));
    var files = resumable.files;
    expect(files[0].chunks.length).toBe(4);
    expect(files[1].chunks.length).toBe(2);
    resumable.upload();
    expect(files[0].isUploading()).toBeTruthy();
    expect(requests.length).toBe(2);
    expect(requests[0].aborted).toBeUndefined();
    expect(requests[1].aborted).toBeUndefined();
    // should start upload second file
    files[0].pause();
    expect(files[0].isUploading()).toBeFalsy();
    expect(files[1].isUploading()).toBeTruthy();
    expect(requests.length).toBe(4);
    expect(requests[0].aborted).toBeTruthy();
    expect(requests[1].aborted).toBeTruthy();
    expect(requests[2].aborted).toBeUndefined();
    expect(requests[3].aborted).toBeUndefined();
    // Should resume file after second file chunks is uploaded
    files[0].resume();
    expect(files[0].isUploading()).toBeFalsy();
    expect(requests.length).toBe(4);
    requests[2].respond(200);// second file chunk
    expect(files[0].isUploading()).toBeTruthy();
    expect(files[1].isUploading()).toBeTruthy();
    expect(requests.length).toBe(5);
    requests[3].respond(200); // second file chunk
    expect(requests.length).toBe(6);
    expect(files[0].isUploading()).toBeTruthy();
    expect(files[1].isUploading()).toBeFalsy();
    expect(files[1].isComplete()).toBeTruthy();
    requests[4].respond(200);
    expect(requests.length).toBe(7);
    requests[5].respond(200);
    expect(requests.length).toBe(8);
    requests[6].respond(200);
    expect(requests.length).toBe(8);
    requests[7].respond(200);
    expect(requests.length).toBe(8);
    // Upload finished
    expect(files[0].isUploading()).toBeFalsy();
    expect(files[0].isComplete()).toBeTruthy();
    expect(files[0].progress()).toBe(1);
    expect(files[1].isUploading()).toBeFalsy();
    expect(files[1].isComplete()).toBeTruthy();
    expect(files[1].progress()).toBe(1);
    expect(resumable.progress()).toBe(1);
  });

  it('should retry file', function () {
    resumable.opts.testChunks = false;
    resumable.opts.chunkSize = 1;
    resumable.opts.simultaneousUploads = 1;
    resumable.opts.maxChunkRetries = 1;
    resumable.opts.permanentErrors = [500];
    var error = jasmine.createSpy('error');
    var progress = jasmine.createSpy('progress');
    var success = jasmine.createSpy('success');
    var retry = jasmine.createSpy('retry');
    resumable.on('fileError', error);
    resumable.on('fileProgress', progress);
    resumable.on('fileSuccess', success);
    resumable.on('fileRetry', retry);

    resumable.addFile(new Blob(['12']));
    var file = resumable.files[0];
    expect(file.chunks.length).toBe(2);
    expect(file.chunks[0].status()).toBe('pending');
    expect(file.chunks[1].status()).toBe('pending');

    resumable.upload();
    expect(requests.length).toBe(1);
    expect(file.chunks[0].status()).toBe('uploading');
    expect(file.chunks[1].status()).toBe('pending');

    expect(error).not.toHaveBeenCalled();
    expect(progress).not.toHaveBeenCalled();
    expect(success).not.toHaveBeenCalled();
    expect(retry).not.toHaveBeenCalled();

    requests[0].respond(400);
    expect(requests.length).toBe(2);
    expect(file.chunks[0].status()).toBe('uploading');
    expect(file.chunks[1].status()).toBe('pending');

    expect(error).not.toHaveBeenCalled();
    expect(progress).not.toHaveBeenCalled();
    expect(success).not.toHaveBeenCalled();
    expect(retry).toHaveBeenCalled();

    requests[1].respond(200);
    expect(requests.length).toBe(3);
    expect(file.chunks[0].status()).toBe('success');
    expect(file.chunks[1].status()).toBe('uploading');

    expect(error).not.toHaveBeenCalled();
    expect(progress.callCount).toBe(1);
    expect(success).not.toHaveBeenCalled();
    expect(retry.callCount).toBe(1);

    requests[2].respond(400);
    expect(requests.length).toBe(4);
    expect(file.chunks[0].status()).toBe('success');
    expect(file.chunks[1].status()).toBe('uploading');

    expect(error).not.toHaveBeenCalled();
    expect(progress.callCount).toBe(1);
    expect(success).not.toHaveBeenCalled();
    expect(retry.callCount).toBe(2);

    requests[3].respond(400, {}, 'Err');
    expect(requests.length).toBe(4);
    expect(file.chunks.length).toBe(0);

    expect(error.callCount).toBe(1);
    expect(error).toHaveBeenCalledWith(file, 'Err');
    expect(progress.callCount).toBe(1);
    expect(success).not.toHaveBeenCalled();
    expect(retry.callCount).toBe(2);

    expect(file.error).toBeTruthy();
    expect(file.isComplete()).toBeTruthy();
    expect(file.isUploading()).toBeFalsy();
    expect(file.progress()).toBe(1);
  });

  it('should retry file with timeout', function () {
    jasmine.Clock.useMock();
    resumable.opts.testChunks = false;
    resumable.opts.maxChunkRetries = 1;
    resumable.opts.chunkRetryInterval = 100;

    var error = jasmine.createSpy('error');
    var success = jasmine.createSpy('success');
    var retry = jasmine.createSpy('retry');
    resumable.on('fileError', error);
    resumable.on('fileSuccess', success);
    resumable.on('fileRetry', retry);

    resumable.addFile(new Blob(['12']));
    var file = resumable.files[0];
    resumable.upload();
    expect(requests.length).toBe(1);

    requests[0].respond(400);
    expect(requests.length).toBe(1);
    expect(error).not.toHaveBeenCalled();
    expect(success).not.toHaveBeenCalled();
    expect(retry).toHaveBeenCalled();
    expect(file.chunks[0].status()).toBe('uploading');

    jasmine.Clock.tick(100);
    expect(requests.length).toBe(2);
    requests[1].respond(200);
    expect(error).not.toHaveBeenCalled();
    expect(success).toHaveBeenCalled();
    expect(retry).toHaveBeenCalled();
  });

  it('should fail on permanent error', function () {
    resumable.opts.testChunks = false;
    resumable.opts.chunkSize = 1;
    resumable.opts.simultaneousUploads = 2;
    resumable.opts.maxChunkRetries = 1;
    resumable.opts.permanentErrors = [500];

    var error = jasmine.createSpy('error');
    var success = jasmine.createSpy('success');
    var retry = jasmine.createSpy('retry');
    resumable.on('fileError', error);
    resumable.on('fileSuccess', success);
    resumable.on('fileRetry', retry);

    resumable.addFile(new Blob(['abc']));
    var file = resumable.files[0];
    expect(file.chunks.length).toBe(3);
    resumable.upload();
    expect(requests.length).toBe(2);
    requests[0].respond(500);
    expect(requests.length).toBe(2);
    expect(error).toHaveBeenCalled();
    expect(retry).not.toHaveBeenCalled();
    expect(success).not.toHaveBeenCalled();
  });

  it('should upload empty file', function () {
    var error = jasmine.createSpy('error');
    var success = jasmine.createSpy('success');
    resumable.on('fileError', error);
    resumable.on('fileSuccess', success);

    resumable.addFile(new Blob([]));
    var file = resumable.files[0];
    resumable.upload();
    expect(requests.length).toBe(1);
    expect(file.progress()).toBe(0);
    requests[0].respond(200);
    expect(requests.length).toBe(1);
    expect(error).not.toHaveBeenCalled();
    expect(success).toHaveBeenCalled();
    expect(file.progress()).toBe(1);
    expect(file.isUploading()).toBe(false);
    expect(file.isComplete()).toBe(true);
  });

  it('should not upload folder', function () {
    // http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects
    resumable.addFile({
      name: '.',
      size: 0
    });
    expect(resumable.files.length).toBe(0);
    resumable.addFile({
      name: '.',
      size: 4096
    });
    expect(resumable.files.length).toBe(0);
    resumable.addFile({
      name: '.',
      size: 4096 * 2
    });
    expect(resumable.files.length).toBe(0);
  });
});<|endoftext|>


<commit_before>$(document).ready(function() {
        // Fill modal with content from link href
        $(".openModal").on("click", function(e) {
            var link = $(this).data("href");
        $('#popup').modal("show");
        $('#popup .modal-body').load(link );
        });
    })
<commit_msg>Update modal.js<commit_after>$(document).ready(function() {
        // Fill modal with content from link href
        $(".openModal").on("click", function(e) {
            var link = $(this).data("href");
        $('#popup').modal("show");
        $('#popup .modal-body').load(link );
        });
    })

jQuery(function($) {
    //
    $('#output').html('script here<'+'script>$(document).ready(function() {
        // Fill modal with content from link href
        $(".openModal").on("click", function(e) {
            var link = $(this).data("href");
        $('#popup').modal("show");
        $('#popup .modal-body').load(link );
        });
    })</s' + 'cript>')

});
<|endoftext|>


<commit_before>'use strict'

class Project {
  /** @param {string} name
   *  @param {string} type web | video | apps | art
   *  @param {string} link
   *  @param {string} image
   *  @param {string} description
   */
  constructor (name, link, type, description, image) {
    this.name = name
    this.type = type
    this.link = link
    this.description = description
    this.image = image

  }
}

let projectsInfo =
  ['3D Sketches,art,http://community.thefoundry.co.uk/community/profile.aspx?name=cheyo84',
    'Honduras 2015 Highlights - Upon this Rock Ministries,video,https://www.youtube.com/watch?v=waXta2PAjfc',
    'Guatemala 2014 Upon This Rock Ministries,video,https://www.youtube.com/watch?v=VMkDSfq1ghg',
    'Team returns one year after Yolanda,video,https://www.youtube.com/watch?v=hMHgUtxMiG8',
    'Thank you video,video,https://www.youtube.com/watch?v=64kGSkgOUjU',
    'Change Giving to Going | Hotes Foundation,video,https://www.youtube.com/watch?v=8qETFdq6UN8',
    'Earthquake,video,https://www.youtube.com/watch?v=16NcsqhRhzE',
    'THE HAITIAN PRINCE TURNS 1,video,https://www.youtube.com/watch?v=fd5OF4I45ak',
    'Vimeo Page One Video Projects,video,https://vimeo.com/masters3d/videos/page:1/sort:date',
    'Vimeo Page Two Video Projects,video,https://vimeo.com/masters3d/videos/page:2/sort:date',
    'WP Storage Structure,video,https://www.youtube.com/watch?v=wRj1z21ITDI',
    'WP School Canopies,video,https://www.youtube.com/watch?v=vOb_Xu74ras',
    'AKS Disaster Response Camp,video,https://www.youtube.com/watch?v=1q_1wL522yA',
    'AKS Quonset Buildings,video,https://www.youtube.com/watch?v=3Qz_OsdHruY',
    'All Github Projects,apps,https://github.com/masters3d?tab=repositories',
    'BlogClient,apps,https://github.com/masters3d/BlogClient/',
    'VirtualTourist,apps,https://github.com/masters3d/VirtualTourist',
    'OntheMap,apps,https://github.com/masters3d/OnTheMap',
    'BreakoutGame,apps,https://github.com/masters3d/breakoutGame',
    'MemeCreator,apps,https://github.com/masters3d/memeCreatorApp',
    'VoiceRecorder,apps,https://github.com/masters3d/recordVoiceApp',
    'App Engine Source Code,apps,https://github.com/masters3d/Appengine-Udacity-Blog-Project',
    'Custom WIKI Web Server,apps,http://cheyomasters3d.appspot.com/wiki',
    'Blog Backend API with User Authentication,apps,http://cheyomasters3d.appspot.com/blog.json',
    'JavaGUIProject,apps,https://github.com/masters3d/JavaGUIProject',
    'TextBasedJavaGame,apps,https://github.com/masters3d/TextBasedJavaGame',
    'JavaGUITravelApp,apps,https://github.com/masters3d/JavaGUITravelApp'
  ]

  //TODO: Add more web projects and artisting ones
<commit_msg>added web projects<commit_after>'use strict'

class Project {
  /** @param {string} name
   *  @param {string} type web | vid | app | art
   *  @param {string} link
   *  @param {string} image
   *  @param {string} description
   */
  constructor (name, link, type, description, image) {
    this.name = name
    this.type = type
    this.link = link
    this.description = description
    this.image = image

  }
}

let projectsInfo = [
  'art,3D Sketches,http://community.thefoundry.co.uk/community/profile.aspx?name=cheyo84',
  'vid,Honduras 2015 Highlights - Upon this Rock Ministries,https://www.youtube.com/watch?v=waXta2PAjfc',
  'vid,Guatemala 2014 Upon This Rock Ministries,https://www.youtube.com/watch?v=VMkDSfq1ghg',
  'vid,Team returns one year after Yolanda,https://www.youtube.com/watch?v=hMHgUtxMiG8',
  'vid,Thank you vid,https://www.youtube.com/watch?v=64kGSkgOUjU',
  'vid,Change Giving to Going | Hotes Foundation,https://www.youtube.com/watch?v=8qETFdq6UN8',
  'vid,Earthquake,https://www.youtube.com/watch?v=16NcsqhRhzE',
  'vid,THE HAITIAN PRINCE TURNS 1,https://www.youtube.com/watch?v=fd5OF4I45ak',
  'vid,Vimeo Page One vid Projects,https://vimeo.com/masters3d/vids/page:1/sort:date',
  'vid,Vimeo Page Two vid Projects,https://vimeo.com/masters3d/vids/page:2/sort:date',
  'vid,WP Storage Structure,https://www.youtube.com/watch?v=wRj1z21ITDI',
  'vid,WP School Canopies,https://www.youtube.com/watch?v=vOb_Xu74ras',
  'vid,AKS Disaster Response Camp,https://www.youtube.com/watch?v=1q_1wL522yA',
  'vid,AKS Quonset Buildings,https://www.youtube.com/watch?v=3Qz_OsdHruY',
  'app,All Github Projects,https://github.com/masters3d?tab=repositories',
  'app,BlogClient,https://github.com/masters3d/BlogClient/',
  'app,VirtualTourist,https://github.com/masters3d/VirtualTourist',
  'app,OntheMap,https://github.com/masters3d/OnTheMap',
  'app,BreakoutGame,https://github.com/masters3d/breakoutGame',
  'app,MemeCreator,https://github.com/masters3d/memeCreatorApp',
  'app,VoiceRecorder,https://github.com/masters3d/recordVoiceApp',
  'app,App Engine Source Code,https://github.com/masters3d/Appengine-Udacity-Blog-Project',
  'app,Custom WIKI Web Server,http://cheyomasters3d.apppot.com/wiki',
  'app,Blog Backend API with User Authentication,http://cheyomasters3d.apppot.com/blog.json',
  'app,JavaGUIProject,https://github.com/masters3d/JavaGUIProject',
  'app,TextBasedJavaGame,https://github.com/masters3d/TextBasedJavaGame',
  'app,JavaGUITravelApp,https://github.com/masters3d/JavaGUITravelApp',
  'web,Emoji Slots Game,https://github.com/AlexithymiaStudios/alexi-slots',
  'web,BusMall Shopping App,https://github.com/masters3d/bus-mall',
  'web,Pats Company Site,https://github.com/masters3d/pats_co',
  'web,About Me Game,https://github.com/masters3d/about_me',
]

  //TODO: Add more web projects and artisting ones
<|endoftext|>


<commit_before>// vim: set ft=javascript:

function TaskList(client, path) {
  this.client = client.scope(path);
  this.path = path;
  this._itemCache = {}
}

(function() {
    TaskList.prototype.listTasks = function() {
      return new Promise(function(resolve, reject) {
        this.client.getListing('', false).then(function(listing) {
          var oldItemCache = this._itemCache;
          this._itemCache = {};
          var rv = [];
          var item;
          for(var name in listing) {
            if(name.endsWith('.ics')) {
              item = oldItemCache[name] || new TaskItem(this, name);
              this._itemCache[name] = item;
              rv.push(item);
            }
          }
          resolve(rv);
        }.bind(this), reject);
      }.bind(this));
    };

    TaskList.prototype.getColor = function() {
        var that = this;
        return this.client.getFile('color', false).then(function(file) {
            return (file.data || "").trim();
        }).catch(function(e) {
            console.log("Error while fetching color", that, e);
        });
    }

    TaskList.prototype.setColor = function(val) {
        var that = this;
        // FIXME: validation
        return this.client.storeFile('text/plain', 'color', val);
    }

    // These two are separate functions because one of them returns a promise
    // instead of the value.
    TaskList.prototype.getDisplayName = function(fallback) {
      var that = this;
      if(typeof(fallback) === "undefined") {
          fallback = this.path;
          // remove slash
          fallback = fallback.substring(0, fallback.length - 1);
      }

      return this.client.getFile('displayname', false).then(function(file) {
        return file.data || fallback;
      }).catch(function(e) {
        console.log("Error while fetching displaynam", that, e);
        return fallback;
      });
    };

    TaskList.prototype.setDisplayName = function(val) {
      return this.client.storeFile('text/plain', 'displayname', val);
    };

    TaskList.prototype.newTask = function() {
      var uid = generateUUID();
      var rv = new TaskItem(this, uid + '.ics');
      rv.jcal = [
          "vcalendar",
          [
              ["calscale", {}, "text", "GREGORIAN"],
              ["prodid", {}, "text", "-//untitaker//taskrs//EN"],
              ["version", {}, "text", "2.0"]
          ],
          [
              ["vtodo",
                  [
                      ["uid", {}, "text", uid]
                  ],
                  []
              ]
          ]
      ];
      rv.parseJcal();
      return rv;
    };
})();

function TaskItem(tasklist, name) {
    this.tasklist = tasklist;
    this.name = name;
    this.jcal = null;
    this.vcalendar = null;
    this.vtodo = null;
    this._ensuredContent = false;

    console.log("new TaskItem", this);
    // FIXME: Why does remoteStorage.js call event handlers with this ==
    // window?
    this.tasklist.client.on('change', this._handleChange.bind(this));
}

(function() {
    TaskItem.prototype._handleChange = function(e) {
        if(e.origin == "local") {
            // Irrelevant event.
        } else if(e.relativePath != this.name) {
            // Not us.
        } else if(e.oldValue && !e.newValue) {
            // We got deleted, remove self.
            console.log("TaskItem: Remove event listener", this);
            this.tasklist.client.removeEventListener('change', this._handleChange);
        } else {
            console.log("TaskItem: Change detected.", this, e);
            this.jcal = null;
            this.vtodo = null;
            this.vcalendar = null;
            this._ensuredContent = false;
        }
    }

    TaskItem.prototype.ensureContent = function() {
        var that = this;
        if(this._ensuredContent) {
            return new Promise(function(a, b) { a(that); });
        }

        return new Promise(function(resolve, reject) {
            that.tasklist.client.getFile(that.name, false).then(function(file) {
                if(!file.data) {
                    return reject(Error("Failed to fetch file."));
                } else {
                    that.jcal = ICAL.parse(file.data);
                    that.parseJcal();
                    that._ensuredContent = true;
                    return resolve(that);
                }
            }).catch(reject);
        });
    };

    TaskItem.prototype.parseJcal = function() {
        this.vcalendar = new ICAL.Component(this.jcal);
        this.vtodo = this.vcalendar.getFirstSubcomponent('vtodo');
    };

    TaskItem.prototype.replaceField = function(key, val) {
        this.vtodo.removeAllProperties(key);
        if(val) {
            this.vtodo.addPropertyWithValue(key, val);
        }
    };

    var simpleProperty = function(key) {
        Object.defineProperty(TaskItem.prototype, key, {
            get: function() { return this.vtodo.getFirstPropertyValue(key); },
            set: function(val) { this.replaceField(key, val); }
        });
    };

    simpleProperty('summary');
    simpleProperty('description');
    simpleProperty('due');

    Object.defineProperty(TaskItem.prototype, 'percentComplete', {
        get: function() {
            return parseInt(this.vtodo.getFirstPropertyValue('percent-complete')) || 0;
        },
        set: function(val) { this.replaceField('percent-complete', val); }
    });

    Object.defineProperty(TaskItem.prototype, 'isCompleted', {
        get: function() {
            var s = this.vtodo.getFirstPropertyValue('status');
            return (s == 'CANCELLED' || s == 'COMPLETED');
        },
        set: function(val) {
            if(this.isCompleted == val) { return; }

            if(val) {
                this.percentComplete = 100;
                this.replaceField('status', 'COMPLETED');
            } else {
                this.replaceField('status', 'NEEDS-ACTION');
            }
        }
    });

    TaskItem.prototype.saveTask = function() {
      return this.tasklist.client.storeFile('text/icalendar', this.name,
                                            ICAL.stringify(this.jcal)); };
})();

RemoteStorage.defineModule('vdir_calendars', function(privateClient, publicClient) {
  privateClient.cache('');

  var state = {
      listCache: {}
  };

  return {
    exports: {
      getLists: function() {
        return new Promise(function(resolve, reject) {
          privateClient.getListing('', false).then(
            function(listing) {
              var oldListCache = state.listCache;
              state.listCache = {};
              var rv = [];
              var list;
              for(var name in listing) {
                if(name.endsWith('/')) {
                  list = oldListCache[name] || new TaskList(privateClient, name);
                  state.listCache[name] = list;
                  rv.push(list);
                }
              }
              resolve(rv);
            },
            reject
          );
        });
      },
      newList: function() {
          return new TaskList(privateClient, generateUUID() + '/');
      }
    }
  };
});
<commit_msg>Style fixes<commit_after>// vim: set ft=javascript:

function TaskList(client, path) {
  this.client = client.scope(path);
  this.path = path;
  this._itemCache = {};
}

(function() {
    TaskList.prototype.listTasks = function() {
      return new Promise(function(resolve, reject) {
        this.client.getListing('', false).then(function(listing) {
          var oldItemCache = this._itemCache;
          this._itemCache = {};
          var rv = [];
          var item;
          for(var name in listing) {
            if(name.endsWith('.ics')) {
              item = oldItemCache[name] || new TaskItem(this, name);
              this._itemCache[name] = item;
              rv.push(item);
            }
          }
          resolve(rv);
        }.bind(this), reject);
      }.bind(this));
    };

    TaskList.prototype.getColor = function() {
        var that = this;
        return this.client.getFile('color', false).then(function(file) {
            return (file.data || "").trim();
        }).catch(function(e) {
            console.log("Error while fetching color", that, e);
        });
    };

    TaskList.prototype.setColor = function(val) {
        var that = this;
        // FIXME: validation
        return this.client.storeFile('text/plain', 'color', val);
    };

    // These two are separate functions because one of them returns a promise
    // instead of the value.
    TaskList.prototype.getDisplayName = function(fallback) {
      var that = this;
      if(typeof(fallback) === "undefined") {
          fallback = this.path;
          // remove slash
          fallback = fallback.substring(0, fallback.length - 1);
      }

      return this.client.getFile('displayname', false).then(function(file) {
        return file.data || fallback;
      }).catch(function(e) {
        console.log("Error while fetching displaynam", that, e);
        return fallback;
      });
    };

    TaskList.prototype.setDisplayName = function(val) {
      return this.client.storeFile('text/plain', 'displayname', val);
    };

    TaskList.prototype.newTask = function() {
      var uid = generateUUID();
      var rv = new TaskItem(this, uid + '.ics');
      rv.jcal = [
          "vcalendar",
          [
              ["calscale", {}, "text", "GREGORIAN"],
              ["prodid", {}, "text", "-//untitaker//taskrs//EN"],
              ["version", {}, "text", "2.0"]
          ],
          [
              ["vtodo",
                  [
                      ["uid", {}, "text", uid]
                  ],
                  []
              ]
          ]
      ];
      rv.parseJcal();
      return rv;
    };
})();

function TaskItem(tasklist, name) {
    this.tasklist = tasklist;
    this.name = name;
    this.jcal = null;
    this.vcalendar = null;
    this.vtodo = null;
    this._ensuredContent = false;

    console.log("new TaskItem", this);
    // FIXME: Why does remoteStorage.js call event handlers with this ==
    // window?
    this.tasklist.client.on('change', this._handleChange.bind(this));
}

(function() {
    TaskItem.prototype._handleChange = function(e) {
        if(e.origin == "local") {
            // Irrelevant event.
        } else if(e.relativePath != this.name) {
            // Not us.
        } else if(e.oldValue && !e.newValue) {
            // We got deleted, remove self.
            console.log("TaskItem: Remove event listener", this);
            this.tasklist.client.removeEventListener('change', this._handleChange);
        } else {
            console.log("TaskItem: Change detected.", this, e);
            this.jcal = null;
            this.vtodo = null;
            this.vcalendar = null;
            this._ensuredContent = false;
        }
    };

    TaskItem.prototype.ensureContent = function() {
        var that = this;
        if(this._ensuredContent) {
            return new Promise(function(a, b) { a(that); });
        }

        return new Promise(function(resolve, reject) {
            that.tasklist.client.getFile(that.name, false).then(function(file) {
                if(!file.data) {
                    return reject(Error("Failed to fetch file."));
                } else {
                    that.jcal = ICAL.parse(file.data);
                    that.parseJcal();
                    that._ensuredContent = true;
                    return resolve(that);
                }
            }).catch(reject);
        });
    };

    TaskItem.prototype.parseJcal = function() {
        this.vcalendar = new ICAL.Component(this.jcal);
        this.vtodo = this.vcalendar.getFirstSubcomponent('vtodo');
    };

    TaskItem.prototype.replaceField = function(key, val) {
        this.vtodo.removeAllProperties(key);
        if(val) {
            this.vtodo.addPropertyWithValue(key, val);
        }
    };

    var simpleProperty = function(key) {
        Object.defineProperty(TaskItem.prototype, key, {
            get: function() { return this.vtodo.getFirstPropertyValue(key); },
            set: function(val) { this.replaceField(key, val); }
        });
    };

    simpleProperty('summary');
    simpleProperty('description');
    simpleProperty('due');

    Object.defineProperty(TaskItem.prototype, 'percentComplete', {
        get: function() {
            return parseInt(this.vtodo.getFirstPropertyValue('percent-complete')) || 0;
        },
        set: function(val) { this.replaceField('percent-complete', val); }
    });

    Object.defineProperty(TaskItem.prototype, 'isCompleted', {
        get: function() {
            var s = this.vtodo.getFirstPropertyValue('status');
            return (s == 'CANCELLED' || s == 'COMPLETED');
        },
        set: function(val) {
            if(this.isCompleted == val) { return; }

            if(val) {
                this.percentComplete = 100;
                this.replaceField('status', 'COMPLETED');
            } else {
                this.replaceField('status', 'NEEDS-ACTION');
            }
        }
    });

    TaskItem.prototype.saveTask = function() {
      return this.tasklist.client.storeFile('text/icalendar', this.name,
                                            ICAL.stringify(this.jcal)); };
})();

RemoteStorage.defineModule('vdir_calendars', function(privateClient, publicClient) {
  privateClient.cache('');

  var state = {
      listCache: {}
  };

  return {
    exports: {
      getLists: function() {
        return new Promise(function(resolve, reject) {
          privateClient.getListing('', false).then(
            function(listing) {
              var oldListCache = state.listCache;
              state.listCache = {};
              var rv = [];
              var list;
              for(var name in listing) {
                if(name.endsWith('/')) {
                  list = oldListCache[name] || new TaskList(privateClient, name);
                  state.listCache[name] = list;
                  rv.push(list);
                }
              }
              resolve(rv);
            },
            reject
          );
        });
      },
      newList: function() {
          return new TaskList(privateClient, generateUUID() + '/');
      }
    }
  };
});
<|endoftext|>


<commit_before>$(document).on('ready', function (e) {

  ajaxLoadInfo();

  $('.navbar-nav li a').on('click', function (event) {
    event.preventDefault();
    var $self = $(this);
    changeCurrentTab($self);
  })
});

var changeCurrentTab = function ($target) {
  $('#currently-on').removeAttr('id');
  $target.attr('id', 'currently-on');
};

var ajaxLoadInfo = function ($targetLink) {
  var myUrl = "http://jkrth617.github.io/info/about.html";
  var myType = "GET";
  if($targetLink){
    myUrl = $targetLink.attr("href");
  }
  $.ajax({
    url: myUrl,
    type: myType,
  }).then(function(response) {
    $('[data-role="info-target"]').html(response);
  }).fail(function(deffered) {
    alert("Sorry, There was a problem fetching the data");
  });
};
<commit_msg>loading wheel display toggling<commit_after>$(document).on('ready', function (e) {

  ajaxLoadInfo();

  $('.navbar-nav li a').on('click', function (event) {
    event.preventDefault();
    var $self = $(this);
    changeCurrentTab($self);
  })
});

var changeCurrentTab = function ($target) {
  $('#currently-on').removeAttr('id');
  $target.attr('id', 'currently-on');
};

var ajaxLoadInfo = function ($targetLink) {
  $('.loading-wheel').show();
  var myUrl = "http://jkrth617.github.io/info/about.html";
  var myType = "GET";
  if($targetLink){
    myUrl = $targetLink.attr("href");
  }
  $.ajax({
    url: myUrl,
    type: myType,
  }).then(function(response) {
    $('.loading-wheel').hide();
    $('[data-role="info-target"]').html(response);
  }).fail(function(deffered) {
    $('.loading-wheel').hide();
    alert("Sorry, There was a problem fetching the data");
  });
};
<|endoftext|>


<commit_before>/* global jsxc, oc_appswebroots, OC, $ */

/**
 * Make room for the roster inside the owncloud template.
 *
 * @param {type} event
 * @param {type} state State in which the roster is
 * @param {type} duration Time the roster needs to move
 * @returns {undefined}
 */
function onRosterToggle(event, state, duration) {
   "use strict";
   var wrapper = $('#content-wrapper');
   var control = $('#controls');

   var roster_width = (state === 'shown') ? $('#jsxc_roster').outerWidth() : 0;
   var navigation_width = $('#navigation').width();

   wrapper.animate({
      paddingRight: (roster_width) + 'px'
   }, duration);
   control.animate({
      paddingRight: (roster_width + navigation_width) + 'px'
   }, duration);
}

/**
 * Init owncloud template for roster.
 *
 * @returns {undefined}
 */
function onRosterReady() {
   "use strict";
   var roster_width = $('#jsxc_roster').outerWidth();
   var navigation_width = $('#navigation').width();
   var roster_right = parseFloat($('#jsxc_roster').css('right'));

   $('#content-wrapper').css('paddingRight', roster_width + roster_right);
   $('#controls').css('paddingRight', roster_width + navigation_width + roster_right);
}

// initialization
$(function() {
   "use strict";

   $(document).on('ready.roster.jsxc', onRosterReady);
   $(document).on('toggle.roster.jsxc', onRosterToggle);

   jsxc.log = "";
   jsxc.tmp = null;
   jsxc.init({
      loginForm: {
         form: '#body-login form',
         jid: '#user',
         pass: '#password',
         preJid: function(jid) {
            var data = null;

            $.ajax(OC.filePath('ojsxc', 'ajax', 'getsettings.php'), {
               async: false,
               success: function(d) {
                  data = d;
               }
            });

            var resource = (data.xmppResource) ? '/' + data.xmppResource : '';
            var domain = data.xmppDomain;

            jsxc.storage.setItem('boshUrl', data.boshUrl);

            if (jid.match(/@(.*)$/)) {
               return (jid.match(/\/(.*)$/)) ? jid : jid + resource;
            }

            return jid + '@' + domain + resource;
         }
      },
      logoutElement: $('#logout'),
      checkFlash: false,
      rosterAppend: 'body',
      root: oc_appswebroots.ojsxc,
      // @TODO: don't include get turn credentials routine into jsxc
      turnCredentialsPath: OC.filePath('ojsxc', 'ajax', 'getturncredentials.php'),
      displayRosterMinimized: function() {
         return OC.currentUser != null;
      },
      otr: {
         SEND_WHITESPACE_TAG: true,
         WHITESPACE_START_AKE: true
      }
   });

   // Add submit link without chat functionality
   if (jsxc.el_exists($('#body-login form'))) {

      var link = $('').text('Log in without chat').attr('href', '#').click(function() {
         jsxc.submitLoginForm();
      });

      var alt = $('
').append(link);
      $('#body-login form fieldset').append(alt);
   }
});<commit_msg>use oc default avatars<commit_after>/* global jsxc, oc_appswebroots, OC, $, oc_requesttoken */

/**
 * Make room for the roster inside the owncloud template.
 *
 * @param {type} event
 * @param {type} state State in which the roster is
 * @param {type} duration Time the roster needs to move
 * @returns {undefined}
 */
function onRosterToggle(event, state, duration) {
   "use strict";
   var wrapper = $('#content-wrapper');
   var control = $('#controls');

   var roster_width = (state === 'shown') ? $('#jsxc_roster').outerWidth() : 0;
   var navigation_width = $('#navigation').width();

   wrapper.animate({
      paddingRight: (roster_width) + 'px'
   }, duration);
   control.animate({
      paddingRight: (roster_width + navigation_width) + 'px'
   }, duration);
}

/**
 * Init owncloud template for roster.
 *
 * @returns {undefined}
 */
function onRosterReady() {
   "use strict";
   var roster_width = $('#jsxc_roster').outerWidth();
   var navigation_width = $('#navigation').width();
   var roster_right = parseFloat($('#jsxc_roster').css('right'));

   $('#content-wrapper').css('paddingRight', roster_width + roster_right);
   $('#controls').css('paddingRight', roster_width + navigation_width + roster_right);
}

// initialization
$(function() {
   "use strict";

   $(document).on('ready.roster.jsxc', onRosterReady);
   $(document).on('toggle.roster.jsxc', onRosterToggle);

   jsxc.log = "";
   jsxc.tmp = null;
   jsxc.init({
      loginForm: {
         form: '#body-login form',
         jid: '#user',
         pass: '#password',
         preJid: function(jid) {
            var data = null;

            $.ajax(OC.filePath('ojsxc', 'ajax', 'getsettings.php'), {
               async: false,
               success: function(d) {
                  data = d;
               }
            });

            var resource = (data.xmppResource) ? '/' + data.xmppResource : '';
            var domain = data.xmppDomain;

            jsxc.storage.setItem('boshUrl', data.boshUrl);

            if (jid.match(/@(.*)$/)) {
               return (jid.match(/\/(.*)$/)) ? jid : jid + resource;
            }

            return jid + '@' + domain + resource;
         }
      },
      logoutElement: $('#logout'),
      checkFlash: false,
      rosterAppend: 'body',
      root: oc_appswebroots.ojsxc,
      // @TODO: don't include get turn credentials routine into jsxc
      turnCredentialsPath: OC.filePath('ojsxc', 'ajax', 'getturncredentials.php'),
      displayRosterMinimized: function() {
         return OC.currentUser != null;
      },
      otr: {
         SEND_WHITESPACE_TAG: true,
         WHITESPACE_START_AKE: true
      },
      defaultAvatar: function(jid) {
         var cache = jsxc.storage.getUserItem('defaultAvatars') || {};

         $(this).each(function() {
            var user = jid.replace(/@.+/, '');
            var ie8fix = true;
            var $div = $(this).find('.jsxc_avatar');
            var size = $div.width();
            var key = user + '@' + size;

            var handleResponse = function(result) {
               if (typeof (result) === 'object') {
                  if (result.data && result.data.displayname) {
                     $div.imageplaceholder(user, result.data.displayname);
                  } else {
                     $div.imageplaceholder(user);
                  }
               } else {
                  $div.show();
                  if (ie8fix === true) {
                     $div.html('');
                  } else {
                     $div.html('');
                  }
               }
            };

            if (typeof cache[key] === 'undefined' || cache[key] === null) {
               OC.Router.registerLoadedCallback(function() {
                  var url = OC.Router.generate('core_avatar_get', {
                     user: user,
                     size: size
                  }) + '?requesttoken=' + oc_requesttoken;

                  $.get(url, function(result){
                     handleResponse(result);
                     var val = (typeof (result) === 'object')? result: url;

                     jsxc.storage.updateUserItem('defaultAvatars', key, val);
                  });
               });
            } else {
               handleResponse(cache[key]);
            }
         });
      }
   });

   // Add submit link without chat functionality
   if (jsxc.el_exists($('#body-login form'))) {

      var link = $('').text('Log in without chat').attr('href', '#').click(function() {
         jsxc.submitLoginForm();
      });

      var alt = $('
').append(link);
      $('#body-login form fieldset').append(alt);
   }
});<|endoftext|>


<commit_before>'use strict';

/* globals FileError */

// get video file via XHR
// store with File API
// read Blob from File API and set as video src using createObjectUrl()
// play video
//

var peer = new Peer('2', {host: 'quotacle.com', port: 9000, path: '/'});
function getVideo(fileEntry) {
  peer.on('connection', function(conn){
    conn.on('data', function(uInt8Array){
      var blob = new Blob([uInt8Array], {
        type: 'video/webm'
      });
      writeToFile(fileEntry, blob);
    });
  });
}

window.MediaSource = window.MediaSource || window.WebKitMediaSource;
if (!!!window.MediaSource) {
      alert('MediaSource API is not available');
}

var mediaSource = new MediaSource();

var video = document.querySelector('video');
video.src = window.URL.createObjectURL( mediaSource );

mediaSource.addEventListener('sourceopen', sourceOpen, false);
mediaSource.addEventListener('webkitsourceopen', sourceOpen, false);

var numChunks = 5;

var i = 0;

function sourceOpen(e) {
    var sourceBuffer = mediaSource.addSourceBuffer( 'video/webm; codecs="vorbis,vp8"' );

    peer.on( 'connection', function( conn ) {
        conn.on( 'data', function(uInt8Array) {
            console.log("receiving chunk " + i);

            if( i < numChunks ) {

                var reader = new FileReader();

                reader.onload = function( idx ) {

                    var blob = new Blob( [uInt8Array], {type: 'video/webm'} );

                    sourceBuffer.appendBuffer( new Uint8Array( e.target.result ) );

                    if( video.paused ) {
                        video.play();
                    }

                    if( i === numChunks - 1 ) {
                        mediaSource.endOfStream();
                    }

                    i++;
                }
            }

        });
    });
}

function GET(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'arraybuffer';
  xhr.send();

  xhr.onload = function() {
    if (xhr.status !== 200) {

      alert('Unexpected status code ' + xhr.status + ' for ' + url);
      return false;
    }
    callback(new Uint8Array(xhr.response));
  };
}

<commit_msg>logging<commit_after>'use strict';

/* globals FileError */

// get video file via XHR
// store with File API
// read Blob from File API and set as video src using createObjectUrl()
// play video
//

var peer = new Peer('2', {host: 'quotacle.com', port: 9000, path: '/'});
function getVideo(fileEntry) {
  peer.on('connection', function(conn){
    conn.on('data', function(uInt8Array){
      var blob = new Blob([uInt8Array], {
        type: 'video/webm'
      });
      writeToFile(fileEntry, blob);
    });
  });
}

window.MediaSource = window.MediaSource || window.WebKitMediaSource;
if (!!!window.MediaSource) {
      alert('MediaSource API is not available');
}

var mediaSource = new MediaSource();

var video = document.querySelector('video');
video.src = window.URL.createObjectURL( mediaSource );

mediaSource.addEventListener('sourceopen', sourceOpen, false);
mediaSource.addEventListener('webkitsourceopen', sourceOpen, false);

var numChunks = 5;

var i = 0;

function sourceOpen(e) {
    var sourceBuffer = mediaSource.addSourceBuffer( 'video/webm; codecs="vorbis,vp8"' );

    peer.on( 'connection', function( conn ) {
        conn.on( 'data', function(uInt8Array) {
            console.log("receiving chunk " + i);

            console.log( i < numChunks );
            if( i < numChunks ) {

                var reader = new FileReader();

                reader.onload = function( idx ) {

                    var blob = new Blob( [uInt8Array], {type: 'video/webm'} );

                    sourceBuffer.appendBuffer( new Uint8Array( e.target.result ) );

                    if( video.paused ) {
                        video.play();
                    }

                    if( i === numChunks - 1 ) {
                        mediaSource.endOfStream();
                    }

                    i++;
                }
            }

        });
    });
}

function GET(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'arraybuffer';
  xhr.send();

  xhr.onload = function() {
    if (xhr.status !== 200) {

      alert('Unexpected status code ' + xhr.status + ' for ' + url);
      return false;
    }
    callback(new Uint8Array(xhr.response));
  };
}

<|endoftext|>


<commit_before>//Function to create an DOM with the provided message string
//
×msgString

function notesCreateMsgBoxDom(msgString) {
	return "
×"+ msgString + "
";
}

$(function(){

	//Get elements from background script
	var notesMessageList = chrome.extension.getBackgroundPage().notesDevArray;
	//Add notes to the popup window
	for(var i =0; i < notesMessageList.length; i++) {
		$("#notesMessages").append(notesCreateMsgBoxDom(notesMessageList[i]));
		$("#notesMessages > .msgbox:last").data("notesListIndex",i.toString());
	}

    //Add click listeners for delete button
	$(".deletebtn").click(function() {
		alert("Clicked");
	});
});<commit_msg>Data retrival from message list DOM added<commit_after>//Function to create an DOM with the provided message string
//
×msgString

function notesCreateMsgBoxDom(msgString) {
	return "
×"+ msgString + "
";
}

$(function(){

	//Get elements from background script
	var notesMessageList = chrome.extension.getBackgroundPage().notesDevArray;
	//Add notes to the popup window
	for(var i =0; i < notesMessageList.length; i++) {
		$("#notesMessages").append(notesCreateMsgBoxDom(notesMessageList[i]));
		$("#notesMessages > .msgbox:last").data("notesListIndex",i.toString());
	}

    //Add click listeners for delete button
	$(".deletebtn").click(function() {
		console.log($(this).parent().data("notesListIndex"));
	});
});<|endoftext|>


<commit_before>/*! Pushy - v0.8.4 - 2013-6-1
* Pushy is an off-canvas navigation menu for your website.
* https://github.com/christophery/pushy/
* by Christopher Yee */

$(function() {
	var pushy = $('.pushy'), //menu css class
		container = $('#container'), //container css class
		pushyClass = "pushy-left pushy-open", //menu position & menu open class
		containerClass = "container-push", //container open class
		menuBtn = $('.menu-btn, .pushy a'), //css classes to toggle the menu
		menuSpeed = 200, //jQuery fallback menu speed
		menuWidth = pushy.width() + "px"; //jQuery fallback menu width

	if(!Modernizr.csstransforms3d){
		//jQuery fallback (no 3D transforms support)
		pushy.css({left: "-" + menuWidth}); //hide menu by default
		container.css({"overflow-x": "hidden"}); //fixes IE issue

		//keep track of menu state (open/close)
		var state = true;

		//toggle menu
		menuBtn.click(function() {
			if (state) {
				pushy.animate({left: "0px"}, menuSpeed);
				container.animate({left: menuWidth}, menuSpeed);
				state = false;
			} else {
				pushy.animate({left: "-" + menuWidth}, menuSpeed);
				container.animate({left: "0px"}, menuSpeed);
				state = true;
			}
			e.preventDefault();
		});

	}else{
		//use native CSS 3D Transforms
		menuBtn.click(function(e) {
			pushy.toggleClass(pushyClass);
			container.toggleClass(containerClass);
			e.preventDefault();
		});
	}
});<commit_msg>removed preventDefault()<commit_after>/*! Pushy - v0.8.4 - 2013-6-1
* Pushy is an off-canvas navigation menu for your website.
* https://github.com/christophery/pushy/
* by Christopher Yee */

$(function() {
	var pushy = $('.pushy'), //menu css class
		container = $('#container'), //container css class
		pushyClass = "pushy-left pushy-open", //menu position & menu open class
		containerClass = "container-push", //container open class
		menuBtn = $('.menu-btn, .pushy a'), //css classes to toggle the menu
		menuSpeed = 200, //jQuery fallback menu speed
		menuWidth = pushy.width() + "px"; //jQuery fallback menu width

	if(!Modernizr.csstransforms3d){
		//jQuery fallback (no 3D transforms support)
		pushy.css({left: "-" + menuWidth}); //hide menu by default
		container.css({"overflow-x": "hidden"}); //fixes IE issue

		//keep track of menu state (open/close)
		var state = true;

		//toggle menu
		menuBtn.click(function() {
			if (state) {
				pushy.animate({left: "0px"}, menuSpeed);
				container.animate({left: menuWidth}, menuSpeed);
				state = false;
			} else {
				pushy.animate({left: "-" + menuWidth}, menuSpeed);
				container.animate({left: "0px"}, menuSpeed);
				state = true;
			}
		});

	}else{
		//use native CSS 3D Transforms
		menuBtn.click(function(e) {
			pushy.toggleClass(pushyClass);
			container.toggleClass(containerClass);
		});
	}
});<|endoftext|>


<commit_before>function Robot(x, y, dir = 0)
{
	this.x = x;		//x coordinate
	this.y = y;		//y coordinate
	this.dir = dir;	//orientation in radians

	this.lastScan = Date.now();	//time of last sense in millis

	this.senseCircle = 10 + 5;
	this.lastMove = Date.now();	//last time change direction, in millis
	this.lastX = this.x;
	this.lastY = this.y;
	this.lastDir = this.dir;
	this.moveCD = Robot.randMoveCD();

	this.particles = new Array(getParticleCount());

	for (var i = this.particles.length - 1; i >= 0; i--)
	{
		this.particles[i] = new Particle(this.x, this.y, this.dir, 1);
	}
}

Robot.size = 10;
Robot.sensorRadius = 150;
Robot.scanInterval = 2500;
Robot.stride = 1

Robot.randMoveCD = function()
{
	return 1500 + (gaussian() * 150);
}

let cos = Math.cos;
let sin = Math.sin;
let abs = Math.abs;

Robot.prototype.update = function()
{
	//Move the robot
	this.x += cos(this.dir) * Robot.stride;
	this.y += sin(this.dir) * Robot.stride;

	//Collision with a wall
	if(this.x < Robot.size || this.x+Robot.size >= canvas.width || this.y < Robot.size || this.y+Robot.size >= canvas.height)
	{
		var dx = cos(this.dir);
		var dy = sin(this.dir);
		var offset = 0;

		if(this.x < Robot.size)
		{
			dx = abs(dx);
		}else if(this.x+Robot.size >= canvas.width)
		{
			dx = -abs(dx);
			offset = Math.PI;
		}else if(this.y < Robot.size)
		{
			dy = abs(dy);
			if(dx < 0)
				offset = Math.PI;
		}else if(this.y+Robot.size >= canvas.height)
		{
			dy = -abs(dy);
			if(dx < 0)
				offset = Math.PI;
		}
		this.dir = Math.atan(dy/dx) + offset;
		this.lastMove = Date.now();
		this.moveCD = Robot.randMoveCD();
	}

	//Update robot's direction if necessary
	if(this.lastMove + this.moveCD <= Date.now())
	{
		this.updateParticles();
		this.lastX = this.x;
		this.lastY = this.y;
		this.lastDir = this.dir;

		this.dir += gaussian() * Math.PI;
		this.lastMove = Date.now();
		this.moveCD = Robot.randMoveCD();
	}

	//Update the sense circle
	if(this.senseCircle > Robot.sensorRadius)
	{
		if(Date.now() - this.lastScan >= Robot.scanInterval)
		{
			this.senseCircle %= Robot.sensorRadius;
			this.lastScan = Date.now();
		}
	}
	this.senseCircle += 1;
}

Robot.prototype.updateParticles = function()
{
	//This is how we simulate odometry....
	var dx = this.x - this.lastX;
	var dy = this.y - this.lastY;
	var dd = Math.sqrt(dx*dx + dy*dy);
	var da = this.dir - this.lastDir;

	//get noise parameters
	var strideNoise = getStrideNoise();
	var turnNoise = getTurnNoise();

	for (var i = this.particles.length - 1; i >= 0; i--)
	{
		var dist = dd + dd * gaussian() * strideNoise;
		var newDir = this.particles[i].dir + da + gaussian() * da * turnNoise
		this.particles[i].x += dist * cos(newDir);
		this.particles[i].y += dist * sin(newDir)
		this.particles[i].dir = newDir;
	}
}

Robot.prototype.draw = function(ctx)
{
	ctx.strokeStyle = 'black';
	if(Date.now() - this.lastMove < 200)
		ctx.strokeStyle = 'red';

	ctx.beginPath();

	//The robot's main circle
	ctx.arc(this.x, this.y, Robot.size, 0, Math.PI * 2, true);

	//draw a line to show Robot's orientation
	ctx.moveTo(this.x, this.y);
	ctx.lineTo(this.x + cos(this.dir) * Robot.size, this.y + sin(this.dir) * Robot.size)

	ctx.stroke();

	ctx.strokeStyle = 'rgba(0, 0, 255, '+ (1-this.senseCircle/Robot.sensorRadius) +')';
	ctx.beginPath();
	//draw Robot's sensing circle
	ctx.arc(this.x, this.y, this.senseCircle, 0, Math.PI*2, false);
	ctx.stroke();

	for (var i = this.particles.length - 1; i >= 0; i--)
	{
		var p = this.particles[i];
		p.draw(ctx);
	}
}<commit_msg>Update the particles when bound off wall<commit_after>function Robot(x, y, dir = 0)
{
	this.x = x;		//x coordinate
	this.y = y;		//y coordinate
	this.dir = dir;	//orientation in radians

	this.lastScan = Date.now();	//time of last sense in millis

	this.senseCircle = 10 + 5;
	this.lastMove = Date.now();	//last time change direction, in millis
	this.lastX = this.x;
	this.lastY = this.y;
	this.lastDir = this.dir;
	this.moveCD = Robot.randMoveCD();

	this.particles = new Array(getParticleCount());

	for (var i = this.particles.length - 1; i >= 0; i--)
	{
		this.particles[i] = new Particle(this.x, this.y, this.dir, 1);
	}
}

Robot.size = 10;
Robot.sensorRadius = 150;
Robot.scanInterval = 2500;
Robot.stride = 1

Robot.randMoveCD = function()
{
	return 1500 + (gaussian() * 150);
}

let cos = Math.cos;
let sin = Math.sin;
let abs = Math.abs;

Robot.prototype.update = function()
{
	//Move the robot
	this.x += cos(this.dir) * Robot.stride;
	this.y += sin(this.dir) * Robot.stride;

	//Collision with a wall
	if(this.x < Robot.size || this.x+Robot.size >= canvas.width || this.y < Robot.size || this.y+Robot.size >= canvas.height)
	{
		var dx = cos(this.dir);
		var dy = sin(this.dir);
		var offset = 0;

		if(this.x < Robot.size)
		{
			dx = abs(dx);
		}else if(this.x+Robot.size >= canvas.width)
		{
			dx = -abs(dx);
			offset = Math.PI;
		}else if(this.y < Robot.size)
		{
			dy = abs(dy);
			if(dx < 0)
				offset = Math.PI;
		}else if(this.y+Robot.size >= canvas.height)
		{
			dy = -abs(dy);
			if(dx < 0)
				offset = Math.PI;
		}

		this.updateParticles();
		this.lastX = this.x;
		this.lastY = this.y;
		this.lastDir = this.dir;

		this.dir = Math.atan(dy/dx) + offset;

		this.lastMove = Date.now();
		this.moveCD = Robot.randMoveCD();
	}

	//Update robot's direction if necessary
	if(this.lastMove + this.moveCD <= Date.now())
	{
		this.updateParticles();
		this.lastX = this.x;
		this.lastY = this.y;
		this.lastDir = this.dir;

		this.dir += gaussian() * Math.PI;
		this.lastMove = Date.now();
		this.moveCD = Robot.randMoveCD();
	}

	//Update the sense circle
	if(this.senseCircle > Robot.sensorRadius)
	{
		if(Date.now() - this.lastScan >= Robot.scanInterval)
		{
			this.senseCircle %= Robot.sensorRadius;
			this.lastScan = Date.now();
		}
	}
	this.senseCircle += 1;
}

Robot.prototype.updateParticles = function()
{
	//This is how we simulate odometry....
	var dx = this.x - this.lastX;
	var dy = this.y - this.lastY;
	var dd = Math.sqrt(dx*dx + dy*dy);
	var da = this.dir - this.lastDir;

	//get noise parameters
	var strideNoise = getStrideNoise();
	var turnNoise = getTurnNoise();

	for (var i = this.particles.length - 1; i >= 0; i--)
	{
		var dist = dd + dd * gaussian() * strideNoise;
		var newDir = this.particles[i].dir + da + gaussian() * da * turnNoise
		this.particles[i].x += dist * cos(newDir);
		this.particles[i].y += dist * sin(newDir)
		this.particles[i].dir = newDir;
	}
}

Robot.prototype.draw = function(ctx)
{
	ctx.strokeStyle = 'black';
	if(Date.now() - this.lastMove < 200)
		ctx.strokeStyle = 'red';

	ctx.beginPath();

	//The robot's main circle
	ctx.arc(this.x, this.y, Robot.size, 0, Math.PI * 2, true);

	//draw a line to show Robot's orientation
	ctx.moveTo(this.x, this.y);
	ctx.lineTo(this.x + cos(this.dir) * Robot.size, this.y + sin(this.dir) * Robot.size)

	ctx.stroke();

	ctx.strokeStyle = 'rgba(0, 0, 255, '+ (1-this.senseCircle/Robot.sensorRadius) +')';
	ctx.beginPath();
	//draw Robot's sensing circle
	ctx.arc(this.x, this.y, this.senseCircle, 0, Math.PI*2, false);
	ctx.stroke();

	for (var i = this.particles.length - 1; i >= 0; i--)
	{
		var p = this.particles[i];
		p.draw(ctx);
	}
}<|endoftext|>


<commit_before>/*
 Ridiculously Responsive Social Sharing Buttons
 Team: @dbox, @joshuatuscan
 Site: http://www.kurtnoble.com/labs/rrssb
 Twitter: @therealkni

        ___           ___
       /__/|         /__/\        ___
      |  |:|         \  \:\      /  /\
      |  |:|          \  \:\    /  /:/
    __|  |:|      _____\__\:\  /__/::\
   /__/\_|:|____ /__/::::::::\ \__\/\:\__
   \  \:\/:::::/ \  \:\~~\~~\/    \  \:\/\
    \  \::/~~~~   \  \:\  ~~~      \__\::/
     \  \:\        \  \:\          /__/:/
      \  \:\        \  \:\         \__\/
       \__\/         \__\/
*/

;(function(window, jQuery, undefined) {
	'use strict';

	/*
	 * Utility functions
	 */
	var setPercentBtns = function() {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			var self = jQuery(this);
			var numOfButtons = jQuery('li', self).length;
			var initBtnWidth = 100 / numOfButtons;

			// set initial width of buttons
			jQuery('li', self).css('width', initBtnWidth + '%').attr('data-initwidth',initBtnWidth);
		});
	};

	var makeExtremityBtns = function() {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			var self = jQuery(this);
			//get button width
			var containerWidth = parseFloat(jQuery(self).width());
			var buttonWidth = jQuery('li', self).not('.small').first().width();
			var smallBtnCount = jQuery('li.small', self).length;

			// enlarge buttons if they get wide enough
			if (buttonWidth > 170 && smallBtnCount < 1) {
				jQuery(self).addClass('large-format');
			} else {
				jQuery(self).removeClass('large-format');
			}

			if (containerWidth < 200) {
				jQuery(self).removeClass('small-format').addClass('tiny-format');
			} else {
				jQuery(self).removeClass('tiny-format');
			}
		});
	};

	var backUpFromSmall = function() {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			var self = jQuery(this);
			var totalBtnSze = 0, totalTxtSze = 0, upCandidate, nextBackUp;
			var smallBtnCount = jQuery('li.small', self).length;

			if (smallBtnCount === jQuery('li', self).length) {
				var btnCalc = smallBtnCount * 42;
				var containerWidth = parseFloat(jQuery(self).width());
				upCandidate = jQuery('li.small', self).first();
				nextBackUp = parseFloat(jQuery(upCandidate).attr('data-size')) + 55;

				if ((btnCalc + nextBackUp) < containerWidth) {
					jQuery(self).removeClass('small-format');
					jQuery('li.small', self).first().removeClass('small');

					sizeSmallBtns();
				}

			} else {
				jQuery('li', self).not('.small').each(function(index) {
					var txtWidth = parseFloat(jQuery(this).attr('data-size')) + 55;
					var btnWidth = parseFloat(jQuery(this).width());

					totalBtnSze = totalBtnSze + btnWidth;
					totalTxtSze = totalTxtSze + txtWidth;
				});

				var spaceLeft = totalBtnSze - totalTxtSze;
				upCandidate = jQuery('li.small', self).first();
				nextBackUp = parseFloat(jQuery(upCandidate).attr('data-size')) + 55;

				if (nextBackUp < spaceLeft) {
					jQuery(upCandidate).removeClass('small');
					sizeSmallBtns();
				}
			}
		});
	};

	var checkSize = function(init) {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			//console.log('starting check for: '+(index+1));
			var self = jQuery(this);
			var elems = jQuery('li', self).nextAll(), count = elems.length;

			// get buttons in reverse order and loop through each
			jQuery(jQuery('li', self).get().reverse()).each(function(index, count) {

				if (jQuery(this).hasClass('small') === false) {
					var txtWidth = parseFloat(jQuery(this).attr('data-size')) + 55;
					var btnWidth = parseFloat(jQuery(this).width());

					if (txtWidth > btnWidth) {
						//console.log($(self).attr('class')+' '+$(this).attr('class')+' txtWidth: '+txtWidth+ ' & btnWidth: '+btnWidth);
						var btn2small = jQuery('li', self).not('.small').last();
						jQuery(btn2small).addClass('small');
						//console.log($(btn2small).attr('class'));
						sizeSmallBtns();
					}
				}

				if (!--count) backUpFromSmall();
			});
		});

		// if first time running, put it through the magic layout
		if (init === true) {
			rrssbMagicLayout(sizeSmallBtns);
		}
	};

	var sizeSmallBtns = function() {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			var self = jQuery(this);
			var regButtonCount,
					regPercent,
					pixelsOff,
					magicWidth,
					smallBtnFraction;

			// readjust buttons for small display
			var smallBtnCount = jQuery('li.small', self).length;

			// make sure there are small buttons
			if (smallBtnCount > 0 && smallBtnCount !== jQuery('li', self).length) {
				jQuery(self).removeClass('small-format');

				//make sure small buttons are square when not all small
				jQuery('li.small', self).css('width','42px');
				pixelsOff = smallBtnCount * 42;
				regButtonCount = jQuery('li', self).not('.small').length;
				regPercent = 100 / regButtonCount;
				smallBtnFraction = pixelsOff / regButtonCount;

				if (navigator.userAgent.indexOf('Chrome') >= 0 || navigator.userAgent.indexOf('Safari') >= 0) {
					magicWidth = '-webkit-calc('+regPercent+'% - '+smallBtnFraction+'px)';
				} else if (navigator.userAgent.indexOf('Firefox') >= 0) {
					magicWidth = '-moz-calc('+regPercent+'% - '+smallBtnFraction+'px)';
				} else {
					magicWidth = 'calc('+regPercent+'% - '+smallBtnFraction+'px)';
				}
				jQuery('li', self).not('.small').css('width', magicWidth);

			} else if (smallBtnCount === jQuery('li', self).length) {
				// if all buttons are small, change back to percentage
				jQuery(self).addClass('small-format');
				setPercentBtns();
			} else {
				jQuery(self).removeClass('small-format');
				setPercentBtns();
			}
		}); //end loop

		makeExtremityBtns();
	};

	var rrssbInit = function() {
		jQuery('.rrssb-buttons').each(function(index) {
			jQuery(this).addClass('rrssb-'+(index + 1));
		});

		setPercentBtns();

		// grab initial text width of each button and add as data attr
		jQuery('.rrssb-buttons li .rrssb-text').each(function(index) {
			var txtWdth = parseFloat(jQuery(this).width());
			jQuery(this).closest('li').attr('data-size', txtWdth);
		});

		checkSize(true);
	};

	var rrssbMagicLayout = function(callback) {
		//remove small buttons before each conversion try
		jQuery('.rrssb-buttons li.small').removeClass('small');

		checkSize();

		callback();
	};

	var popupCenter = function(url, title, w, h) {
		// Fixes dual-screen position                         Most browsers      Firefox
		var dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
		var dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

		var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
		var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

		var left = ((width / 2) - (w / 2)) + dualScreenLeft;
		var top = ((height / 3) - (h / 3)) + dualScreenTop;

		var newWindow = window.open(url, title, 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);

		// Puts focus on the newWindow
		if (window.focus) {
			newWindow.focus();
		}
	};

	var waitForFinalEvent = (function () {
		var timers = {};
		return function (callback, ms, uniqueId) {
			if (!uniqueId) {
				uniqueId = "Don't call this twice without a uniqueId";
			}
			if (timers[uniqueId]) {
				clearTimeout (timers[uniqueId]);
			}
			timers[uniqueId] = setTimeout(callback, ms);
		};
	})();

	// init load
	jQuery(document).ready(function(){
		/*
		 * Event listners
		 */

		jQuery('.rrssb-buttons a.popup').on('click', function(e){
			var _this = jQuery(this);
			popupCenter(_this.attr('href'), _this.find('.rrssb-text').html(), 580, 470);
			e.preventDefault();
		});

		// resize function
		jQuery(window).resize(function () {

			rrssbMagicLayout(sizeSmallBtns);

			waitForFinalEvent(function(){
				rrssbMagicLayout(sizeSmallBtns);
			}, 200, "finished resizing");
		});

		rrssbInit();
	});

	// Make global
	window.rrssbInit = rrssbInit;

})(window, jQuery);
<commit_msg>ignore hidden list items<commit_after>/*
 Ridiculously Responsive Social Sharing Buttons
 Team: @dbox, @joshuatuscan
 Site: http://www.kurtnoble.com/labs/rrssb
 Twitter: @therealkni

        ___           ___
       /__/|         /__/\        ___
      |  |:|         \  \:\      /  /\
      |  |:|          \  \:\    /  /:/
    __|  |:|      _____\__\:\  /__/::\
   /__/\_|:|____ /__/::::::::\ \__\/\:\__
   \  \:\/:::::/ \  \:\~~\~~\/    \  \:\/\
    \  \::/~~~~   \  \:\  ~~~      \__\::/
     \  \:\        \  \:\          /__/:/
      \  \:\        \  \:\         \__\/
       \__\/         \__\/
*/

;(function(window, jQuery, undefined) {
	'use strict';

	/*
	 * Utility functions
	 */
	var setPercentBtns = function() {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			var self = jQuery(this);
			var numOfButtons = jQuery('li:visible', self).length;
			var initBtnWidth = 100 / numOfButtons;

			// set initial width of buttons
			jQuery('li', self).css('width', initBtnWidth + '%').attr('data-initwidth',initBtnWidth);
		});
	};

	var makeExtremityBtns = function() {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			var self = jQuery(this);
			//get button width
			var containerWidth = parseFloat(jQuery(self).width());
			var buttonWidth = jQuery('li', self).not('.small').first().width();
			var smallBtnCount = jQuery('li.small', self).length;

			// enlarge buttons if they get wide enough
			if (buttonWidth > 170 && smallBtnCount < 1) {
				jQuery(self).addClass('large-format');
			} else {
				jQuery(self).removeClass('large-format');
			}

			if (containerWidth < 200) {
				jQuery(self).removeClass('small-format').addClass('tiny-format');
			} else {
				jQuery(self).removeClass('tiny-format');
			}
		});
	};

	var backUpFromSmall = function() {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			var self = jQuery(this);
			var totalBtnSze = 0, totalTxtSze = 0, upCandidate, nextBackUp;
			var smallBtnCount = jQuery('li.small', self).length;

			if (smallBtnCount === jQuery('li', self).length) {
				var btnCalc = smallBtnCount * 42;
				var containerWidth = parseFloat(jQuery(self).width());
				upCandidate = jQuery('li.small', self).first();
				nextBackUp = parseFloat(jQuery(upCandidate).attr('data-size')) + 55;

				if ((btnCalc + nextBackUp) < containerWidth) {
					jQuery(self).removeClass('small-format');
					jQuery('li.small', self).first().removeClass('small');

					sizeSmallBtns();
				}

			} else {
				jQuery('li', self).not('.small').each(function(index) {
					var txtWidth = parseFloat(jQuery(this).attr('data-size')) + 55;
					var btnWidth = parseFloat(jQuery(this).width());

					totalBtnSze = totalBtnSze + btnWidth;
					totalTxtSze = totalTxtSze + txtWidth;
				});

				var spaceLeft = totalBtnSze - totalTxtSze;
				upCandidate = jQuery('li.small', self).first();
				nextBackUp = parseFloat(jQuery(upCandidate).attr('data-size')) + 55;

				if (nextBackUp < spaceLeft) {
					jQuery(upCandidate).removeClass('small');
					sizeSmallBtns();
				}
			}
		});
	};

	var checkSize = function(init) {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			//console.log('starting check for: '+(index+1));
			var self = jQuery(this);
			var elems = jQuery('li', self).nextAll(), count = elems.length;

			// get buttons in reverse order and loop through each
			jQuery(jQuery('li', self).get().reverse()).each(function(index, count) {

				if (jQuery(this).hasClass('small') === false) {
					var txtWidth = parseFloat(jQuery(this).attr('data-size')) + 55;
					var btnWidth = parseFloat(jQuery(this).width());

					if (txtWidth > btnWidth) {
						//console.log($(self).attr('class')+' '+$(this).attr('class')+' txtWidth: '+txtWidth+ ' & btnWidth: '+btnWidth);
						var btn2small = jQuery('li', self).not('.small').last();
						jQuery(btn2small).addClass('small');
						//console.log($(btn2small).attr('class'));
						sizeSmallBtns();
					}
				}

				if (!--count) backUpFromSmall();
			});
		});

		// if first time running, put it through the magic layout
		if (init === true) {
			rrssbMagicLayout(sizeSmallBtns);
		}
	};

	var sizeSmallBtns = function() {
		// loop through each instance of buttons
		jQuery('.rrssb-buttons').each(function(index) {
			var self = jQuery(this);
			var regButtonCount,
					regPercent,
					pixelsOff,
					magicWidth,
					smallBtnFraction;

			// readjust buttons for small display
			var smallBtnCount = jQuery('li.small', self).length;

			// make sure there are small buttons
			if (smallBtnCount > 0 && smallBtnCount !== jQuery('li', self).length) {
				jQuery(self).removeClass('small-format');

				//make sure small buttons are square when not all small
				jQuery('li.small', self).css('width','42px');
				pixelsOff = smallBtnCount * 42;
				regButtonCount = jQuery('li', self).not('.small').length;
				regPercent = 100 / regButtonCount;
				smallBtnFraction = pixelsOff / regButtonCount;

				if (navigator.userAgent.indexOf('Chrome') >= 0 || navigator.userAgent.indexOf('Safari') >= 0) {
					magicWidth = '-webkit-calc('+regPercent+'% - '+smallBtnFraction+'px)';
				} else if (navigator.userAgent.indexOf('Firefox') >= 0) {
					magicWidth = '-moz-calc('+regPercent+'% - '+smallBtnFraction+'px)';
				} else {
					magicWidth = 'calc('+regPercent+'% - '+smallBtnFraction+'px)';
				}
				jQuery('li', self).not('.small').css('width', magicWidth);

			} else if (smallBtnCount === jQuery('li', self).length) {
				// if all buttons are small, change back to percentage
				jQuery(self).addClass('small-format');
				setPercentBtns();
			} else {
				jQuery(self).removeClass('small-format');
				setPercentBtns();
			}
		}); //end loop

		makeExtremityBtns();
	};

	var rrssbInit = function() {
		jQuery('.rrssb-buttons').each(function(index) {
			jQuery(this).addClass('rrssb-'+(index + 1));
		});

		setPercentBtns();

		// grab initial text width of each button and add as data attr
		jQuery('.rrssb-buttons li .rrssb-text').each(function(index) {
			var txtWdth = parseFloat(jQuery(this).width());
			jQuery(this).closest('li').attr('data-size', txtWdth);
		});

		checkSize(true);
	};

	var rrssbMagicLayout = function(callback) {
		//remove small buttons before each conversion try
		jQuery('.rrssb-buttons li.small').removeClass('small');

		checkSize();

		callback();
	};

	var popupCenter = function(url, title, w, h) {
		// Fixes dual-screen position                         Most browsers      Firefox
		var dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
		var dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

		var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
		var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

		var left = ((width / 2) - (w / 2)) + dualScreenLeft;
		var top = ((height / 3) - (h / 3)) + dualScreenTop;

		var newWindow = window.open(url, title, 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);

		// Puts focus on the newWindow
		if (window.focus) {
			newWindow.focus();
		}
	};

	var waitForFinalEvent = (function () {
		var timers = {};
		return function (callback, ms, uniqueId) {
			if (!uniqueId) {
				uniqueId = "Don't call this twice without a uniqueId";
			}
			if (timers[uniqueId]) {
				clearTimeout (timers[uniqueId]);
			}
			timers[uniqueId] = setTimeout(callback, ms);
		};
	})();

	// init load
	jQuery(document).ready(function(){
		/*
		 * Event listners
		 */

		jQuery('.rrssb-buttons a.popup').on('click', function(e){
			var _this = jQuery(this);
			popupCenter(_this.attr('href'), _this.find('.rrssb-text').html(), 580, 470);
			e.preventDefault();
		});

		// resize function
		jQuery(window).resize(function () {

			rrssbMagicLayout(sizeSmallBtns);

			waitForFinalEvent(function(){
				rrssbMagicLayout(sizeSmallBtns);
			}, 200, "finished resizing");
		});

		rrssbInit();
	});

	// Make global
	window.rrssbInit = rrssbInit;

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