<commit_before>DroolsPlatformControllers.controller('assetStatusController', function ($rootScope, $scope, $http) {
    /* Select package */
    $scope.selectPackage = {
        allowClear: true
    };

    $http.get('./server/rules_package/list')
        .success(function (data) {
            $scope.packagesList = data;
        })
        .error(function (error) {
            console.log(error);
        });

    /* Input select */
    $scope.filters = {};
    $scope.assets = undefined;
    $http.get('./server/rule_status/all')
        .success(function (data) {
            $scope.statuses = data;
        })
        .error(function (error) {
            console.log(error);
        });

    $scope.filtersOptions = {
        selectOnBlur: true
    };

    $scope.search = function () {
        var filters = $scope.filters;
        var packageSelected=$scope.package;
        if(filters==undefined){
            $scope.assetStatusSelectClass="form-group has-error has-feedback";
        }
        else if(packageSelected == "" && filters.length == 0 ) {
            $scope.namePackageSelectClass="form-group has-error has-feedback";
            $scope.assetStatusSelectClass="form-group has-error has-feedback";
        }else if (filters.length == 0) {
            /* When mistake happens display the tooltip */
            $scope.assetStatusSelectClass="form-group has-error has-feedback";
            return;
        }else if (packageSelected == "") {
            /* When mistake happens display the tooltip */
            $scope.namePackageSelectClass="form-group has-error has-feedback";
            $scope.assetStatusSelectClass="form-group";
            return;
        }else{
            $scope.namePackageSelectClass="form-group";
            $scope.assetStatusSelectClass="form-group";
            //$("#popoverBtn").popover('destroy');
            $http.post('./server/rule_status/'+packageSelected, JSON.stringify(filters))
                .success(function (data) {
                    $scope.showCancelButton=true;
                    $scope.assets = data;
                    console.log(data);
                })
                .error(function (error, status) {
                    $scope.showCancelButton=true;
                    $scope.noAssetSent = true;
                    $scope.status=status;
                    console.log(error);
                });
        }
    };
    $scope.reset = function () {
        $scope.showCancelButton=false;
        $scope.package=undefined;
        $scope.filters = undefined;
        $scope.assets = undefined;
        $scope.namePackageSelectClass="form-group";
        $scope.assetStatusSelectClass="form-group";
    }

    $scope.promoteAssetsStatus = function () {
        var packageSelected=$scope.package;
        var assetsToPromote = _.where($scope.assets, {selected: true});
        var data = {assetsToPromote: assetsToPromote, assetStatuses: $scope.filters};
        $http.post('./server/rule_status/'+packageSelected+'/promote', data)
            .success(function (data) {
                $scope.assets = data;
            })
            .error(function (error) {
                console.log(error);
            });
    };

    $scope.demoteAssetsStatus = function () {
        var packageSelected=$scope.package;
        var assetsToDemote = _.where($scope.assets, {selected: true});
        var data = {assetsToDemote: assetsToDemote, assetStatuses: $scope.filters};
        $http.post('./server/rule_status/'+packageSelected+'/demote', data)
            .success(function (data) {
                $scope.assets = data;
            })
            .error(function (error) {
                console.log(error);
            });
    };

});
<commit_msg>* Temporary commit (date format trial)<commit_after>DroolsPlatformControllers.controller('runtimeAnalysisController', function ($rootScope, $scope, $document, $http, $log, $timeout, growlNotifications) {

    /** SCOPE DEFINITION **/

    $scope.allRuntimes=[];

    //___ Fetch the list
    $http.get('./server/rules_package/list')
        .success(function (data) {
            $scope.packagesList = data;
        })
        .error(function (error) {
            console.log(error);
        });

    $scope.filters={
        packageName : undefined,
        status : undefined,
        hostname : undefined,
        startDate:new Date(),
        endDate:new Date()
    };

    //___ Collapse status for each box from the "Search panel"
    $scope.collapseStatus = {
        "firstBox":false,
        "secondBox":false
    };

    //___ Popover details (when you move the mouse over the rulePackage)
    $scope.popoverDetails={
        'title':'Guvnor URL',
        'content':'Guvnor URL
192.168.1.26:8080/drools-guvnor'

    };

    //___ Session Execution Details area
    $scope.sessionExecutionDetails={
        'area':false,
        'panel':false
    };

    //___ Dates
    $scope.format = 'yyyy/MM/dd';
    $scope.dates={
        'initDate':new Date('2016/12/20'),
        'minDate':'1993-07-29',
        'maxDate':'2050-07-29',
        'myTime':new Date()
    };
    $scope.dateOptions = {
        formatYear: 'yy',
        startingDay: 1
    };

    $scope.datePickers={
        'firstCalendar':false,
        'secondCalendar':false
    };
    $scope.hstep = 1;
    $scope.mstep = 15;

    $scope.options = {
        hstep: [1, 2, 3],
        mstep: [1, 5, 10, 15, 25, 30]
    };

    $scope.ismeridian = true;

    //___ ID of the runtime selected
    $scope.selectedRuntimeID = undefined;

    //___ Tab mgmt
    $scope.selectedTab=1;

    //___ Code JSON
    $scope.code = {
        'input':"// input",
        'output':'// output'
    };

    /**********************/
    /*  DATE & TIME MGMT  */
    /**********************/
    $scope.today = function(dateGiven) {
        return new Date();
    };
    $scope.today();

    $scope.clear = function () {
        $scope.filters.startDate = new Date();
    };

    // Disable weekend selection
    $scope.disabled = function(date, mode) {
        return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
    };
/*
    $scope.toggleMin = function() {
        $scope.dates.minDate = $scope.dates.minDate ? null : new Date();
    };
    $scope.toggleMin();*/

    $scope.open = function($event, inputConcerned) {
        $event.preventDefault();
        $event.stopPropagation();
         if(inputConcerned=="startDate"){
             $scope.datePickers.firstCalendar=true;

         }else{
             $scope.datePickers.secondCalendar=true;
         }

    };

    $scope.toggleMode = function() {
        $scope.ismeridian = ! $scope.ismeridian;
    };

    $scope.update = function() {
        var d = new Date();
        d.setHours( 14 );
        d.setMinutes( 0 );
        $scope.dates.mytime = d;
    };

    $scope.changed = function () {
        console.log('Time changed to: ' + $scope.dates.myTime);
    };

    /** SESSION EXECUTION DETAILS **/

    //___ Scrolling to the next panel
    $scope.scrollToPanel = function(ruleBaseID) {
        $scope.selectedRuntimeID=ruleBaseID;
        $scope.sessionExecutionDetails.area=true;
        $timeout(function() {
            $scope.sessionExecutionDetails.panel=true;
            var someElement = angular.element(document.getElementById('detailsPanel'));
            $document.scrollToElement(someElement, 0, 1000);
        }, 3);
    };

    // Toggle to another tab
    $scope.selectedTab = 'output';
    $scope.toggleTab=function(item){
        $scope.selectedTab = item;
    }

    $scope.closeDetailsPanel = function() {
        var someElement = angular.element(document.getElementById('wrap'));
        $document.scrollToElement(someElement, 0, 1000);
        $timeout(function() {
            $scope.sessionExecutionDetails.area=false;
            $scope.sessionExecutionDetails.panel=false;
        }, 1000);
    };

    /** EVENTS ASSOCIATED WITH BUTTONS **/

    /** SEARCH **/
    //___ Method :
    //___ Retrieve filters
    //___ Then launch the http get request
    $scope.search = function () {

        var str = ''+$scope.filters.startDate;
        var suffix="(CET)";

        if(str.indexOf(suffix, str.length - suffix.length) !== -1){
            $scope.filters.startDate=''+$scope.filters.startDate.getFullYear()+'-'+$scope.filters.startDate.getMonth()+'-'+$scope.filters.startDate.getDate();
        }
        str = ''+$scope.filters.endDate;
         if(str.indexOf(suffix, str.length - suffix.length) !== -1){
            $scope.filters.endDate=''+$scope.filters.endDate.getFullYear()+'-'+$scope.filters.endDate.getMonth()+'-'+$scope.filters.endDate.getDate();
         }

        console.log($scope.filters.startDate);
        console.log($scope.filters.endDate);

        var filters = $scope.filters;
        console.log(filters);

        if ($scope.filters.packageName == null) {
            console.log("then do sthing");
            $scope.namePackageSelectClass = "form-group has-error has-feedback";

        } else {
            $scope.namePackageSelectClass = "form-group";
            $http.get('./server/runtime/filter', $scope.filters)
                .success(function (data) {
                    $scope.allRuntimes = data;
                })
                .error(function (error, status) {
                    console.log(error);
                    //____ TODO Send an appropriate message
                    growlNotifications.add('Whoops ! Error HTTP ' + status, 'danger', 2000);
                });
        }
        $scope.showCancelButton = true;

        //___ Mockup values
        $scope.allRuntimes= [{
            ruleBaseID:'0',
            runtimeURL:'http://192.168.1.26:8080/runtime-1',
            rulePackage:'loyalty',
            sessionId:'1',
            status:'INITMODE',
            startDate:'2014-04-20 1:48:23 AM',
            endDate:'2014-04-20 1:48:42 AM'
            },
            {
                ruleBaseID:'1',
                runtimeURL:'http://192.168.1.26:8080/runtime-2',
                rulePackage:'loyalty',
                sessionId:'2',
                status:'STARTED',
                startDate:'2014-04-20 1:48:23 AM',
                endDate:'2014-04-20 1:48:42 AM'
            },
            {
                ruleBaseID:'2',
                runtimeURL:'http://192.168.1.26:8080/runtime-2',
                rulePackage:'loyalty',
                sessionId:'3',
                status:'NOT_JOIGNABLE',
                startDate:'2014-04-20 1:48:23 AM',
                endDate:'2014-04-20 1:48:42 AM'
            },
            {
                ruleBaseID:'3',
                runtimeURL:'http://192.168.1.26:8080/runtime-2',
                rulePackage:'loyalty',
                sessionId:'4',
                status:'STOPPED',
                startDate:'2014-04-20 1:48:23 AM',
                endDate:'2014-04-20 1:48:42 AM'
            },
            {
                ruleBaseID:'5',
                runtimeURL:'http://192.168.1.26:8080/runtime-2',
                rulePackage:'loyalty',
                sessionId:'5',
                status:'CRASHED',
                startDate:'2014-04-20 1:48:23 AM',
                endDate:'2014-04-20 1:48:42 AM'
            },
            {
                ruleBaseID:'6',
                runtimeURL:'http://192.168.1.26:8080/runtime-2',
                rulePackage:'loyalty',
                sessionId:'6',
                status:'STOPPED',
                startDate:'2014-04-20 1:48:23 AM',
                endDate:'2014-04-20 1:48:42 AM'
            }
        ];
    };

    $scope.reset = function(){
        $scope.allRuntimes= [];
        $scope.namePackageSelectClass = "form-group";
        $scope.showCancelButton=false;
    };

});

<|endoftext|>


<commit_before>var root = require('root-path')
require(root('test/setup'))
var factories = require(root('test/setup/factories'))
var Promise = require('bluebird')
var checkAndSetMembership = Promise.promisify(require(require('root-path')('api/policies/checkAndSetMembership')))
var CommunityController = require(root('api/controllers/CommunityController'))

describe('CommunityController', () => {
  var req, res, user

  before(() => {
    user = factories.user()
    return user.save()
  })

  beforeEach(() => {
    req = factories.mock.request()
    res = factories.mock.response()
  })

  describe('.findOne', () => {
    var community

    beforeEach(() => {
      community = factories.community({beta_access_code: 'sekrit'})
      return community.save()
      .then(() => user.joinCommunity(community))
      .then(() => {
        req.params.communityId = community.id
        req.session.userId = user.id
      })
    })

    it('does not include the invitation code', () => {
      return checkAndSetMembership(req, res)
      .then(() => CommunityController.findOne(req, res))
      .then(() => {
        expect(res.ok).to.have.been.called()
        expect(res.body).to.deep.equal({
          id: community.id,
          name: community.get('name'),
          slug: community.get('slug'),
          avatar_url: null,
          banner_url: null,
          description: null,
          settings: {},
          location: null
        })
      })
    })
  })

  describe('.create', () => {
    it('works', () => {
      req.session.userId = user.id
      _.extend(req.params, {name: 'Bar', slug: 'bar'})

      return CommunityController.create(req, res)
      .then(() => Community.find('bar', {withRelated: ['users', 'memberships', 'leader']}))
      .then(community => {
        expect(community).to.exist
        expect(community.get('name')).to.equal('Bar')
        expect(community.get('slug')).to.equal('bar')
        expect(community.relations.leader.id).to.equal(user.id)
        expect(community.relations.users.first().pivot.get('role')).to.equal(Membership.MODERATOR_ROLE)
      })
    })
  })

  describe('.validate', () => {
    it('rejects non-whitelisted columns', () => {
      req.params.column = 'foo'
      CommunityController.validate(req, res)
      .then(() => {
        expect(res.badRequest).to.have.been.called()
        expect(res.body).to.equal('invalid value "foo" for parameter "column"')
      })
    })

    it('requires a value', () => {
      req.params.column = 'name'
      CommunityController.validate(req, res)
      .then(() => {
        expect(res.badRequest).to.have.been.called()
        expect(res.body).to.equal('missing required parameter "value"')
      })
    })

    it('requires a constraint', () => {
      _.extend(req.params, {column: 'name', value: 'foo', constraint: 'foo'})
      CommunityController.validate(req, res)
      .then(() => {
        expect(res.badRequest).to.have.been.called()
        expect(res.body).to.equal('invalid value "foo" for parameter "constraint"')
      })
    })

    describe('with an existing value', () => {
      var community

      before(() => {
        community = factories.community()
        return community.save()
      })

      it('fails a uniqueness check', () => {
        _.extend(req.params, {column: 'name', value: community.get('name'), constraint: 'unique'})
        return CommunityController.validate(req, res)
        .then(() => {
          expect(res.ok).to.have.been.called()
          expect(res.body).to.deep.equal({unique: false})
        })
      })

      it('passes an existence check', () => {
        _.extend(req.params, {column: 'name', value: community.get('name'), constraint: 'exists'})
        return CommunityController.validate(req, res)
        .then(() => {
          expect(res.ok).to.have.been.called()
          expect(res.body).to.deep.equal({exists: true})
        })
      })
    })
  })

  describe('.joinWithCode', () => {
    var community
    beforeEach(() => {
      community = factories.community({beta_access_code: 'foo'})
      return community.save()
    })

    it('works', () => {
      req.params.code = 'foo'
      req.login(user.id)

      return CommunityController.joinWithCode(req, res)
      .tap(() => Promise.join(
        community.load(['posts', 'posts.relatedUsers']),
        user.load('communities')
      ))
      .then(() => {
        var welcome = community.relations.posts.find(p => p.get('type') === 'welcome')
        expect(welcome).to.exist
        var relatedUser = welcome.relations.relatedUsers.first()
        expect(relatedUser).to.exist
        expect(relatedUser.id).to.equal(user.id)
        expect(user.relations.communities.map(c => c.id)).to.contain(community.id)
      })
    })
  })

  describe('.findForNetwork', () => {
    var network
    before(done => {
      network = new Network({name: 'N1', slug: 'n1'}).save()
      return network
      .then(network => {
        return Promise.join({
          c1: new Community({name: 'C1', slug: 'c1', network_id: network.get('id')}).save(),
          c2: new Community({name: 'C2', slug: 'c2', network_id: network.get('id')}).save(),
          c3: new Community({name: 'C3', slug: 'c3'}).save(),
          n1: network
        })
      })
      .then(() => done())
    })

    it('works with slug', () => {
      req.params.networkId = 'n1'
      req.login(user.id)
      return CommunityController.findForNetwork(req, res)
      .then(() => {
        expect(res.body.length).to.equal(2)
        expect(res.body[0].slug).to.equal('c1')
        expect(res.body[1].slug).to.equal('c2')
      })
    })

    it('works with paginate', () => {
      req.params.networkId = 'n1'
      req.params.paginate = true
      req.params.offset = 1
      req.params.limit = 1
      req.login(user.id)
      return CommunityController.findForNetwork(req, res)
      .then(() => {
        expect(res.body.communities_total).to.equal('2')
        expect(res.body.communities.length).to.equal(1)
        expect(res.body.communities[0].slug).to.equal('c2')
      })
    })
  })
})
<commit_msg>fix test<commit_after>var root = require('root-path')
require(root('test/setup'))
var factories = require(root('test/setup/factories'))
var Promise = require('bluebird')
var checkAndSetMembership = Promise.promisify(require(require('root-path')('api/policies/checkAndSetMembership')))
var CommunityController = require(root('api/controllers/CommunityController'))

describe('CommunityController', () => {
  var req, res, user

  before(() => {
    user = factories.user()
    return user.save()
  })

  beforeEach(() => {
    req = factories.mock.request()
    res = factories.mock.response()
  })

  describe('.findOne', () => {
    var community

    beforeEach(() => {
      community = factories.community({beta_access_code: 'sekrit'})
      return community.save()
      .then(() => user.joinCommunity(community))
      .then(() => {
        req.params.communityId = community.id
        req.session.userId = user.id
      })
    })

    it('does not include the invitation code', () => {
      return checkAndSetMembership(req, res)
      .then(() => CommunityController.findOne(req, res))
      .then(() => {
        expect(res.ok).to.have.been.called()
        expect(res.body).to.deep.equal({
          id: community.id,
          name: community.get('name'),
          slug: community.get('slug'),
          avatar_url: null,
          banner_url: null,
          description: null,
          settings: {},
          location: null
        })
      })
    })
  })

  describe('.create', () => {
    it('works', () => {
      req.session.userId = user.id
      _.extend(req.params, {name: 'Bar', slug: 'bar'})

      return CommunityController.create(req, res)
      .then(() => Community.find('bar', {withRelated: ['users', 'memberships', 'leader']}))
      .then(community => {
        expect(community).to.exist
        expect(community.get('name')).to.equal('Bar')
        expect(community.get('slug')).to.equal('bar')
        expect(community.relations.leader.id).to.equal(user.id)
        expect(community.relations.users.first().pivot.get('role')).to.equal(Membership.MODERATOR_ROLE)
      })
    })
  })

  describe('.validate', () => {
    it('rejects non-whitelisted columns', () => {
      req.params.column = 'foo'
      CommunityController.validate(req, res)
      .then(() => {
        expect(res.badRequest).to.have.been.called()
        expect(res.body).to.equal('invalid value "foo" for parameter "column"')
      })
    })

    it('requires a value', () => {
      req.params.column = 'name'
      CommunityController.validate(req, res)
      .then(() => {
        expect(res.badRequest).to.have.been.called()
        expect(res.body).to.equal('missing required parameter "value"')
      })
    })

    it('requires a constraint', () => {
      _.extend(req.params, {column: 'name', value: 'foo', constraint: 'foo'})
      CommunityController.validate(req, res)
      .then(() => {
        expect(res.badRequest).to.have.been.called()
        expect(res.body).to.equal('invalid value "foo" for parameter "constraint"')
      })
    })

    describe('with an existing value', () => {
      var community

      before(() => {
        community = factories.community()
        return community.save()
      })

      it('fails a uniqueness check', () => {
        _.extend(req.params, {column: 'name', value: community.get('name'), constraint: 'unique'})
        return CommunityController.validate(req, res)
        .then(() => {
          expect(res.ok).to.have.been.called()
          expect(res.body).to.deep.equal({unique: false})
        })
      })

      it('passes an existence check', () => {
        _.extend(req.params, {column: 'name', value: community.get('name'), constraint: 'exists'})
        return CommunityController.validate(req, res)
        .then(() => {
          expect(res.ok).to.have.been.called()
          expect(res.body).to.deep.equal({exists: true})
        })
      })
    })
  })

  describe('.joinWithCode', () => {
    var community
    beforeEach(() => {
      community = factories.community({beta_access_code: 'foo'})
      return community.save()
    })

    it('works', () => {
      req.params.code = 'foo'
      req.login(user.id)

      return CommunityController.joinWithCode(req, res)
      .tap(() => Promise.join(
        community.load(['posts', 'posts.relatedUsers']),
        user.load('communities')
      ))
      .then(() => {
        var welcome = community.relations.posts.find(p => p.get('type') === 'welcome')
        expect(welcome).to.exist
        var relatedUser = welcome.relations.relatedUsers.first()
        expect(relatedUser).to.exist
        expect(relatedUser.id).to.equal(user.id)
        expect(user.relations.communities.map(c => c.id)).to.contain(community.id)
      })
    })
  })

  describe('.findForNetwork', () => {
    var network
    before(done => {
      network = new Network({name: 'N1', slug: 'n1'}).save()
      return network
      .then(network => {
        return Promise.join({
          c1: new Community({name: 'NC1', slug: 'nc1', network_id: network.get('id')}).save(),
          c2: new Community({name: 'NC2', slug: 'nc2', network_id: network.get('id')}).save(),
          c3: new Community({name: 'NC3', slug: 'nc3'}).save(),
          n1: network
        })
      })
      .then(() => done())
    })

    it('works with slug', () => {
      req.params.networkId = 'n1'
      req.login(user.id)
      return CommunityController.findForNetwork(req, res)
      .then(() => {
        expect(res.body.length).to.equal(2)
        expect(res.body[0].slug).to.equal('nc1')
        expect(res.body[1].slug).to.equal('nc2')
      })
    })

    it('works with paginate', () => {
      req.params.networkId = 'n1'
      req.params.paginate = true
      req.params.offset = 1
      req.params.limit = 1
      req.login(user.id)
      return CommunityController.findForNetwork(req, res)
      .then(() => {
        expect(res.body.communities_total).to.equal('2')
        expect(res.body.communities.length).to.equal(1)
        expect(res.body.communities[0].slug).to.equal('nc2')
      })
    })
  })
})
<|endoftext|>


<commit_before>/* FileSaver.js
 * A saveAs() FileSaver implementation.
 * 1.1.20150716
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
 */

/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */

var saveAs = saveAs || (function(view) {
	"use strict";

			var doc;

	// IE <10 is explicitly unsupported
	if (typeof navigator !== "undefined" && /MSIE [1-8]\./.test(navigator.userAgent)) {
		return;
	} else if (typeof navigator !== "undefined" && /MSIE [9]\./.test(navigator.userAgent)) {
    // IE9 doesn't support typed arrays (which we need for this to work)
    (function() {
      try {
        var a = new Uint8Array(1);
        return; //no need
      } catch(e) { }

      function subarray(start, end) {
        return this.slice(start, end);
      }

      function set_(array, offset) {
        if (arguments.length < 2) offset = 0;
        for (var i = 0, n = array.length; i < n; ++i, ++offset)
          this[offset] = array[i] & 0xFF;
      }

      // we need typed arrays
      function TypedArray(arg1) {
        var result;
        if (typeof arg1 === "number") {
          result = new Array(arg1);
          for (var i = 0; i < arg1; ++i)
            result[i] = 0;
        } else
          result = arg1.slice(0);
        result.subarray = subarray;
        result.buffer = result;
        result.byteLength = result.length;
        result.set = set_;
        if (typeof arg1 === "object" && arg1.buffer)
          result.buffer = arg1.buffer;

        return result;
      }

      window.Uint8Array = TypedArray;
      window.Uint32Array = TypedArray;
      window.Int32Array = TypedArray;
    })();
		// IE 9 will try to use execCommand to save the file
		return function (data, filename) {
      var w = window.open();
      doc = w.document;

      doc.open(mimetype, 'replace');
      doc.charset = "utf-8";
      doc.write(data);
      doc.close();
      doc.execCommand("SaveAs", null, filename);
    };
	}

			doc = view.document
		  // only get URL when necessary in case Blob.js hasn't overridden it yet
		var get_URL = function() {
			return view.URL || view.webkitURL || view;
		}
		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
		, can_use_save_link = "download" in save_link
		, click = function(node) {
			var event = new MouseEvent("click");
			node.dispatchEvent(event);
		}
		, webkit_req_fs = view.webkitRequestFileSystem
		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
		, throw_outside = function(ex) {
			(view.setImmediate || view.setTimeout)(function() {
				throw ex;
			}, 0);
		}
		, force_saveable_type = "application/octet-stream"
		, fs_min_size = 0
		// See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and
		// https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047
		// for the reasoning behind the timeout and revocation flow
		, arbitrary_revoke_timeout = 500 // in ms
		, revoke = function(file) {
			var revoker = function() {
				if (typeof file === "string") { // file is an object URL
					get_URL().revokeObjectURL(file);
				} else { // file is a File
					file.remove();
				}
			};
			if (view.chrome) {
				revoker();
			} else {
				setTimeout(revoker, arbitrary_revoke_timeout);
			}
		}
		, dispatch = function(filesaver, event_types, event) {
			event_types = [].concat(event_types);
			var i = event_types.length;
			while (i--) {
				var listener = filesaver["on" + event_types[i]];
				if (typeof listener === "function") {
					try {
						listener.call(filesaver, event || filesaver);
					} catch (ex) {
						throw_outside(ex);
					}
				}
			}
		}
		, auto_bom = function(blob) {
			// prepend BOM for UTF-8 XML and text/* types (including HTML)
			if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
				return new Blob(["\ufeff", blob], {type: blob.type});
			}
			return blob;
		}
		, FileSaver = function(blob, name, no_auto_bom) {
			if (!no_auto_bom) {
				blob = auto_bom(blob);
			}
			// First try a.download, then web filesystem, then object URLs
			var
				  filesaver = this
				, type = blob.type
				, blob_changed = false
				, object_url
				, target_view
				, dispatch_all = function() {
					dispatch(filesaver, "writestart progress write writeend".split(" "));
				}
				// on any filesys errors revert to saving with object URLs
				, fs_error = function() {
					// don't create more object URLs than needed
					if (blob_changed || !object_url) {
						object_url = get_URL().createObjectURL(blob);
					}
					if (target_view) {
						target_view.location.href = object_url;
					} else {
						var new_tab = view.open(object_url, "_blank");
						if (new_tab == undefined && typeof safari !== "undefined") {
							//Apple do not allow window.open, see http://bit.ly/1kZffRI
							view.location.href = object_url
						}
					}
					filesaver.readyState = filesaver.DONE;
					dispatch_all();
					revoke(object_url);
				}
				, abortable = function(func) {
					return function() {
						if (filesaver.readyState !== filesaver.DONE) {
							return func.apply(this, arguments);
						}
					};
				}
				, create_if_not_found = {create: true, exclusive: false}
				, slice
			;
			filesaver.readyState = filesaver.INIT;
			if (!name) {
				name = "download";
			}
			if (can_use_save_link) {
				object_url = get_URL().createObjectURL(blob);
				save_link.href = object_url;
				save_link.download = name;
				setTimeout(function() {
					click(save_link);
					dispatch_all();
					revoke(object_url);
					filesaver.readyState = filesaver.DONE;
				});
				return;
			}
			// Object and web filesystem URLs have a problem saving in Google Chrome when
			// viewed in a tab, so I force save with application/octet-stream
			// http://code.google.com/p/chromium/issues/detail?id=91158
			// Update: Google errantly closed 91158, I submitted it again:
			// https://code.google.com/p/chromium/issues/detail?id=389642
			if (view.chrome && type && type !== force_saveable_type) {
				slice = blob.slice || blob.webkitSlice;
				blob = slice.call(blob, 0, blob.size, force_saveable_type);
				blob_changed = true;
			}
			// Since I can't be sure that the guessed media type will trigger a download
			// in WebKit, I append .download to the filename.
			// https://bugs.webkit.org/show_bug.cgi?id=65440
			if (webkit_req_fs && name !== "download") {
				name += ".download";
			}
			if (type === force_saveable_type || webkit_req_fs) {
				target_view = view;
			}
			if (!req_fs) {
				fs_error();
				return;
			}
			fs_min_size += blob.size;
			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
					var save = function() {
						dir.getFile(name, create_if_not_found, abortable(function(file) {
							file.createWriter(abortable(function(writer) {
								writer.onwriteend = function(event) {
									target_view.location.href = file.toURL();
									filesaver.readyState = filesaver.DONE;
									dispatch(filesaver, "writeend", event);
									revoke(file);
								};
								writer.onerror = function() {
									var error = writer.error;
									if (error.code !== error.ABORT_ERR) {
										fs_error();
									}
								};
								"writestart progress write abort".split(" ").forEach(function(event) {
									writer["on" + event] = filesaver["on" + event];
								});
								writer.write(blob);
								filesaver.abort = function() {
									writer.abort();
									filesaver.readyState = filesaver.DONE;
								};
								filesaver.readyState = filesaver.WRITING;
							}), fs_error);
						}), fs_error);
					};
					dir.getFile(name, {create: false}, abortable(function(file) {
						// delete file if it already exists
						file.remove();
						save();
					}), abortable(function(ex) {
						if (ex.code === ex.NOT_FOUND_ERR) {
							save();
						} else {
							fs_error();
						}
					}));
				}), fs_error);
			}), fs_error);
		}
		, FS_proto = FileSaver.prototype
		, saveAs = function(blob, name, no_auto_bom) {
			return new FileSaver(blob, name, no_auto_bom);
		}
	;
	// IE 10+ (native saveAs)
	if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
		return function(blob, name, no_auto_bom) {
			if (!no_auto_bom) {
				blob = auto_bom(blob);
			}
			return navigator.msSaveOrOpenBlob(blob, name || "download");
		};
	}

	FS_proto.abort = function() {
		var filesaver = this;
		filesaver.readyState = filesaver.DONE;
		dispatch(filesaver, "abort");
	};
	FS_proto.readyState = FS_proto.INIT = 0;
	FS_proto.WRITING = 1;
	FS_proto.DONE = 2;

	FS_proto.error =
	FS_proto.onwritestart =
	FS_proto.onprogress =
	FS_proto.onwrite =
	FS_proto.onabort =
	FS_proto.onerror =
	FS_proto.onwriteend =
		null;

	return saveAs;
}(
	   typeof self !== "undefined" && self
	|| typeof window !== "undefined" && window
	|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window

if (typeof module !== "undefined" && module.exports) {
  module.exports.saveAs = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) {
  define([], function() {
    return saveAs;
  });
}
<commit_msg>added blob.js to filesaver<commit_after>/* Blob.js
 * A Blob implementation.
 * 2014-07-24
 *
 * By Eli Grey, http://eligrey.com
 * By Devin Samarin, https://github.com/dsamarin
 * License: X11/MIT
 *   See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
 */

/*global self, unescape */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
 plusplus: true */

/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */

(function (view) {
  "use strict";

  view.URL = view.URL || view.webkitURL;

  if (view.Blob && view.URL) {
    try {
      new Blob;
      return;
    } catch (e) {}
  }

  // Internally we use a BlobBuilder implementation to base Blob off of
  // in order to support older browsers that only have BlobBuilder
  var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
        var
            get_class = function(object) {
              return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
            }
            , FakeBlobBuilder = function BlobBuilder() {
              this.data = [];
            }
            , FakeBlob = function Blob(data, type, encoding) {
              this.data = data;
              this.size = data.length;
              this.type = type;
              this.encoding = encoding;
            }
            , FBB_proto = FakeBlobBuilder.prototype
            , FB_proto = FakeBlob.prototype
            , FileReaderSync = view.FileReaderSync
            , FileException = function(type) {
              this.code = this[this.name = type];
            }
            , file_ex_codes = (
                "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
                + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
            ).split(" ")
            , file_ex_code = file_ex_codes.length
            , real_URL = view.URL || view.webkitURL || view
            , real_create_object_URL = real_URL.createObjectURL
            , real_revoke_object_URL = real_URL.revokeObjectURL
            , URL = real_URL
            , btoa = view.btoa
            , atob = view.atob

            , ArrayBuffer = view.ArrayBuffer
            , Uint8Array = view.Uint8Array

            , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
            ;
        FakeBlob.fake = FB_proto.fake = true;
        while (file_ex_code--) {
          FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
        }
        // Polyfill URL
        if (!real_URL.createObjectURL) {
          URL = view.URL = function(uri) {
            var
                uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
                , uri_origin
                ;
            uri_info.href = uri;
            if (!("origin" in uri_info)) {
              if (uri_info.protocol.toLowerCase() === "data:") {
                uri_info.origin = null;
              } else {
                uri_origin = uri.match(origin);
                uri_info.origin = uri_origin && uri_origin[1];
              }
            }
            return uri_info;
          };
        }
        URL.createObjectURL = function(blob) {
          var
              type = blob.type
              , data_URI_header
              ;
          if (type === null) {
            type = "application/octet-stream";
          }
          if (blob instanceof FakeBlob) {
            data_URI_header = "data:" + type;
            if (blob.encoding === "base64") {
              return data_URI_header + ";base64," + blob.data;
            } else if (blob.encoding === "URI") {
              return data_URI_header + "," + decodeURIComponent(blob.data);
            } if (btoa) {
              return data_URI_header + ";base64," + btoa(blob.data);
            } else {
              return data_URI_header + "," + encodeURIComponent(blob.data);
            }
          } else if (real_create_object_URL) {
            return real_create_object_URL.call(real_URL, blob);
          }
        };
        URL.revokeObjectURL = function(object_URL) {
          if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
            real_revoke_object_URL.call(real_URL, object_URL);
          }
        };
        FBB_proto.append = function(data/*, endings*/) {
          var bb = this.data;
          // decode data to a binary string
          if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
            var
                str = ""
                , buf = new Uint8Array(data)
                , i = 0
                , buf_len = buf.length
                ;
            for (; i < buf_len; i++) {
              str += String.fromCharCode(buf[i]);
            }
            bb.push(str);
          } else if (get_class(data) === "Blob" || get_class(data) === "File") {
            if (FileReaderSync) {
              var fr = new FileReaderSync;
              bb.push(fr.readAsBinaryString(data));
            } else {
              // async FileReader won't work as BlobBuilder is sync
              throw new FileException("NOT_READABLE_ERR");
            }
          } else if (data instanceof FakeBlob) {
            if (data.encoding === "base64" && atob) {
              bb.push(atob(data.data));
            } else if (data.encoding === "URI") {
              bb.push(decodeURIComponent(data.data));
            } else if (data.encoding === "raw") {
              bb.push(data.data);
            }
          } else {
            if (typeof data !== "string") {
              data += ""; // convert unsupported types to strings
            }
            // decode UTF-16 to binary string
            bb.push(unescape(encodeURIComponent(data)));
          }
        };
        FBB_proto.getBlob = function(type) {
          if (!arguments.length) {
            type = null;
          }
          return new FakeBlob(this.data.join(""), type, "raw");
        };
        FBB_proto.toString = function() {
          return "[object BlobBuilder]";
        };
        FB_proto.slice = function(start, end, type) {
          var args = arguments.length;
          if (args < 3) {
            type = null;
          }
          return new FakeBlob(
              this.data.slice(start, args > 1 ? end : this.data.length)
              , type
              , this.encoding
          );
        };
        FB_proto.toString = function() {
          return "[object Blob]";
        };
        FB_proto.close = function() {
          this.size = 0;
          delete this.data;
        };
        return FakeBlobBuilder;
      }(view));

  view.Blob = function(blobParts, options) {
    var type = options ? (options.type || "") : "";
    var builder = new BlobBuilder();
    if (blobParts) {
      for (var i = 0, len = blobParts.length; i < len; i++) {
        if (Uint8Array && blobParts[i] instanceof Uint8Array) {
          builder.append(blobParts[i].buffer);
        }
        else {
          builder.append(blobParts[i]);
        }
      }
    }
    var blob = builder.getBlob(type);
    if (!blob.slice && blob.webkitSlice) {
      blob.slice = blob.webkitSlice;
    }
    return blob;
  };

  var getPrototypeOf = Object.getPrototypeOf || function(object) {
        return object.__proto__;
      };
  view.Blob.prototype = getPrototypeOf(new view.Blob());
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));

/* FileSaver.js
 * A saveAs() FileSaver implementation.
 * 1.1.20150716
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
 */

/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */

var saveAs = saveAs || (function(view) {
	"use strict";

			var doc;

	// IE <10 is explicitly unsupported
	if (typeof navigator !== "undefined" && /MSIE [1-8]\./.test(navigator.userAgent)) {
		return;
	} else if (typeof navigator !== "undefined" && /MSIE [9]\./.test(navigator.userAgent)) {
    // IE9 doesn't support typed arrays (which we need for this to work)
    (function() {
      try {
        var a = new Uint8Array(1);
        return; //no need
      } catch(e) { }

      function subarray(start, end) {
        return this.slice(start, end);
      }

      function set_(array, offset) {
        if (arguments.length < 2) offset = 0;
        for (var i = 0, n = array.length; i < n; ++i, ++offset)
          this[offset] = array[i] & 0xFF;
      }

      // we need typed arrays
      function TypedArray(arg1) {
        var result;
        if (typeof arg1 === "number") {
          result = new Array(arg1);
          for (var i = 0; i < arg1; ++i)
            result[i] = 0;
        } else
          result = arg1.slice(0);
        result.subarray = subarray;
        result.buffer = result;
        result.byteLength = result.length;
        result.set = set_;
        if (typeof arg1 === "object" && arg1.buffer)
          result.buffer = arg1.buffer;

        return result;
      }

      window.Uint8Array = TypedArray;
      window.Uint32Array = TypedArray;
      window.Int32Array = TypedArray;
    })();
		// IE 9 will try to use execCommand to save the file
		return function (data, filename) {
      var w = window.open();
      doc = w.document;

      doc.open(mimetype, 'replace');
      doc.charset = "utf-8";
      doc.write(data);
      doc.close();
      doc.execCommand("SaveAs", null, filename);
    };
	}

			doc = view.document
		  // only get URL when necessary in case Blob.js hasn't overridden it yet
		var get_URL = function() {
			return view.URL || view.webkitURL || view;
		}
		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
		, can_use_save_link = "download" in save_link
		, click = function(node) {
			var event = new MouseEvent("click");
			node.dispatchEvent(event);
		}
		, webkit_req_fs = view.webkitRequestFileSystem
		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
		, throw_outside = function(ex) {
			(view.setImmediate || view.setTimeout)(function() {
				throw ex;
			}, 0);
		}
		, force_saveable_type = "application/octet-stream"
		, fs_min_size = 0
		// See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and
		// https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047
		// for the reasoning behind the timeout and revocation flow
		, arbitrary_revoke_timeout = 500 // in ms
		, revoke = function(file) {
			var revoker = function() {
				if (typeof file === "string") { // file is an object URL
					get_URL().revokeObjectURL(file);
				} else { // file is a File
					file.remove();
				}
			};
			if (view.chrome) {
				revoker();
			} else {
				setTimeout(revoker, arbitrary_revoke_timeout);
			}
		}
		, dispatch = function(filesaver, event_types, event) {
			event_types = [].concat(event_types);
			var i = event_types.length;
			while (i--) {
				var listener = filesaver["on" + event_types[i]];
				if (typeof listener === "function") {
					try {
						listener.call(filesaver, event || filesaver);
					} catch (ex) {
						throw_outside(ex);
					}
				}
			}
		}
		, auto_bom = function(blob) {
			// prepend BOM for UTF-8 XML and text/* types (including HTML)
			if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
				return new Blob(["\ufeff", blob], {type: blob.type});
			}
			return blob;
		}
		, FileSaver = function(blob, name, no_auto_bom) {
			if (!no_auto_bom) {
				blob = auto_bom(blob);
			}
			// First try a.download, then web filesystem, then object URLs
			var
				  filesaver = this
				, type = blob.type
				, blob_changed = false
				, object_url
				, target_view
				, dispatch_all = function() {
					dispatch(filesaver, "writestart progress write writeend".split(" "));
				}
				// on any filesys errors revert to saving with object URLs
				, fs_error = function() {
					// don't create more object URLs than needed
					if (blob_changed || !object_url) {
						object_url = get_URL().createObjectURL(blob);
					}
					if (target_view) {
						target_view.location.href = object_url;
					} else {
						var new_tab = view.open(object_url, "_blank");
						if (new_tab == undefined && typeof safari !== "undefined") {
							//Apple do not allow window.open, see http://bit.ly/1kZffRI
							view.location.href = object_url
						}
					}
					filesaver.readyState = filesaver.DONE;
					dispatch_all();
					revoke(object_url);
				}
				, abortable = function(func) {
					return function() {
						if (filesaver.readyState !== filesaver.DONE) {
							return func.apply(this, arguments);
						}
					};
				}
				, create_if_not_found = {create: true, exclusive: false}
				, slice
			;
			filesaver.readyState = filesaver.INIT;
			if (!name) {
				name = "download";
			}
			if (can_use_save_link) {
				object_url = get_URL().createObjectURL(blob);
				save_link.href = object_url;
				save_link.download = name;
				setTimeout(function() {
					click(save_link);
					dispatch_all();
					revoke(object_url);
					filesaver.readyState = filesaver.DONE;
				});
				return;
			}
			// Object and web filesystem URLs have a problem saving in Google Chrome when
			// viewed in a tab, so I force save with application/octet-stream
			// http://code.google.com/p/chromium/issues/detail?id=91158
			// Update: Google errantly closed 91158, I submitted it again:
			// https://code.google.com/p/chromium/issues/detail?id=389642
			if (view.chrome && type && type !== force_saveable_type) {
				slice = blob.slice || blob.webkitSlice;
				blob = slice.call(blob, 0, blob.size, force_saveable_type);
				blob_changed = true;
			}
			// Since I can't be sure that the guessed media type will trigger a download
			// in WebKit, I append .download to the filename.
			// https://bugs.webkit.org/show_bug.cgi?id=65440
			if (webkit_req_fs && name !== "download") {
				name += ".download";
			}
			if (type === force_saveable_type || webkit_req_fs) {
				target_view = view;
			}
			if (!req_fs) {
				fs_error();
				return;
			}
			fs_min_size += blob.size;
			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
					var save = function() {
						dir.getFile(name, create_if_not_found, abortable(function(file) {
							file.createWriter(abortable(function(writer) {
								writer.onwriteend = function(event) {
									target_view.location.href = file.toURL();
									filesaver.readyState = filesaver.DONE;
									dispatch(filesaver, "writeend", event);
									revoke(file);
								};
								writer.onerror = function() {
									var error = writer.error;
									if (error.code !== error.ABORT_ERR) {
										fs_error();
									}
								};
								"writestart progress write abort".split(" ").forEach(function(event) {
									writer["on" + event] = filesaver["on" + event];
								});
								writer.write(blob);
								filesaver.abort = function() {
									writer.abort();
									filesaver.readyState = filesaver.DONE;
								};
								filesaver.readyState = filesaver.WRITING;
							}), fs_error);
						}), fs_error);
					};
					dir.getFile(name, {create: false}, abortable(function(file) {
						// delete file if it already exists
						file.remove();
						save();
					}), abortable(function(ex) {
						if (ex.code === ex.NOT_FOUND_ERR) {
							save();
						} else {
							fs_error();
						}
					}));
				}), fs_error);
			}), fs_error);
		}
		, FS_proto = FileSaver.prototype
		, saveAs = function(blob, name, no_auto_bom) {
			return new FileSaver(blob, name, no_auto_bom);
		}
	;
	// IE 10+ (native saveAs)
	if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
		return function(blob, name, no_auto_bom) {
			if (!no_auto_bom) {
				blob = auto_bom(blob);
			}
			return navigator.msSaveOrOpenBlob(blob, name || "download");
		};
	}

	FS_proto.abort = function() {
		var filesaver = this;
		filesaver.readyState = filesaver.DONE;
		dispatch(filesaver, "abort");
	};
	FS_proto.readyState = FS_proto.INIT = 0;
	FS_proto.WRITING = 1;
	FS_proto.DONE = 2;

	FS_proto.error =
	FS_proto.onwritestart =
	FS_proto.onprogress =
	FS_proto.onwrite =
	FS_proto.onabort =
	FS_proto.onerror =
	FS_proto.onwriteend =
		null;

	return saveAs;
}(
	   typeof self !== "undefined" && self
	|| typeof window !== "undefined" && window
	|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window

if (typeof module !== "undefined" && module.exports) {
  module.exports.saveAs = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) {
  define([], function() {
    return saveAs;
  });
}
<|endoftext|>


<commit_before>/* FileSaver.js
 * A saveAs() FileSaver implementation.
 * 2013-12-27
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See LICENSE.md
 */

/*global self */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
  plusplus: true */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */

var saveAs = saveAs
  // IE 10+ (native saveAs)
  || (navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
  // Everyone else
  || (function(view) {
	"use strict";
	// IE <10 is explicitly unsupported
	if (/MSIE [1-9]\./.test(navigator.userAgent)) {
		return;
	}
	var
		  doc = view.document
		  // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
		, get_URL = function() {
			return view.URL || view.webkitURL || view;
		}
		, URL = view.URL || view.webkitURL || view
		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
		, can_use_save_link =  !view.externalHost && "download" in save_link
		, click = function(node) {
			var event = doc.createEvent("MouseEvents");
			event.initMouseEvent(
				"click", true, false, view, 0, 0, 0, 0, 0
				, false, false, false, false, 0, null
			);
			node.dispatchEvent(event);
		}
		, webkit_req_fs = view.webkitRequestFileSystem
		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
		, throw_outside = function (ex) {
			(view.setImmediate || view.setTimeout)(function() {
				throw ex;
			}, 0);
		}
		, force_saveable_type = "application/octet-stream"
		, fs_min_size = 0
		, deletion_queue = []
		, process_deletion_queue = function() {
			var i = deletion_queue.length;
			while (i--) {
				var file = deletion_queue[i];
				if (typeof file === "string") { // file is an object URL
					URL.revokeObjectURL(file);
				} else { // file is a File
					file.remove();
				}
			}
			deletion_queue.length = 0; // clear queue
		}
		, dispatch = function(filesaver, event_types, event) {
			event_types = [].concat(event_types);
			var i = event_types.length;
			while (i--) {
				var listener = filesaver["on" + event_types[i]];
				if (typeof listener === "function") {
					try {
						listener.call(filesaver, event || filesaver);
					} catch (ex) {
						throw_outside(ex);
					}
				}
			}
		}
		, FileSaver = function(blob, name) {
			// First try a.download, then web filesystem, then object URLs
			var
				  filesaver = this
				, type = blob.type
				, blob_changed = false
				, object_url
				, target_view
				, get_object_url = function() {
					var object_url = get_URL().createObjectURL(blob);
					deletion_queue.push(object_url);
					return object_url;
				}
				, dispatch_all = function() {
					dispatch(filesaver, "writestart progress write writeend".split(" "));
				}
				// on any filesys errors revert to saving with object URLs
				, fs_error = function() {
					// don't create more object URLs than needed
					if (blob_changed || !object_url) {
						object_url = get_object_url(blob);
					}
					if (target_view) {
						target_view.location.href = object_url;
					} else {
                        window.open(object_url, "_blank");
                    }
					filesaver.readyState = filesaver.DONE;
					dispatch_all();
				}
				, abortable = function(func) {
					return function() {
						if (filesaver.readyState !== filesaver.DONE) {
							return func.apply(this, arguments);
						}
					};
				}
				, create_if_not_found = {create: true, exclusive: false}
				, slice
			;
			filesaver.readyState = filesaver.INIT;
			if (!name) {
				name = "download";
			}
			if (can_use_save_link) {
				object_url = get_object_url(blob);
				// FF for Android has a nasty garbage collection mechanism
				// that turns all objects that are not pure javascript into 'deadObject'
				// this means `doc` and `save_link` are unusable and need to be recreated
				// `view` is usable though:
				doc = view.document;
				save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
				save_link.href = object_url;
				save_link.download = name;
				var event = doc.createEvent("MouseEvents");
				event.initMouseEvent(
					"click", true, false, view, 0, 0, 0, 0, 0
					, false, false, false, false, 0, null
				);
				save_link.dispatchEvent(event);
				filesaver.readyState = filesaver.DONE;
				dispatch_all();
				return;
			}
			// Object and web filesystem URLs have a problem saving in Google Chrome when
			// viewed in a tab, so I force save with application/octet-stream
			// http://code.google.com/p/chromium/issues/detail?id=91158
			if (view.chrome && type && type !== force_saveable_type) {
				slice = blob.slice || blob.webkitSlice;
				blob = slice.call(blob, 0, blob.size, force_saveable_type);
				blob_changed = true;
			}
			// Since I can't be sure that the guessed media type will trigger a download
			// in WebKit, I append .download to the filename.
			// https://bugs.webkit.org/show_bug.cgi?id=65440
			if (webkit_req_fs && name !== "download") {
				name += ".download";
			}
			if (type === force_saveable_type || webkit_req_fs) {
				target_view = view;
			}
			if (!req_fs) {
				fs_error();
				return;
			}
			fs_min_size += blob.size;
			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
					var save = function() {
						dir.getFile(name, create_if_not_found, abortable(function(file) {
							file.createWriter(abortable(function(writer) {
								writer.onwriteend = function(event) {
									target_view.location.href = file.toURL();
									deletion_queue.push(file);
									filesaver.readyState = filesaver.DONE;
									dispatch(filesaver, "writeend", event);
								};
								writer.onerror = function() {
									var error = writer.error;
									if (error.code !== error.ABORT_ERR) {
										fs_error();
									}
								};
								"writestart progress write abort".split(" ").forEach(function(event) {
									writer["on" + event] = filesaver["on" + event];
								});
								writer.write(blob);
								filesaver.abort = function() {
									writer.abort();
									filesaver.readyState = filesaver.DONE;
								};
								filesaver.readyState = filesaver.WRITING;
							}), fs_error);
						}), fs_error);
					};
					dir.getFile(name, {create: false}, abortable(function(file) {
						// delete file if it already exists
						file.remove();
						save();
					}), abortable(function(ex) {
						if (ex.code === ex.NOT_FOUND_ERR) {
							save();
						} else {
							fs_error();
						}
					}));
				}), fs_error);
			}), fs_error);
		}
		, FS_proto = FileSaver.prototype
		, saveAs = function(blob, name) {
			return new FileSaver(blob, name);
		}
	;
	FS_proto.abort = function() {
		var filesaver = this;
		filesaver.readyState = filesaver.DONE;
		dispatch(filesaver, "abort");
	};
	FS_proto.readyState = FS_proto.INIT = 0;
	FS_proto.WRITING = 1;
	FS_proto.DONE = 2;

	FS_proto.error =
	FS_proto.onwritestart =
	FS_proto.onprogress =
	FS_proto.onwrite =
	FS_proto.onabort =
	FS_proto.onerror =
	FS_proto.onwriteend =
		null;

	view.addEventListener("unload", process_deletion_queue, false);
	return saveAs;
}(
	   typeof self !== "undefined" && self
	|| typeof window !== "undefined" && window
	|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window

if (typeof module !== "undefined") module.exports = saveAs;
<commit_msg>Update release date<commit_after>/* FileSaver.js
 * A saveAs() FileSaver implementation.
 * 2014-01-24
 *
 * By Eli Grey, http://eligrey.com
 * License: X11/MIT
 *   See LICENSE.md
 */

/*global self */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
  plusplus: true */

/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */

var saveAs = saveAs
  // IE 10+ (native saveAs)
  || (navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
  // Everyone else
  || (function(view) {
	"use strict";
	// IE <10 is explicitly unsupported
	if (/MSIE [1-9]\./.test(navigator.userAgent)) {
		return;
	}
	var
		  doc = view.document
		  // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
		, get_URL = function() {
			return view.URL || view.webkitURL || view;
		}
		, URL = view.URL || view.webkitURL || view
		, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
		, can_use_save_link =  !view.externalHost && "download" in save_link
		, click = function(node) {
			var event = doc.createEvent("MouseEvents");
			event.initMouseEvent(
				"click", true, false, view, 0, 0, 0, 0, 0
				, false, false, false, false, 0, null
			);
			node.dispatchEvent(event);
		}
		, webkit_req_fs = view.webkitRequestFileSystem
		, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
		, throw_outside = function (ex) {
			(view.setImmediate || view.setTimeout)(function() {
				throw ex;
			}, 0);
		}
		, force_saveable_type = "application/octet-stream"
		, fs_min_size = 0
		, deletion_queue = []
		, process_deletion_queue = function() {
			var i = deletion_queue.length;
			while (i--) {
				var file = deletion_queue[i];
				if (typeof file === "string") { // file is an object URL
					URL.revokeObjectURL(file);
				} else { // file is a File
					file.remove();
				}
			}
			deletion_queue.length = 0; // clear queue
		}
		, dispatch = function(filesaver, event_types, event) {
			event_types = [].concat(event_types);
			var i = event_types.length;
			while (i--) {
				var listener = filesaver["on" + event_types[i]];
				if (typeof listener === "function") {
					try {
						listener.call(filesaver, event || filesaver);
					} catch (ex) {
						throw_outside(ex);
					}
				}
			}
		}
		, FileSaver = function(blob, name) {
			// First try a.download, then web filesystem, then object URLs
			var
				  filesaver = this
				, type = blob.type
				, blob_changed = false
				, object_url
				, target_view
				, get_object_url = function() {
					var object_url = get_URL().createObjectURL(blob);
					deletion_queue.push(object_url);
					return object_url;
				}
				, dispatch_all = function() {
					dispatch(filesaver, "writestart progress write writeend".split(" "));
				}
				// on any filesys errors revert to saving with object URLs
				, fs_error = function() {
					// don't create more object URLs than needed
					if (blob_changed || !object_url) {
						object_url = get_object_url(blob);
					}
					if (target_view) {
						target_view.location.href = object_url;
					} else {
                        window.open(object_url, "_blank");
                    }
					filesaver.readyState = filesaver.DONE;
					dispatch_all();
				}
				, abortable = function(func) {
					return function() {
						if (filesaver.readyState !== filesaver.DONE) {
							return func.apply(this, arguments);
						}
					};
				}
				, create_if_not_found = {create: true, exclusive: false}
				, slice
			;
			filesaver.readyState = filesaver.INIT;
			if (!name) {
				name = "download";
			}
			if (can_use_save_link) {
				object_url = get_object_url(blob);
				// FF for Android has a nasty garbage collection mechanism
				// that turns all objects that are not pure javascript into 'deadObject'
				// this means `doc` and `save_link` are unusable and need to be recreated
				// `view` is usable though:
				doc = view.document;
				save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
				save_link.href = object_url;
				save_link.download = name;
				var event = doc.createEvent("MouseEvents");
				event.initMouseEvent(
					"click", true, false, view, 0, 0, 0, 0, 0
					, false, false, false, false, 0, null
				);
				save_link.dispatchEvent(event);
				filesaver.readyState = filesaver.DONE;
				dispatch_all();
				return;
			}
			// Object and web filesystem URLs have a problem saving in Google Chrome when
			// viewed in a tab, so I force save with application/octet-stream
			// http://code.google.com/p/chromium/issues/detail?id=91158
			if (view.chrome && type && type !== force_saveable_type) {
				slice = blob.slice || blob.webkitSlice;
				blob = slice.call(blob, 0, blob.size, force_saveable_type);
				blob_changed = true;
			}
			// Since I can't be sure that the guessed media type will trigger a download
			// in WebKit, I append .download to the filename.
			// https://bugs.webkit.org/show_bug.cgi?id=65440
			if (webkit_req_fs && name !== "download") {
				name += ".download";
			}
			if (type === force_saveable_type || webkit_req_fs) {
				target_view = view;
			}
			if (!req_fs) {
				fs_error();
				return;
			}
			fs_min_size += blob.size;
			req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
				fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
					var save = function() {
						dir.getFile(name, create_if_not_found, abortable(function(file) {
							file.createWriter(abortable(function(writer) {
								writer.onwriteend = function(event) {
									target_view.location.href = file.toURL();
									deletion_queue.push(file);
									filesaver.readyState = filesaver.DONE;
									dispatch(filesaver, "writeend", event);
								};
								writer.onerror = function() {
									var error = writer.error;
									if (error.code !== error.ABORT_ERR) {
										fs_error();
									}
								};
								"writestart progress write abort".split(" ").forEach(function(event) {
									writer["on" + event] = filesaver["on" + event];
								});
								writer.write(blob);
								filesaver.abort = function() {
									writer.abort();
									filesaver.readyState = filesaver.DONE;
								};
								filesaver.readyState = filesaver.WRITING;
							}), fs_error);
						}), fs_error);
					};
					dir.getFile(name, {create: false}, abortable(function(file) {
						// delete file if it already exists
						file.remove();
						save();
					}), abortable(function(ex) {
						if (ex.code === ex.NOT_FOUND_ERR) {
							save();
						} else {
							fs_error();
						}
					}));
				}), fs_error);
			}), fs_error);
		}
		, FS_proto = FileSaver.prototype
		, saveAs = function(blob, name) {
			return new FileSaver(blob, name);
		}
	;
	FS_proto.abort = function() {
		var filesaver = this;
		filesaver.readyState = filesaver.DONE;
		dispatch(filesaver, "abort");
	};
	FS_proto.readyState = FS_proto.INIT = 0;
	FS_proto.WRITING = 1;
	FS_proto.DONE = 2;

	FS_proto.error =
	FS_proto.onwritestart =
	FS_proto.onprogress =
	FS_proto.onwrite =
	FS_proto.onabort =
	FS_proto.onerror =
	FS_proto.onwriteend =
		null;

	view.addEventListener("unload", process_deletion_queue, false);
	return saveAs;
}(
	   typeof self !== "undefined" && self
	|| typeof window !== "undefined" && window
	|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window

if (typeof module !== "undefined") module.exports = saveAs;
<|endoftext|>


<commit_before>var is = require('is');
var clone = require('clone');
var InputTypes = require('./InputTypes');

var FormMixin = {
	getInitialState: function(){
		return {
			initial_values_source_version: this.____getInitialValuesSourceVersion(this.props),
			data: this.____getInitialValues(this.props),
			errors: {},
			submit_attempts: 0
		};
	},
	componentWillReceiveProps: function(new_props){
		var initial_values_source_version = this.____getInitialValuesSourceVersion(new_props);
		if(this.state.initial_values_source_version !== initial_values_source_version){
			this.setState({
				initial_values_source_version: initial_values_source_version,
				data: this.____getInitialValues(new_props),
				errors: {},
				submit_attempts: 0
			});
		}
	},
	Form_validate: function(){
		var fields = this.Form_buildSchema();
		var data = this.state.data;
		return validateFields(fields, data);
	},
	Form_onSubmit: function(e){
		if(e && e.preventDefault){
			e.preventDefault();
		}
		var self = this;
		this.setState({
			submit_attempts: this.state.submit_attempts + 1,
			errors: this.Form_validate()
		}, function(){
			if(is.empty(self.state.errors)){
				self.____onSubmit(self.state.data);
			}else{
				self.____onSubmitFail(self.state.errors);
			}
		});
	},
	Form_onChange: function(field_name, new_value){
		var self = this;
		var fields = this.Form_buildSchema();
		var should_validate = this.state.submit_attempts > 0;
		var data = this.state.data;

		data[field_name] = new_value;

		this.setState({
			data: data,
			errors: should_validate ? validateFields(fields, data) : null
		}, function(){
			self.____onFormChanged(field_name, new_value);
		});
	},
	Form_buildInput: function(field){
		var self = this;
		var input = InputTypes.getInputByType(field.type);
		return input.component({
			field: field,
			value: this.state.data[field.name],
			onChange: function(value){
				self.Form_onChange(field.name, value);
			}
		});
	},
	Form_reset: function(){
		this.setState({data: this.____getInitialValues(this.props), errors: {}, submit_attempts: 0});
	},
	Form_areChangesMade: function(props){
		return !is.equal(this.state.data, this.____getInitialValues(props || this.props));
	},
	Form_buildSchema: function(){
		var schema = this.____buildSchema();
		Object.keys(schema).forEach(function(name){
			schema[name].name = name;
		});
		return schema;
	},

	//Below are functions that the child can implement
	____buildSchema: function(){
		if(is.fn(this.buildSchema)){
			return this.buildSchema();
		}else{
			console.warn("react-loose-forms FormMixin expects there to be a funciton on the compoent called buildSchema that returns the schema for the form.");
			return {};
		}
	},
	____getInitialValuesSourceVersion: function(props){
		if(is.fn(this.getInitialValuesSourceVersion)){
			return this.getInitialValuesSourceVersion(props);
		}
		return null;
	},
	____getInitialValues: function(props){
		if(is.fn(this.getInitialValues)){
			return clone(this.getInitialValues(props) || {});
		}
		return {};
	},
	____onFormChanged: function(field_name, new_value){
		if(is.fn(this.onFormChanged)){
			this.onFormChanged(field_name, new_value);
		}
	},
	____onSubmit: function(data){
		if(is.fn(this.props.onSubmit)){
			this.props.onSubmit(data);
		}
	},
	____onSubmitFail: function(errors){
		if(is.fn(this.props.onSubmitFail)){
			this.props.onSubmitFail(errors);
		}
	}
};

var defaultValidationFn = function(value, field){
	return true;
};

var validateFields = function(fields, data){
	var errors = {};
	Object.keys(fields).forEach(function(field_name){
		var field = fields[field_name];
		var validation_fn = defaultValidationFn;
		if(is.fn(field.validate)){
			validation_fn = field.validate;
		}else{
			var input = InputTypes.getInputByType(field.type);
			if(is.fn(input && input.validate)){
				validation_fn = input.validate;
			}
		}
		var resp = validation_fn(data[field_name], field);
		if(resp !== true){
			errors[field_name] = resp;
		}
	});
	return errors;
};

module.exports = FormMixin;
<commit_msg>getInitialValuesSourceVersion now json stringifies getInitialValues by default<commit_after>var is = require('is');
var clone = require('clone');
var InputTypes = require('./InputTypes');

var FormMixin = {
	getInitialState: function(){
		return {
			initial_values_source_version: this.____getInitialValuesSourceVersion(this.props),
			data: this.____getInitialValues(this.props),
			errors: {},
			submit_attempts: 0
		};
	},
	componentWillReceiveProps: function(new_props){
		var initial_values_source_version = this.____getInitialValuesSourceVersion(new_props);
		if(this.state.initial_values_source_version !== initial_values_source_version){
			this.setState({
				initial_values_source_version: initial_values_source_version,
				data: this.____getInitialValues(new_props),
				errors: {},
				submit_attempts: 0
			});
		}
	},
	Form_validate: function(){
		var fields = this.Form_buildSchema();
		var data = this.state.data;
		return validateFields(fields, data);
	},
	Form_onSubmit: function(e){
		if(e && e.preventDefault){
			e.preventDefault();
		}
		var self = this;
		this.setState({
			submit_attempts: this.state.submit_attempts + 1,
			errors: this.Form_validate()
		}, function(){
			if(is.empty(self.state.errors)){
				self.____onSubmit(self.state.data);
			}else{
				self.____onSubmitFail(self.state.errors);
			}
		});
	},
	Form_onChange: function(field_name, new_value){
		var self = this;
		var fields = this.Form_buildSchema();
		var should_validate = this.state.submit_attempts > 0;
		var data = this.state.data;

		data[field_name] = new_value;

		this.setState({
			data: data,
			errors: should_validate ? validateFields(fields, data) : null
		}, function(){
			self.____onFormChanged(field_name, new_value);
		});
	},
	Form_buildInput: function(field){
		var self = this;
		var input = InputTypes.getInputByType(field.type);
		return input.component({
			field: field,
			value: this.state.data[field.name],
			onChange: function(value){
				self.Form_onChange(field.name, value);
			}
		});
	},
	Form_reset: function(){
		this.setState({data: this.____getInitialValues(this.props), errors: {}, submit_attempts: 0});
	},
	Form_areChangesMade: function(props){
		return !is.equal(this.state.data, this.____getInitialValues(props || this.props));
	},
	Form_buildSchema: function(){
		var schema = this.____buildSchema();
		Object.keys(schema).forEach(function(name){
			schema[name].name = name;
		});
		return schema;
	},

	//Below are functions that the child can implement
	____buildSchema: function(){
		if(is.fn(this.buildSchema)){
			return this.buildSchema();
		}else{
			console.warn("react-loose-forms FormMixin expects there to be a funciton on the compoent called buildSchema that returns the schema for the form.");
			return {};
		}
	},
	____getInitialValuesSourceVersion: function(props){
		if(is.fn(this.getInitialValuesSourceVersion)){
			return this.getInitialValuesSourceVersion(props);
		}
		return JSON.stringify(this.____getInitialValues(props));
	},
	____getInitialValues: function(props){
		if(is.fn(this.getInitialValues)){
			return clone(this.getInitialValues(props) || {});
		}
		return {};
	},
	____onFormChanged: function(field_name, new_value){
		if(is.fn(this.onFormChanged)){
			this.onFormChanged(field_name, new_value);
		}
	},
	____onSubmit: function(data){
		if(is.fn(this.props.onSubmit)){
			this.props.onSubmit(data);
		}
	},
	____onSubmitFail: function(errors){
		if(is.fn(this.props.onSubmitFail)){
			this.props.onSubmitFail(errors);
		}
	}
};

var defaultValidationFn = function(value, field){
	return true;
};

var validateFields = function(fields, data){
	var errors = {};
	Object.keys(fields).forEach(function(field_name){
		var field = fields[field_name];
		var validation_fn = defaultValidationFn;
		if(is.fn(field.validate)){
			validation_fn = field.validate;
		}else{
			var input = InputTypes.getInputByType(field.type);
			if(is.fn(input && input.validate)){
				validation_fn = input.validate;
			}
		}
		var resp = validation_fn(data[field_name], field);
		if(resp !== true){
			errors[field_name] = resp;
		}
	});
	return errors;
};

module.exports = FormMixin;
<|endoftext|>


<commit_before>N.ConnectionTemplate({},
  function(context, from, to) {
    var connection = {
      className: 'N.Connection',
      name: 'FD',
      description: 'Fast depressing synapse inibitory synapse - logic equivalent 1.0',
      reference: 'https://www.evernote.com/shard/s211/nl/22441192/f0c99229-3113-499d-a2e5-cc461a5646a8/',
      path: from + '->' + to,
      threshold: 2.0, // nominally mV
      previousActivationStart: -100, // ms
      previousActivationEnd: -25, // ms
      gainDropOff: 10.0/25.0, // 10mv/25ms
      gainMin: 3.0, // minimum gain
      gainDropOffTime: 15, // ms
      minimumOffTime: 10, // ms - time with input below threshold before synapse 'resets'
      active: false,
      delay: 1, // ms
      update: function(time) {
        var current = this.source.getOutputAt(time-this.delay);
        if(this.active) {
          if(current < this.threshold) {
            this.previousActivationEnd = time;
            this.active = false;
            this.output = 0.0;
          } else {
            // The function for determining output.
            this.output = current*(
              (this.gainDropOff*this.gainDropOffTime-this.gainMin)*(time-this.previousActivationStart)
              +this.gainMin);
          }
        } else {
          if(current >= this.threshold) {
            this.previousActivationStart = time;
            this.output = this.gainDropOff*this.gainDropOffTime*this.gainMin*current;
          }
        }

        this.outputStore.appendData(time, this.output);
      }

    };
    context.self.connections = context.self.connections || [];
    context.self.connections.push(connection);
  }
);
<commit_msg>Fast spiking output algorithm was broken. Fixed and improved.<commit_after>N.ConnectionTemplate({},
  function(context, from, to) {
    var connection = {
      className: 'N.Connection',
      name: 'FD',
      description: 'Fast depressing synapse inibitory synapse - logic equivalent 1.0',
      reference: 'https://www.evernote.com/shard/s211/nl/22441192/f0c99229-3113-499d-a2e5-cc461a5646a8/',
      path: from + '->' + to,
      threshold: 2.0, // nominally mV
      activationStart: -100, // ms
      gainVarying: 10.0, // 10mv/25ms
      gainConstant: 3.0, // minimum gain
      timeConstant: 0.87055057, // drop off rate per ms. 0.87055057 is 10 ms half life
      active: false,
      delay: 1, // ms
      update: function(time) {
        var input = this.source.getOutputAt(time-this.delay);
        if(this.active) {
          if(input < this.threshold) {
            this.active = false;
            this.output = 0.0;
          } else {
            // The function for determining output.
            this.output = (this.gainVarying*Math.pow(this.timeConstant, time-this.activationStart)+this.gainConstant)*(input-this.threshold);
          }
        } else {
          if(input >= this.threshold) {
            this.activationStart = time;
            this.output = (this.gainVarying+this.gainConstant)*(input-this.threshold);
            this.active = true;
          }
        }

        this.outputStore.appendData(time, this.output);
      }

    };
    context.self.connections = context.self.connections || [];
    context.self.connections.push(connection);
  }
);
<|endoftext|>


<commit_before>/* piece.js */
define ([
	'three',
	'1401/objects/pieces/protopiece'
], function (
	THREE,
	ProtoPiece
) {

	var DBGOUT = false;

/**	Piece ********************************************************************\

	A piece is an autonomous actor within the system, and the various piece
	classes add various capabilities.

	The model for using a piece is to set its properties directly during
	initialization and give it a role to tell it what goals/behaviors it should
	work on. These goals and behaviors are changed as needed by managers or its
	own robot ai. This decouples the need to directly set parameters with
	some outside subroutine.

	NOTES

	This module is designed to be imported and used as a based for creating
	extended Piece classes in a constructor chain.

	Since Javascript does not have multiple inheritance, advanced functions
	like Physics, ai, etc are composed into properties.

	The Piece.Update, Think, and Execute methods are called every frame. Pieces
	are updated automatically; there is no need to call them yourself.

/** OBJECT DECLARATION ******************************************************/

///	PIECE /////////////////////////////////////////////////////////////////////
///	stores position, visual, event queues, and behavior hooks

	/*/ constructor /*/
	function Piece ( name ) {

	//	call the parent constructor
		ProtoPiece.call (this, name);

	//	position and orientation
		this.position = new THREE.Vector3(0,0,0);
		this.rotation = new THREE.Vector3(0,0,0);

	//	direction (unit vector);
		this.heading = new THREE.Vector3(1,0,0);

	//	utility position data
		this.position0 = null;	// last posiiton
		this.position1 = null;	// start position
		this.position2 = null;	// end position

	//	visual representation
		this.visual = null;

	//	physics features via physics engine
		this.body = null;

	//	autonomous features via state manager
		this.state = null;

	//	thinking features via ai
		this.ai = null;

	// 	override functions (useful for temp testing)
		this.updateFunc = null;
		this.thinkFunc = null;
		this.executeFunc = null;

	}
	/*/ inheritance /*/
	Piece.inheritsFrom(ProtoPiece);

/// PRE-ALLOCATED HEAP-SAVING VARIABLES ///////////////////////////////////////

	var override;

///	BASIC LIFECYCLE METHODS ///////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('Update', function ( interval_ms ) {

		override = false;
		if (this.updateFunc) {
			override = this.updateFunc.call (this, interval_ms);
			if (override) return;
		}
		if (this.state) this.state.Update( interval_ms );

	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('Think', function ( interval_ms ) {

		override = false;
		if (this.thinkFunc) {
			override = this.thinkFunc.call( this, interval_ms );
			if (override) return;
		}
		// behavior tree
		if (this.ai) this.ai.behavior.Execute( this, interval_ms );

	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('Execute', function ( interval_ms ) {

		override = false;
		if (this.executeFunc) {
			override = this.executeFunc.call( this, interval_ms );
			if (override) return;
		}

	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('OverrideUpdate', function ( func ) {
		if (typeof func!=='function') {
			console.error("not a function");
			return;
		}
		this.updateFunc = func;
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('OverrideThink', function ( func ) {
		if (typeof func!=='function') {
			console.error("not a function");
			return;
		}
		this.thinkFunc = func;
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('OverrideExecute', function ( func ) {
		if (typeof func!=='function') {
			console.error("not a function");
			return;
		}
		this.executeFunc = func;
	});

///	POSITION ACCESS METHODS //////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('Rotation', function () {
		return this.rotation.clone();
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method('RotationX', function () { return this.rotation.x; });
	Piece.method('RotationY', function () { return this.rotation.y; });
	Piece.method('RotationZ', function () { return this.rotation.z; });
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotation', function ( vector3 ) {
		if (vector3===undefined) console.error("rotation vector is undefined");
		if (typeof vector3!=='object') console.error('SetRotation requires Vector3, not',typeof vector3);
		SetRotatxionXYZ(vector3.x,vector3.y,vectory3.z);
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotationXYZ', function ( x, y, z ) {

		this.rotation.x = x;
		this.rotation.y = y;
		this.rotation.z = z;

		// update visual
		// NOTE: visuals are THREE.object3d instances
		if (this.visual) {
			this.visual.rotation.x = x;
			this.visual.rotation.y = y;
			this.visual.rotation.z = z;
			if (this.visual.inqsprite) {
				this.visual.Rotate(z);
			}
		}

	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotationX', function ( rot ) {
		if (rot===undefined) console.error("rotationX is undefined");
		this.SetRotationXYZ( rot, this.rotation.y, this.rotation.x );
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotationY', function ( rot ) {
		if (rot===undefined) console.error("rotationY is undefined");
		this.SetRotationXYZ ( this.rotation.x, rot, this.rotation.z );
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotationZ', function ( rot ) {
		if (rot===undefined) console.error("rotationZ is undefined");
		this.SetRotationXYZ ( this.rotation.x, this.rotation.y, rot );
	});

///	POSITION ACCESS METHODS //////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	Preferred way to read position of piece
/*/	Piece.method ('Position', function () {
		// return a copy, so callee can manipulate it without borking
		// the piece's actual position.
		return this.position.clone();
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	Preferred way to set the position of the piece
/*/	Piece.method ('SetPosition', function ( vector3 ) {
		this.SetPositionXYZ(vector3.x,vector3.y,vector3.z);
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionXYZ', function ( x, y, z ) {

		// calculate heading based on old positions
		var hx = x - this.position.x;
		var hy = y - this.position.y;
		var hz = z - this.position.z;
		// update if the change exceeds threashold
		if ( (hx*hx+hy*hy+hz*hz)>.00001 ) {
			this.heading.x = hx;
			this.heading.y = hy;
			this.heading.z = hz;
			this.heading.normalize();
		}

		// copy position into current vector
		this.position.x = x;
		this.position.y = y;
		this.position.z = z;

		// NOTE: visuals are THREE.object3d instances
		if (this.visual) {
			this.visual.position.x = x;
			this.visual.position.y = y;
			this.visual.position.z = z;
		}
		// NOTE: physics engine hooks also exist in movingpiece.js
		if (this.body) {
			// this.body.position.x = vector3.x;
			// this.body.position.y = vector3.y;
		}
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionXY', function ( x, y ) {
		this.SetPositionXYZ( x, y, this.position.z );
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionX', function ( x ) {
		this.SetPositionXYZ( x, this.position.y, this.position.z );
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionY', function ( y ) {
		this.SetPositionXYZ(this.position.x, y, this.position.z);
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionZ', function ( z ) {
		this.SetPositionXYZ( this.position.x, this.position.y, z );
	});

///	DIRECTION ACCESSORS //////////////////////////////////////////////////////
/// The Heading is the direction of movement of a piece, which is not the
///	same as the way a piece of pointing. Calculated by SetPositionXYZ.
///	If physics engine is in use.
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	Get the angle of the heading vector.
/*/	Piece.method ('HeadingAngle', function () {
		// NOTE: physics engine hooks also exist in movingpiece.js
		if (this.body) {
			/* TODO: return physics-based heading */
		} else {
			// otherwise calculate based on stored positions
			return Math.atan2(this.heading.y, this.heading.x);
		}
	});

///	VISUAL METHODS ////////////////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('Visual', function () {
		return this.visual;
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetVisual', function ( vis ) {

		if (vis===undefined) {
			console.warn("To unset visual, use value of 'null' instead of 'undefined");
			return;
		}
		if (vis===null) {
			// clear the current visual
			if (this.visual) {
				var pieceId = this.visual.pieceId;
				if (this.visual.pieceId) {
					if (DBGOUT)
						console.log('removed visual',this.visual.pieceId,'from',pieceId);
					this.visual.pieceId = null;
				}
			}
			this.visual = null;
		} else {
			// assign new visual to this piece
			if (vis.pieceId) // is already assigned or not null
				console.warn("visual",vis.id,"is being assigned again to piece",this.id);
			this.visual = vis;
			this.visual.pieceId = this.id;
		}
	});

/** RETURN CONSTRUCTOR *******************************************************/

	return Piece;

});<commit_msg>add leading 0<commit_after>/* piece.js */
define ([
	'three',
	'1401/objects/pieces/protopiece'
], function (
	THREE,
	ProtoPiece
) {

	var DBGOUT = false;

/**	Piece ********************************************************************\

	A piece is an autonomous actor within the system, and the various piece
	classes add various capabilities.

	The model for using a piece is to set its properties directly during
	initialization and give it a role to tell it what goals/behaviors it should
	work on. These goals and behaviors are changed as needed by managers or its
	own robot ai. This decouples the need to directly set parameters with
	some outside subroutine.

	NOTES

	This module is designed to be imported and used as a based for creating
	extended Piece classes in a constructor chain.

	Since Javascript does not have multiple inheritance, advanced functions
	like Physics, ai, etc are composed into properties.

	The Piece.Update, Think, and Execute methods are called every frame. Pieces
	are updated automatically; there is no need to call them yourself.

/** OBJECT DECLARATION ******************************************************/

///	PIECE /////////////////////////////////////////////////////////////////////
///	stores position, visual, event queues, and behavior hooks

	/*/ constructor /*/
	function Piece ( name ) {

	//	call the parent constructor
		ProtoPiece.call (this, name);

	//	position and orientation
		this.position = new THREE.Vector3(0,0,0);
		this.rotation = new THREE.Vector3(0,0,0);

	//	direction (unit vector);
		this.heading = new THREE.Vector3(1,0,0);

	//	utility position data
		this.position0 = null;	// last posiiton
		this.position1 = null;	// start position
		this.position2 = null;	// end position

	//	visual representation
		this.visual = null;

	//	physics features via physics engine
		this.body = null;

	//	autonomous features via state manager
		this.state = null;

	//	thinking features via ai
		this.ai = null;

	// 	override functions (useful for temp testing)
		this.updateFunc = null;
		this.thinkFunc = null;
		this.executeFunc = null;

	}
	/*/ inheritance /*/
	Piece.inheritsFrom(ProtoPiece);

/// PRE-ALLOCATED HEAP-SAVING VARIABLES ///////////////////////////////////////

	var override;

///	BASIC LIFECYCLE METHODS ///////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('Update', function ( interval_ms ) {

		override = false;
		if (this.updateFunc) {
			override = this.updateFunc.call (this, interval_ms);
			if (override) return;
		}
		if (this.state) this.state.Update( interval_ms );

	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('Think', function ( interval_ms ) {

		override = false;
		if (this.thinkFunc) {
			override = this.thinkFunc.call( this, interval_ms );
			if (override) return;
		}
		// behavior tree
		if (this.ai) this.ai.behavior.Execute( this, interval_ms );

	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('Execute', function ( interval_ms ) {

		override = false;
		if (this.executeFunc) {
			override = this.executeFunc.call( this, interval_ms );
			if (override) return;
		}

	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('OverrideUpdate', function ( func ) {
		if (typeof func!=='function') {
			console.error("not a function");
			return;
		}
		this.updateFunc = func;
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('OverrideThink', function ( func ) {
		if (typeof func!=='function') {
			console.error("not a function");
			return;
		}
		this.thinkFunc = func;
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('OverrideExecute', function ( func ) {
		if (typeof func!=='function') {
			console.error("not a function");
			return;
		}
		this.executeFunc = func;
	});

///	POSITION ACCESS METHODS //////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('Rotation', function () {
		return this.rotation.clone();
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method('RotationX', function () { return this.rotation.x; });
	Piece.method('RotationY', function () { return this.rotation.y; });
	Piece.method('RotationZ', function () { return this.rotation.z; });
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotation', function ( vector3 ) {
		if (vector3===undefined) console.error("rotation vector is undefined");
		if (typeof vector3!=='object') console.error('SetRotation requires Vector3, not',typeof vector3);
		SetRotatxionXYZ(vector3.x,vector3.y,vectory3.z);
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotationXYZ', function ( x, y, z ) {

		this.rotation.x = x;
		this.rotation.y = y;
		this.rotation.z = z;

		// update visual
		// NOTE: visuals are THREE.object3d instances
		if (this.visual) {
			this.visual.rotation.x = x;
			this.visual.rotation.y = y;
			this.visual.rotation.z = z;
			if (this.visual.inqsprite) {
				this.visual.Rotate(z);
			}
		}

	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotationX', function ( rot ) {
		if (rot===undefined) console.error("rotationX is undefined");
		this.SetRotationXYZ( rot, this.rotation.y, this.rotation.x );
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotationY', function ( rot ) {
		if (rot===undefined) console.error("rotationY is undefined");
		this.SetRotationXYZ ( this.rotation.x, rot, this.rotation.z );
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/
/*/	Piece.method('SetRotationZ', function ( rot ) {
		if (rot===undefined) console.error("rotationZ is undefined");
		this.SetRotationXYZ ( this.rotation.x, this.rotation.y, rot );
	});

///	POSITION ACCESS METHODS //////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	Preferred way to read position of piece
/*/	Piece.method ('Position', function () {
		// return a copy, so callee can manipulate it without borking
		// the piece's actual position.
		return this.position.clone();
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	Preferred way to set the position of the piece
/*/	Piece.method ('SetPosition', function ( vector3 ) {
		this.SetPositionXYZ(vector3.x,vector3.y,vector3.z);
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionXYZ', function ( x, y, z ) {

		// calculate heading based on old positions
		var hx = x - this.position.x;
		var hy = y - this.position.y;
		var hz = z - this.position.z;
		// update if the change exceeds threashold
		if ( (hx*hx+hy*hy+hz*hz)>0.00001 ) {
			this.heading.x = hx;
			this.heading.y = hy;
			this.heading.z = hz;
			this.heading.normalize();
		}

		// copy position into current vector
		this.position.x = x;
		this.position.y = y;
		this.position.z = z;

		// NOTE: visuals are THREE.object3d instances
		if (this.visual) {
			this.visual.position.x = x;
			this.visual.position.y = y;
			this.visual.position.z = z;
		}
		// NOTE: physics engine hooks also exist in movingpiece.js
		if (this.body) {
			// this.body.position.x = vector3.x;
			// this.body.position.y = vector3.y;
		}
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionXY', function ( x, y ) {
		this.SetPositionXYZ( x, y, this.position.z );
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionX', function ( x ) {
		this.SetPositionXYZ( x, this.position.y, this.position.z );
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionY', function ( y ) {
		this.SetPositionXYZ(this.position.x, y, this.position.z);
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetPositionZ', function ( z ) {
		this.SetPositionXYZ( this.position.x, this.position.y, z );
	});

///	DIRECTION ACCESSORS //////////////////////////////////////////////////////
/// The Heading is the direction of movement of a piece, which is not the
///	same as the way a piece of pointing. Calculated by SetPositionXYZ.
///	If physics engine is in use.
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*/	Get the angle of the heading vector.
/*/	Piece.method ('HeadingAngle', function () {
		// NOTE: physics engine hooks also exist in movingpiece.js
		if (this.body) {
			/* TODO: return physics-based heading */
		} else {
			// otherwise calculate based on stored positions
			return Math.atan2(this.heading.y, this.heading.x);
		}
	});

///	VISUAL METHODS ////////////////////////////////////////////////////////////
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('Visual', function () {
		return this.visual;
	});
///	- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Piece.method ('SetVisual', function ( vis ) {

		if (vis===undefined) {
			console.warn("To unset visual, use value of 'null' instead of 'undefined");
			return;
		}
		if (vis===null) {
			// clear the current visual
			if (this.visual) {
				var pieceId = this.visual.pieceId;
				if (this.visual.pieceId) {
					if (DBGOUT)
						console.log('removed visual',this.visual.pieceId,'from',pieceId);
					this.visual.pieceId = null;
				}
			}
			this.visual = null;
		} else {
			// assign new visual to this piece
			if (vis.pieceId) // is already assigned or not null
				console.warn("visual",vis.id,"is being assigned again to piece",this.id);
			this.visual = vis;
			this.visual.pieceId = this.id;
		}
	});

/** RETURN CONSTRUCTOR *******************************************************/

	return Piece;

});
<|endoftext|>