<commit_before>
var express = require('../')
  , request = require('./support/http')
  , assert = require('assert')
  , methods = require('methods');

describe('app.router', function(){
  describe('methods supported', function(){
    methods.forEach(function(method){
      it('should include ' + method.toUpperCase(), function(done){
        if (method == 'delete') method = 'del';
        var app = express();
        var calls = [];

        app[method]('/foo', function(req, res){
          if ('head' == method) {
            res.end();
          } else {
            res.end(method);
          }
        });

        request(app)
        [method]('/foo')
        .expect('head' == method ? '' : method, done);
      })
    });
  })

  describe('decode querystring', function(){
    it('should decode correct params', function(done){
      var app = express();

      app.get('/:name', function(req, res, next){
        res.send(req.params.name);
      });

      request(app)
      .get('/foo%2Fbar')
      .expect('foo/bar', done);
    })

    it('should not accept params in malformed paths', function(done) {
      var app = express();

      app.get('/:name', function(req, res, next){
        res.send(req.params.name);
      });

      request(app)
      .get('/%foobar')
      .expect(400, done);
    })

    it('should not decode spaces', function(done) {
      var app = express();

      app.get('/:name', function(req, res, next){
        res.send(req.params.name);
      });

      request(app)
      .get('/foo+bar')
      .expect('foo+bar', done);
    })

    it('should work with unicode', function(done) {
      var app = express();

      app.get('/:name', function(req, res, next){
        res.send(req.params.name);
      });

      request(app)
      .get('/%ce%b1')
      .expect('\u03b1', done);
    })
  })

  it('should be .use()able', function(done){
    var app = express();

    var calls = [];

    app.use(function(req, res, next){
      calls.push('before');
      next();
    });

    app.get('/', function(req, res, next){
      calls.push('GET /')
      next();
    });

    app.use(function(req, res, next){
      calls.push('after');
      res.end();
    });

    request(app)
    .get('/')
    .end(function(res){
      calls.should.eql(['before', 'GET /', 'after'])
      done();
    })
  })

  describe('when given a regexp', function(){
    it('should match the pathname only', function(done){
      var app = express();

      app.get(/^\/user\/[0-9]+$/, function(req, res){
        res.end('user');
      });

      request(app)
      .get('/user/12?foo=bar')
      .expect('user', done);
    })

    it('should populate req.params with the captures', function(done){
      var app = express();

      app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function(req, res){
        var id = req.params[0]
          , op = req.params[1];
        res.end(op + 'ing user ' + id);
      });

      request(app)
      .get('/user/10/edit')
      .expect('editing user 10', done);
    })
  })

  describe('case sensitivity', function(){
    it('should be disabled by default', function(done){
      var app = express();

      app.get('/user', function(req, res){
        res.end('tj');
      });

      request(app)
      .get('/USER')
      .expect('tj', done);
    })

    describe('when "case sensitive routing" is enabled', function(){
      it('should match identical casing', function(done){
        var app = express();

        app.enable('case sensitive routing');

        app.get('/uSer', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/uSer')
        .expect('tj', done);
      })

      it('should not match otherwise', function(done){
        var app = express();

        app.enable('case sensitive routing');

        app.get('/uSer', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user')
        .expect(404, done);
      })
    })
  })

  describe('trailing slashes', function(){
    it('should be optional by default', function(done){
      var app = express();

      app.get('/user', function(req, res){
        res.end('tj');
      });

      request(app)
      .get('/user/')
      .expect('tj', done);
    })

    describe('when "strict routing" is enabled', function(){
      it('should match trailing slashes', function(done){
        var app = express();

        app.enable('strict routing');

        app.get('/user/', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user/')
        .expect('tj', done);
      })

      it('should match no slashes', function(done){
        var app = express();

        app.enable('strict routing');

        app.get('/user', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user')
        .expect('tj', done);
      })

      it('should fail when omitting the trailing slash', function(done){
        var app = express();

        app.enable('strict routing');

        app.get('/user/', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user')
        .expect(404, done);
      })

      it('should fail when adding the trailing slash', function(done){
        var app = express();

        app.enable('strict routing');

        app.get('/user', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user/')
        .expect(404, done);
      })
    })
  })

  it('should allow escaped regexp', function(done){
    var app = express();

    app.get('/user/\\d+', function(req, res){
      res.end('woot');
    });

    request(app)
    .get('/user/10')
    .end(function(err, res){
      res.statusCode.should.equal(200);
      request(app)
      .get('/user/tj')
      .expect(404, done);
    });
  })

  it('should allow literal "."', function(done){
    var app = express();

    app.get('/api/users/:from..:to', function(req, res){
      var from = req.params.from
        , to = req.params.to;

      res.end('users from ' + from + ' to ' + to);
    });

    request(app)
    .get('/api/users/1..50')
    .expect('users from 1 to 50', done);
  })

  describe('*', function(){
    it('should denote a greedy capture group', function(done){
      var app = express();

      app.get('/user/*.json', function(req, res){
        res.end(req.params[0]);
      });

      request(app)
      .get('/user/tj.json')
      .expect('tj', done);
    })

    it('should work with several', function(done){
      var app = express();

      app.get('/api/*.*', function(req, res){
        var resource = req.params[0]
          , format = req.params[1];
        res.end(resource + ' as ' + format);
      });

      request(app)
      .get('/api/users/foo.bar.json')
      .expect('users/foo.bar as json', done);
    })

    it('should work cross-segment', function(done){
      var app = express();

      app.get('/api*', function(req, res){
        res.send(req.params[0]);
      });

      request(app)
      .get('/api')
      .expect('', function(){
        request(app)
        .get('/api/hey')
        .expect('/hey', done);
      });
    })

    it('should allow naming', function(done){
      var app = express();

      app.get('/api/:resource(*)', function(req, res){
        var resource = req.params.resource;
        res.end(resource);
      });

      request(app)
      .get('/api/users/0.json')
      .expect('users/0.json', done);
    })

    it('should not be greedy immediately after param', function(done){
      var app = express();

      app.get('/user/:user*', function(req, res){
        res.end(req.params.user);
      });

      request(app)
      .get('/user/122')
      .expect('122', done);
    })

    it('should eat everything after /', function(done){
      var app = express();

      app.get('/user/:user*', function(req, res){
        res.end(req.params.user);
      });

      request(app)
      .get('/user/122/aaa')
      .expect('122', done);
    })

    it('should span multiple segments', function(done){
      var app = express();

      app.get('/file/*', function(req, res){
        res.end(req.params[0]);
      });

      request(app)
      .get('/file/javascripts/jquery.js')
      .expect('javascripts/jquery.js', done);
    })

    it('should be optional', function(done){
      var app = express();

      app.get('/file/*', function(req, res){
        res.end(req.params[0]);
      });

      request(app)
      .get('/file/')
      .expect('', done);
    })

    it('should require a preceeding /', function(done){
      var app = express();

      app.get('/file/*', function(req, res){
        res.end(req.params[0]);
      });

      request(app)
      .get('/file')
      .expect(404, done);
    })
  })

  describe(':name', function(){
    it('should denote a capture group', function(done){
      var app = express();

      app.get('/user/:user', function(req, res){
        res.end(req.params.user);
      });

      request(app)
      .get('/user/tj')
      .expect('tj', done);
    })

    it('should match a single segment only', function(done){
      var app = express();

      app.get('/user/:user', function(req, res){
        res.end(req.params.user);
      });

      request(app)
      .get('/user/tj/edit')
      .expect(404, done);
    })

    it('should allow several capture groups', function(done){
      var app = express();

      app.get('/user/:user/:op', function(req, res){
        res.end(req.params.op + 'ing ' + req.params.user);
      });

      request(app)
      .get('/user/tj/edit')
      .expect('editing tj', done);
    })
  })

  describe(':name?', function(){
    it('should denote an optional capture group', function(done){
      var app = express();

      app.get('/user/:user/:op?', function(req, res){
        var op = req.params.op || 'view';
        res.end(op + 'ing ' + req.params.user);
      });

      request(app)
      .get('/user/tj')
      .expect('viewing tj', done);
    })

    it('should populate the capture group', function(done){
      var app = express();

      app.get('/user/:user/:op?', function(req, res){
        var op = req.params.op || 'view';
        res.end(op + 'ing ' + req.params.user);
      });

      request(app)
      .get('/user/tj/edit')
      .expect('editing tj', done);
    })
  })

  describe('.:name', function(){
    it('should denote a format', function(done){
      var app = express();

      app.get('/:name.:format', function(req, res){
        res.end(req.params.name + ' as ' + req.params.format);
      });

      request(app)
      .get('/foo.json')
      .expect('foo as json', function(){
        request(app)
        .get('/foo')
        .expect(404, done);
      });
    })
  })

  describe('.:name?', function(){
    it('should denote an optional format', function(done){
      var app = express();

      app.get('/:name.:format?', function(req, res){
        res.end(req.params.name + ' as ' + (req.params.format || 'html'));
      });

      request(app)
      .get('/foo')
      .expect('foo as html', function(){
        request(app)
        .get('/foo.json')
        .expect('foo as json', done);
      });
    })
  })

  describe('when next() is called', function(){
    it('should continue lookup', function(done){
      var app = express()
        , calls = [];

      app.get('/foo/:bar?', function(req, res, next){
        calls.push('/foo/:bar?');
        next();
      });

      app.get('/bar', function(req, res){
        assert(0);
      });

      app.get('/foo', function(req, res, next){
        calls.push('/foo');
        next();
      });

      app.get('/foo', function(req, res, next){
        calls.push('/foo 2');
        res.end('done');
      });

      request(app)
      .get('/foo')
      .expect('done', function(){
        calls.should.eql(['/foo/:bar?', '/foo', '/foo 2']);
        done();
      })
    })
  })

  describe('when next(err) is called', function(){
    it('should break out of app.router', function(done){
      var app = express()
        , calls = [];

      app.get('/foo/:bar?', function(req, res, next){
        calls.push('/foo/:bar?');
        next();
      });

      app.get('/bar', function(req, res){
        assert(0);
      });

      app.get('/foo', function(req, res, next){
        calls.push('/foo');
        next(new Error('fail'));
      });

      app.get('/foo', function(req, res, next){
        assert(0);
      });

      app.use(function(err, req, res, next){
        res.end(err.message);
      })

      request(app)
      .get('/foo')
      .expect('fail', function(){
        calls.should.eql(['/foo/:bar?', '/foo']);
        done();
      })
    })
  })

  it('should allow rewriting of the url', function(done){
    var app = express();

    app.get('/account/edit', function(req, res, next){
      req.user = { id: 12 }; // faux authenticated user
      req.url = '/user/' + req.user.id + '/edit';
      next();
    });

    app.get('/user/:id/edit', function(req, res){
      res.send('editing user ' + req.params.id);
    });

    request(app)
    .get('/account/edit')
    .expect('editing user 12', done);
  })

  it('should be chainable', function(){
    var app = express();
    app.get('/', function(){}).should.equal(app);
  })
})
<commit_msg>test app.router: ignore connect method<commit_after>
var express = require('../')
  , request = require('./support/http')
  , assert = require('assert')
  , methods = require('methods');

describe('app.router', function(){
  describe('methods supported', function(){
    methods.forEach(function(method){
      if (method === 'connect') return;

      it('should include ' + method.toUpperCase(), function(done){
        if (method == 'delete') method = 'del';
        var app = express();
        var calls = [];

        app[method]('/foo', function(req, res){
          if ('head' == method) {
            res.end();
          } else {
            res.end(method);
          }
        });

        request(app)
        [method]('/foo')
        .expect('head' == method ? '' : method, done);
      })
    });
  })

  describe('decode querystring', function(){
    it('should decode correct params', function(done){
      var app = express();

      app.get('/:name', function(req, res, next){
        res.send(req.params.name);
      });

      request(app)
      .get('/foo%2Fbar')
      .expect('foo/bar', done);
    })

    it('should not accept params in malformed paths', function(done) {
      var app = express();

      app.get('/:name', function(req, res, next){
        res.send(req.params.name);
      });

      request(app)
      .get('/%foobar')
      .expect(400, done);
    })

    it('should not decode spaces', function(done) {
      var app = express();

      app.get('/:name', function(req, res, next){
        res.send(req.params.name);
      });

      request(app)
      .get('/foo+bar')
      .expect('foo+bar', done);
    })

    it('should work with unicode', function(done) {
      var app = express();

      app.get('/:name', function(req, res, next){
        res.send(req.params.name);
      });

      request(app)
      .get('/%ce%b1')
      .expect('\u03b1', done);
    })
  })

  it('should be .use()able', function(done){
    var app = express();

    var calls = [];

    app.use(function(req, res, next){
      calls.push('before');
      next();
    });

    app.get('/', function(req, res, next){
      calls.push('GET /')
      next();
    });

    app.use(function(req, res, next){
      calls.push('after');
      res.end();
    });

    request(app)
    .get('/')
    .end(function(res){
      calls.should.eql(['before', 'GET /', 'after'])
      done();
    })
  })

  describe('when given a regexp', function(){
    it('should match the pathname only', function(done){
      var app = express();

      app.get(/^\/user\/[0-9]+$/, function(req, res){
        res.end('user');
      });

      request(app)
      .get('/user/12?foo=bar')
      .expect('user', done);
    })

    it('should populate req.params with the captures', function(done){
      var app = express();

      app.get(/^\/user\/([0-9]+)\/(view|edit)?$/, function(req, res){
        var id = req.params[0]
          , op = req.params[1];
        res.end(op + 'ing user ' + id);
      });

      request(app)
      .get('/user/10/edit')
      .expect('editing user 10', done);
    })
  })

  describe('case sensitivity', function(){
    it('should be disabled by default', function(done){
      var app = express();

      app.get('/user', function(req, res){
        res.end('tj');
      });

      request(app)
      .get('/USER')
      .expect('tj', done);
    })

    describe('when "case sensitive routing" is enabled', function(){
      it('should match identical casing', function(done){
        var app = express();

        app.enable('case sensitive routing');

        app.get('/uSer', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/uSer')
        .expect('tj', done);
      })

      it('should not match otherwise', function(done){
        var app = express();

        app.enable('case sensitive routing');

        app.get('/uSer', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user')
        .expect(404, done);
      })
    })
  })

  describe('trailing slashes', function(){
    it('should be optional by default', function(done){
      var app = express();

      app.get('/user', function(req, res){
        res.end('tj');
      });

      request(app)
      .get('/user/')
      .expect('tj', done);
    })

    describe('when "strict routing" is enabled', function(){
      it('should match trailing slashes', function(done){
        var app = express();

        app.enable('strict routing');

        app.get('/user/', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user/')
        .expect('tj', done);
      })

      it('should match no slashes', function(done){
        var app = express();

        app.enable('strict routing');

        app.get('/user', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user')
        .expect('tj', done);
      })

      it('should fail when omitting the trailing slash', function(done){
        var app = express();

        app.enable('strict routing');

        app.get('/user/', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user')
        .expect(404, done);
      })

      it('should fail when adding the trailing slash', function(done){
        var app = express();

        app.enable('strict routing');

        app.get('/user', function(req, res){
          res.end('tj');
        });

        request(app)
        .get('/user/')
        .expect(404, done);
      })
    })
  })

  it('should allow escaped regexp', function(done){
    var app = express();

    app.get('/user/\\d+', function(req, res){
      res.end('woot');
    });

    request(app)
    .get('/user/10')
    .end(function(err, res){
      res.statusCode.should.equal(200);
      request(app)
      .get('/user/tj')
      .expect(404, done);
    });
  })

  it('should allow literal "."', function(done){
    var app = express();

    app.get('/api/users/:from..:to', function(req, res){
      var from = req.params.from
        , to = req.params.to;

      res.end('users from ' + from + ' to ' + to);
    });

    request(app)
    .get('/api/users/1..50')
    .expect('users from 1 to 50', done);
  })

  describe('*', function(){
    it('should denote a greedy capture group', function(done){
      var app = express();

      app.get('/user/*.json', function(req, res){
        res.end(req.params[0]);
      });

      request(app)
      .get('/user/tj.json')
      .expect('tj', done);
    })

    it('should work with several', function(done){
      var app = express();

      app.get('/api/*.*', function(req, res){
        var resource = req.params[0]
          , format = req.params[1];
        res.end(resource + ' as ' + format);
      });

      request(app)
      .get('/api/users/foo.bar.json')
      .expect('users/foo.bar as json', done);
    })

    it('should work cross-segment', function(done){
      var app = express();

      app.get('/api*', function(req, res){
        res.send(req.params[0]);
      });

      request(app)
      .get('/api')
      .expect('', function(){
        request(app)
        .get('/api/hey')
        .expect('/hey', done);
      });
    })

    it('should allow naming', function(done){
      var app = express();

      app.get('/api/:resource(*)', function(req, res){
        var resource = req.params.resource;
        res.end(resource);
      });

      request(app)
      .get('/api/users/0.json')
      .expect('users/0.json', done);
    })

    it('should not be greedy immediately after param', function(done){
      var app = express();

      app.get('/user/:user*', function(req, res){
        res.end(req.params.user);
      });

      request(app)
      .get('/user/122')
      .expect('122', done);
    })

    it('should eat everything after /', function(done){
      var app = express();

      app.get('/user/:user*', function(req, res){
        res.end(req.params.user);
      });

      request(app)
      .get('/user/122/aaa')
      .expect('122', done);
    })

    it('should span multiple segments', function(done){
      var app = express();

      app.get('/file/*', function(req, res){
        res.end(req.params[0]);
      });

      request(app)
      .get('/file/javascripts/jquery.js')
      .expect('javascripts/jquery.js', done);
    })

    it('should be optional', function(done){
      var app = express();

      app.get('/file/*', function(req, res){
        res.end(req.params[0]);
      });

      request(app)
      .get('/file/')
      .expect('', done);
    })

    it('should require a preceeding /', function(done){
      var app = express();

      app.get('/file/*', function(req, res){
        res.end(req.params[0]);
      });

      request(app)
      .get('/file')
      .expect(404, done);
    })
  })

  describe(':name', function(){
    it('should denote a capture group', function(done){
      var app = express();

      app.get('/user/:user', function(req, res){
        res.end(req.params.user);
      });

      request(app)
      .get('/user/tj')
      .expect('tj', done);
    })

    it('should match a single segment only', function(done){
      var app = express();

      app.get('/user/:user', function(req, res){
        res.end(req.params.user);
      });

      request(app)
      .get('/user/tj/edit')
      .expect(404, done);
    })

    it('should allow several capture groups', function(done){
      var app = express();

      app.get('/user/:user/:op', function(req, res){
        res.end(req.params.op + 'ing ' + req.params.user);
      });

      request(app)
      .get('/user/tj/edit')
      .expect('editing tj', done);
    })
  })

  describe(':name?', function(){
    it('should denote an optional capture group', function(done){
      var app = express();

      app.get('/user/:user/:op?', function(req, res){
        var op = req.params.op || 'view';
        res.end(op + 'ing ' + req.params.user);
      });

      request(app)
      .get('/user/tj')
      .expect('viewing tj', done);
    })

    it('should populate the capture group', function(done){
      var app = express();

      app.get('/user/:user/:op?', function(req, res){
        var op = req.params.op || 'view';
        res.end(op + 'ing ' + req.params.user);
      });

      request(app)
      .get('/user/tj/edit')
      .expect('editing tj', done);
    })
  })

  describe('.:name', function(){
    it('should denote a format', function(done){
      var app = express();

      app.get('/:name.:format', function(req, res){
        res.end(req.params.name + ' as ' + req.params.format);
      });

      request(app)
      .get('/foo.json')
      .expect('foo as json', function(){
        request(app)
        .get('/foo')
        .expect(404, done);
      });
    })
  })

  describe('.:name?', function(){
    it('should denote an optional format', function(done){
      var app = express();

      app.get('/:name.:format?', function(req, res){
        res.end(req.params.name + ' as ' + (req.params.format || 'html'));
      });

      request(app)
      .get('/foo')
      .expect('foo as html', function(){
        request(app)
        .get('/foo.json')
        .expect('foo as json', done);
      });
    })
  })

  describe('when next() is called', function(){
    it('should continue lookup', function(done){
      var app = express()
        , calls = [];

      app.get('/foo/:bar?', function(req, res, next){
        calls.push('/foo/:bar?');
        next();
      });

      app.get('/bar', function(req, res){
        assert(0);
      });

      app.get('/foo', function(req, res, next){
        calls.push('/foo');
        next();
      });

      app.get('/foo', function(req, res, next){
        calls.push('/foo 2');
        res.end('done');
      });

      request(app)
      .get('/foo')
      .expect('done', function(){
        calls.should.eql(['/foo/:bar?', '/foo', '/foo 2']);
        done();
      })
    })
  })

  describe('when next(err) is called', function(){
    it('should break out of app.router', function(done){
      var app = express()
        , calls = [];

      app.get('/foo/:bar?', function(req, res, next){
        calls.push('/foo/:bar?');
        next();
      });

      app.get('/bar', function(req, res){
        assert(0);
      });

      app.get('/foo', function(req, res, next){
        calls.push('/foo');
        next(new Error('fail'));
      });

      app.get('/foo', function(req, res, next){
        assert(0);
      });

      app.use(function(err, req, res, next){
        res.end(err.message);
      })

      request(app)
      .get('/foo')
      .expect('fail', function(){
        calls.should.eql(['/foo/:bar?', '/foo']);
        done();
      })
    })
  })

  it('should allow rewriting of the url', function(done){
    var app = express();

    app.get('/account/edit', function(req, res, next){
      req.user = { id: 12 }; // faux authenticated user
      req.url = '/user/' + req.user.id + '/edit';
      next();
    });

    app.get('/user/:id/edit', function(req, res){
      res.send('editing user ' + req.params.id);
    });

    request(app)
    .get('/account/edit')
    .expect('editing user 12', done);
  })

  it('should be chainable', function(){
    var app = express();
    app.get('/', function(){}).should.equal(app);
  })
})
<|endoftext|>


<commit_before>function ddg_spice_aur(response) {
    if (response.type == 'error'
            || !response.results
            || response.results.length == 0)
        return;

    var pkgs = response.results;
    var pkg  = pkgs[0];

    var query = DDG.get_query().replace(/(aur|archlinux package|arch package|arch linux package)/, "");

    Spice.render({
        data             : pkgs.length == 1 ? pkg : { 'package' : pkgs },
        header1          : pkg['Name'] + " (AUR)",
        source_url       : 'https://aur.archlinux.org/packages/?O=0&K=' + query,
        source_name      : 'ArchLinux User Repository',
        template_normal  : pkgs.length == 1 ? 'single' : 'list',
        force_big_header : true
    });
}
<commit_msg>Aur: Linted.<commit_after>function ddg_spice_aur(response) {
    "use strict";

    if (response.type === 'error' || !response.results || response.results.length === 0) {
        return;
    }

    var pkgs = response.results;
    var pkg  = pkgs[0];

    var query = DDG.get_query().replace(/(aur|archlinux package|arch package|arch linux package)/, "");

    Spice.render({
        data             : pkgs.length === 1 ? pkg : {'package' : pkgs},
        header1          : pkg.Name + " (AUR)",
        source_url       : 'https://aur.archlinux.org/packages/?O=0&K=' + query,
        source_name      : 'ArchLinux User Repository',
        template_normal  : pkgs.length === 1 ? 'single' : 'list',
        force_big_header : true
    });
}
<|endoftext|>


<commit_before>var fields = refilm`
文件
`;

function main() {
    var page = div();
    page.innerHTML = root;
    page.onback = function () {
        var $scope = this.$scope;
        if (!$scope.pathlist.length) {
            return;
        }
        $scope.pathlist.pop();
        $scope.open();
        return false;
    }
    page.setAttribute('ng-mousedown', 'setActive')

    renderWithDefaults(page, {
        lattice,
        pathlist: [],
        active: null,
        open(p) {
            if (p) p = String(p.name || '').replace(/\/$/, '');
            if (p) this.pathlist.push(p);
            this.data = data.from("folder", { opt: 'list', path: "/" + this.pathlist.join('/') }, files => {
                if (files) return sortname(files).map(f => {
                    return {
                        name: f,
                        type: /\/$/.test(f) ? 'folder' : 'file'
                    }
                });
            });
        },
        setActive(e) {
            this.active = getActive(e);
        },
        data: [],
    });
    page.$scope.open();
    var getActive = e => {
        var p = page.querySelector('lattice');
        var t = getTargetIn(e => e.parentNode && e.parentNode.parentNode === p, e.target);
        return t;
    };
    var when = e => !!getActive(e);
    var popupEdit = function (e) {
        zimoli.prepare('/wow/edit', function () {
            var p = popup("#/wow/edit", {
                path: page.$scope.pathlist,
                name: e || ''
            });
            on('submited')(p, function () {
                page.$scope.open();
                remove(p);
            });
        })

    };
    contextmenu(page, [
        {
            name: "新建文件夹",
            when: e => !getActive(e),
            do() {
                popupEdit();
            }
        },
        {
            name: '编辑',
            when,
            do(e) {
                popupEdit(e.$scope.d.name);
            }
        },
        {
            get name() {
                return this.confirm ? "确认删除" : "删除";
            },
            confirm: false,
            when(e) {
                this.confirm = false;
                return when(e);
            },
            type: "danger",
            async do(e) {
                if (!this.confirm) {
                    this.confirm = true;
                    setTimeout(_ => {
                        this.confirm = false;
                        render.refresh();
                    }, 2000);
                    return false;
                }
                await data.from("folder", { opt: 'del', path: "/" + page.$scope.pathlist.concat(e.$scope.d.name).join("/") }).loading_promise;
                page.$scope.open();
            }
        }
    ]);
    return page;
}<commit_msg>刷新时保持刷新前的路径<commit_after>var fields = refilm`
文件
`;

function main() {
    var page = div();
    page.innerHTML = root;
    page.onback = function () {
        var $scope = this.$scope;
        if (!$scope.pathlist.length) {
            return;
        }
        data.setInstance("pathlist", $scope.pathlist.slice(0, -1));
        $scope.open();
        return false;
    }
    page.setAttribute('ng-mousedown', 'setActive')

    renderWithDefaults(page, {
        lattice,
        pathlist: data.getInstance("pathlist"),
        active: null,
        open(p) {
            if (p) p = String(p.name || '').replace(/\/$/, '');
            if (p) data.setInstance("pathlist", this.pathlist.concat(p));
            this.data = data.from("folder", { opt: 'list', path: "/" + this.pathlist.join('/') }, files => {
                if (files) return sortname(files).map(f => {
                    return {
                        name: f,
                        type: /\/$/.test(f) ? 'folder' : 'file'
                    }
                });
            });
        },
        setActive(e) {
            this.active = getActive(e);
        },
        data: [],
    });
    page.$scope.open();
    var getActive = e => {
        var p = page.querySelector('lattice');
        var t = getTargetIn(e => e.parentNode && e.parentNode.parentNode === p, e.target);
        return t;
    };
    var when = e => !!getActive(e);
    var popupEdit = function (e) {
        zimoli.prepare('/wow/edit', function () {
            var p = popup("#/wow/edit", {
                path: page.$scope.pathlist,
                name: e || ''
            });
            on('submited')(p, function () {
                page.$scope.open();
                remove(p);
            });
        })

    };
    contextmenu(page, [
        {
            name: "新建文件夹",
            when: e => !getActive(e),
            do() {
                popupEdit();
            }
        },
        {
            name: '编辑',
            when,
            do(e) {
                popupEdit(e.$scope.d.name);
            }
        },
        {
            get name() {
                return this.confirm ? "确认删除" : "删除";
            },
            confirm: false,
            when(e) {
                this.confirm = false;
                return when(e);
            },
            type: "danger",
            async do(e) {
                if (!this.confirm) {
                    this.confirm = true;
                    setTimeout(_ => {
                        this.confirm = false;
                        render.refresh();
                    }, 2000);
                    return false;
                }
                await data.from("folder", { opt: 'del', path: "/" + page.$scope.pathlist.concat(e.$scope.d.name).join("/") }).loading_promise;
                page.$scope.open();
            }
        }
    ]);
    return page;
}<|endoftext|>


<commit_before>/*
 * Copyright (C) 2012-2014 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Ro Tercera component
 * @author Roy Braam
 */
Ext.define ("viewer.components.rotercera.RoComment",{
    extend: "viewer.components.Edit",

    window: null,
    planId: null,
    config: {
        planIdAttributeName : "BESTEMMINGSPLANGEBIEDID",
        publicAttributeName:  "OPENBAAR",
        ownerAttributeName: "EIGENAAR",
        component: null
    },
    constructor: function(conf,component){
        conf.isPopup=true;
        conf.component=component;
        this.initConfig(conf);
        viewer.components.Edit.superclass.constructor.call(this, conf);
        var div = this.getContentDiv();
        this.loadWindow();
    },

    createLayerSelector: function(){
        var me = this;
        //dummy layer selector
        this.layerSelector= {
            initLayers: function(){
            },getValue: function(){
                if (me.layers){
                    return me.viewerController.getAppLayerById(me.layers[0]);
                }else{
                    return null;
                }
            },combobox: {
                select: function(){}
            },getSelectedAppLayer: function(){
                if (me.layers){
                    return me.viewerController.getAppLayerById(me.layers[0]);
                }else{
                    return null;
                }
            }
        };
    },
    newComment: function (planId){
        this.startComment(planId,this.createNew);
        Ext.getCmp(this.name + "CommentDeleteButton").hide();
    },
    editComment: function(planId,feature){
        this.startComment(planId,function(){
            //if scope ommited: the scope is the component
            this.planId=planId;
            this.mode = "edit";
            this.handleFeature(feature);
            Ext.getCmp(this.name + "CommentDeleteButton").show();
        });
    },
    startComment: function(planId,afterLoadAttributes){
        this.planId=planId;
        if (this.vectorLayer==null){
            this.createVectorLayer();
        }
        if (this.window==null){
            this.createInputWindow();
        }
        this.layerChanged(this.layerSelector.getValue(),null,null,afterLoadAttributes);
        this.window.show();
    },

    createNew : function(){
        this.vectorLayer.removeAllFeatures();
        this.viewerController.mapComponent.getMap().removeMarker("edit");
        this.mode = "new";
        if(this.newGeomType != null && this.geometryEditable){
            this.vectorLayer.drawFeature(this.newGeomType);
        }
        Ext.getCmp(this.name + "CommentDeleteButton").hide();
    },

    createInputWindow: function(){
        var me = this;
        this.inputContainer = Ext.create("Ext.form.Panel",{
            id: this.name + 'CommentInputPanel',
            border: 0,
            autoScroll: true,
            flex: 1
        });
        this.window = Ext.create("Ext.window.Window",{
            title: "Ro-Commentaar",
            height: 350,
            width: 290,
            closeAction: 'hide',
            listeners:{
                hide:{
                    scope:this,
                    fn: function(){
                        this.vectorLayer.stopDrawing();
                    }
                }
            },
            resizable: false,
            layout: {
                type: "vbox",
                align: 'stretch',
                pack: 'start'
            },
            items: [
                this.inputContainer,
                {
                    id: this.name + 'CommentSavePanel',
                    xtype: "container",
                    height: MobileManager.isMobile() ? 45 : 30,
                    layout: {
                        type: 'hbox',
                        pack: 'end'
                    },
                    defaults: {
                        xtype: 'button',
                        componentCls: 'mobileLarge'
                    },
                    items:[
                    {
                        id : this.name + "CommentCancelButton",
                        tooltip: "Annuleren",
                        text: "Annuleren",
                        listeners: {
                            click:{
                                scope: me,
                                fn: me.cancel
                            }
                        }
                    },
                    {
                        id : this.name + "CommentSaveButton",
                        tooltip: "Opslaan",
                        text: "Opslaan",
                        listeners: {
                            click:{
                                scope: me,
                                fn: function(){
                                    if(this.vectorLayer.getActiveFeature() !== null){
                                        Ext.getCmp(this.name + "CommentSaveButton").disable();
                                        me.save();
                                    }else{
                                         Ext.MessageBox.alert('Foutmelding', "Commentaar niet compleet: geometrie mist.");
                                    }
                                }
                            }
                        }
                    },
                    {
                        id : this.name + "CommentDeleteButton",
                        tooltip: "Verwijder",
                        text: "Verwijder",
                        listeners: {
                            click:{
                                scope: me,
                                fn: me.remove
                            }
                        }
                    }
                    ]
                }
            ]
        });
    },

    /**
     * @override
     */
    cancel: function (){
        this.callParent(arguments);
        if (this.window){
            this.window.hide();
        }
        this.vectorLayer.stopDrawing();
    },
    changeFeatureBeforeSave: function(feature){
        if (this.planId ==null || this.planId == undefined){
            throw "Geen plan geselecteerd";
        }
        if (user==null){
            throw "Er is niet ingelogd. Er kan geen commentaar worden aangemaakt";
        }
        feature[this.config.planIdAttributeName]=this.planId;
        //add user
        feature[this.config.ownerAttributeName] = user.name;
        return feature;
    },
    /**
     * @override
     */
    saveSucces  : function(fid){
        Ext.getCmp(this.name + "saveButton").enable();
        this.config.component.roAllComment.reload();
        this.callParent(arguments);
        Ext.getCmp(this.name + "CommentDeleteButton").show();
    },
    /**
     * @override
     */
    saveFailed : function(fid){
        Ext.getCmp(this.name + "CommentSaveButton").enable();
        this.callParent(arguments);
    },
    /**
     * @override
     */
    deleteSucces: function(){
        this.config.component.roAllComment.reload();
        this.callParent(arguments);
    },
    /**
     * @override
     */
    allowedEditable: function(attribute){
        if (attribute.name === this.config.ownerAttributeName){
            return false;
        }else{
            return true;
        }
    }

});<commit_msg>Always enable save button on opening window<commit_after>/*
 * Copyright (C) 2012-2014 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * Ro Tercera component
 * @author Roy Braam
 */
Ext.define ("viewer.components.rotercera.RoComment",{
    extend: "viewer.components.Edit",

    window: null,
    planId: null,
    config: {
        planIdAttributeName : "BESTEMMINGSPLANGEBIEDID",
        publicAttributeName:  "OPENBAAR",
        ownerAttributeName: "EIGENAAR",
        component: null
    },
    constructor: function(conf,component){
        conf.isPopup=true;
        conf.component=component;
        this.initConfig(conf);
        viewer.components.Edit.superclass.constructor.call(this, conf);
        var div = this.getContentDiv();
        this.loadWindow();
    },

    createLayerSelector: function(){
        var me = this;
        //dummy layer selector
        this.layerSelector= {
            initLayers: function(){
            },getValue: function(){
                if (me.layers){
                    return me.viewerController.getAppLayerById(me.layers[0]);
                }else{
                    return null;
                }
            },combobox: {
                select: function(){}
            },getSelectedAppLayer: function(){
                if (me.layers){
                    return me.viewerController.getAppLayerById(me.layers[0]);
                }else{
                    return null;
                }
            }
        };
    },
    newComment: function (planId){
        this.startComment(planId,this.createNew);
        Ext.getCmp(this.name + "CommentDeleteButton").hide();
    },
    editComment: function(planId,feature){
        this.startComment(planId,function(){
            //if scope ommited: the scope is the component
            this.planId=planId;
            this.mode = "edit";
            this.handleFeature(feature);
            Ext.getCmp(this.name + "CommentDeleteButton").show();
        });
    },
    startComment: function(planId,afterLoadAttributes){
        this.planId=planId;
        if (this.vectorLayer==null){
            this.createVectorLayer();
        }
        if (this.window==null){
            this.createInputWindow();
        }
        this.layerChanged(this.layerSelector.getValue(),null,null,afterLoadAttributes);
        Ext.getCmp(this.name + "CommentSaveButton").enable();
        this.window.show();
    },

    createNew : function(){
        this.vectorLayer.removeAllFeatures();
        this.viewerController.mapComponent.getMap().removeMarker("edit");
        this.mode = "new";
        if(this.newGeomType != null && this.geometryEditable){
            this.vectorLayer.drawFeature(this.newGeomType);
        }
        Ext.getCmp(this.name + "CommentDeleteButton").hide();
    },

    createInputWindow: function(){
        var me = this;
        this.inputContainer = Ext.create("Ext.form.Panel",{
            id: this.name + 'CommentInputPanel',
            border: 0,
            autoScroll: true,
            flex: 1
        });
        this.window = Ext.create("Ext.window.Window",{
            title: "Ro-Commentaar",
            height: 350,
            width: 290,
            closeAction: 'hide',
            listeners:{
                hide:{
                    scope:this,
                    fn: function(){
                        this.vectorLayer.stopDrawing();
                    }
                }
            },
            resizable: false,
            layout: {
                type: "vbox",
                align: 'stretch',
                pack: 'start'
            },
            items: [
                this.inputContainer,
                {
                    id: this.name + 'CommentSavePanel',
                    xtype: "container",
                    height: MobileManager.isMobile() ? 45 : 30,
                    layout: {
                        type: 'hbox',
                        pack: 'end'
                    },
                    defaults: {
                        xtype: 'button',
                        componentCls: 'mobileLarge'
                    },
                    items:[
                    {
                        id : this.name + "CommentCancelButton",
                        tooltip: "Annuleren",
                        text: "Annuleren",
                        listeners: {
                            click:{
                                scope: me,
                                fn: me.cancel
                            }
                        }
                    },
                    {
                        id : this.name + "CommentSaveButton",
                        tooltip: "Opslaan",
                        text: "Opslaan",
                        listeners: {
                            click:{
                                scope: me,
                                fn: function(){
                                    if(this.vectorLayer.getActiveFeature() !== null){
                                        Ext.getCmp(this.name + "CommentSaveButton").disable();
                                        me.save();
                                    }else{
                                         Ext.MessageBox.alert('Foutmelding', "Commentaar niet compleet: geometrie mist.");
                                    }
                                }
                            }
                        }
                    },
                    {
                        id : this.name + "CommentDeleteButton",
                        tooltip: "Verwijder",
                        text: "Verwijder",
                        listeners: {
                            click:{
                                scope: me,
                                fn: me.remove
                            }
                        }
                    }
                    ]
                }
            ]
        });
    },

    /**
     * @override
     */
    cancel: function (){
        this.callParent(arguments);
        if (this.window){
            this.window.hide();
        }
        this.vectorLayer.stopDrawing();
    },
    changeFeatureBeforeSave: function(feature){
        if (this.planId ==null || this.planId == undefined){
            throw "Geen plan geselecteerd";
        }
        if (user==null){
            throw "Er is niet ingelogd. Er kan geen commentaar worden aangemaakt";
        }
        feature[this.config.planIdAttributeName]=this.planId;
        //add user
        feature[this.config.ownerAttributeName] = user.name;
        return feature;
    },
    /**
     * @override
     */
    saveSucces  : function(fid){
        Ext.getCmp(this.name + "saveButton").enable();
        this.config.component.roAllComment.reload();
        this.callParent(arguments);
        Ext.getCmp(this.name + "CommentDeleteButton").show();
    },
    /**
     * @override
     */
    saveFailed : function(fid){
        Ext.getCmp(this.name + "CommentSaveButton").enable();
        this.callParent(arguments);
    },
    /**
     * @override
     */
    deleteSucces: function(){
        this.config.component.roAllComment.reload();
        this.callParent(arguments);
    },
    /**
     * @override
     */
    allowedEditable: function(attribute){
        if (attribute.name === this.config.ownerAttributeName){
            return false;
        }else{
            return true;
        }
    }

});<|endoftext|>


<commit_before>// ==========================================================================
// Project:   xTuple Postbooks - Business Management System Framework
// Copyright: ©2011 OpenMFG LLC, d/b/a xTuple
// ==========================================================================
/*globals Postbooks XM sc_assert */

sc_require('views/carousel');
sc_require('views/tile_view');

var base03 =   "#002b36";
var base02 =   "#073642";
var base01 =   "#586e75";
var base00 =   "#657b83";
var base0 =    "#839496";
var base1 =    "#93a1a1";
var base2 =    "#eee8d5";
var base3 =    "#fdf6e3";
var yellow =   "#b58900";
var orange =   "#cb4b16";
var red =      "#dc322f";
var magenta =  "#d33682";
var violet =   "#6c71c4";
var blue =     "#268bd2";
var cyan =     "#2aa198";
var green =    "#859900";
var white =    "white";

Postbooks.TilesForClass = function(klass, controller, isRoot) {
  console.log('Postbooks.TilesForClass(', klass, ')');

  var tiles = [],
      proto = klass.prototype;

  // see if there is a function for this specific class
  if (Postbooks[klass] && Postbooks[klass].tiles) {
    tiles = Postbooks[klass].tiles(controller, isRoot);

  // otherwise generate automatically
  } else {
    tiles.push(Postbooks.CreateTileViewForClass(klass, controller, undefined, true, isRoot));

    for (var key in proto) {
      if (key === 'guid') continue;
      if (key === 'type') continue;
      if (key === 'dataState') continue;

      var property = proto[key];

      if (property && (property.isChildrenAttribute || property.isManyAttribute)) {
        continue;

      } else if (property && (property.isChildAttribute || property.isSingleAttribute)) {
        var objectKlass = property.get('typeClass');

        var objectController = SC.ObjectController.create({
          contentBinding: SC.Binding.from(key, controller).single().oneWay()
        });

        tiles.push(Postbooks.CreateTileViewForClass(objectKlass, objectController, property.label));
      } else if (key === 'customTileViews') {
        property.forEach(function(viewName) {
          var view = SC.objectForPropertyPath(viewName);
          if (view) {
            tiles.push(view.CreateTileView(controller));
          } else { SC.Logger.warn("Could not find view for class %@".fmt(viewName)); }
        });
      }
    }
  }

  return tiles;
};

/** Builds an SC.View subclass from all attributes that can edit properties of the record class. */
Postbooks.CreateTileViewForClass = function(klass, controller, title, isOverview, isRoot) {
  console.log('Postbooks.CreateTileViewForClass(', klass, title, isOverview, ')');

  // See if we have an override.
  if (klass.CreateTileView) {
    return klass.CreateTileView(controller, title, isOverview);
  }

  // Nope, generate the default tile view on the fly.
  var proto = klass.prototype, properties = [], commands = [];

  if (isOverview && isRoot) {
    commands = [{
      title: "\u2699",
      value: null,
      enabled: true
    }, {
      title: "Delete",
      value: 'delete',
      enabled: true
    }];

    for (var key in klass) {
      var property = klass[key];
      if (typeof property === 'function' && property.isCommand) {
        commands.push({
          title: property.commandName || "(no name)",
          value: property,
          enabled: true
        });
      } else if (typeof property === 'object' && property.isCommand && property.call && typeof property.call === 'function') {
        commands.push({
          title: property.commandName || "(no name)",
          value: property,
          enabled: true
        });
      }
    }
  }

  for (key in proto) {
   if (key === 'guid') continue;
    if (key === 'type') continue;
    if (key === 'dataState') continue;

    var property = proto[key];

    if (property && (property.isChildrenAttribute || property.isManyAttribute)) {
      continue;
    } else if (property && (property.isChildAttribute || property.isSingleAttribute)) {
      continue;
    } else if (property && property.isRecordAttribute) {
      if (property.isChildrenAttribute)    continue;
      else if (property.isChildAttribute)  continue;
      else if (property.isManyAttribute)   continue;
      else if (property.isSingleAttribute) continue;

      properties.push(key);
    }
  }

  view = Postbooks.CreateTileView(klass, controller, title, properties, commands, isOverview);

  return view;
};

/** Builds an SC.View subclass from a specific property list that can edit them the record class. */
Postbooks.CreateTileView = function(klass, controller, title, properties, commands, isOverview) {
  console.log('Postbooks.CreateTileView(', klass, controller, title, properties, commands, isOverview, ')');

  title = title? title : "_overview".loc();
  var view = Postbooks.TileView.create({
    title: title,
    mouseDown: function(evt) {
      SC.EndEditingTextLayer();

      if (!isOverview) {
        Postbooks.LoadModal(title, "_back".loc(), controller.get('content'));
      }

      return true;
    }
  }),
  layers = view.get('layers'),
  y = 42,
  proto = klass.prototype,
  K = Postbooks;

  if (commands && commands.get('length')) {
    layers.pushObject(SC.SelectWidget.create({
      layout: { top: 7, right: 10, width: 60, height: 24 },
      theme: 'regular',
      items: commands,
      value: null,
      itemTitleKey: 'title',
      itemValueKey: 'value',
      itemIsEnabledKey: 'enabled',

      valueDidChange: function() {
        var value = this.get('value');
        if (value === 'delete') {
          Postbooks.statechart.sendAction('deleteRecord');
        } else {
          alert('FIXME: Execute command!');
        }
      }.observes('value')
    }));
  }

  properties.forEach(function(key) {
    if (key === 'spacer') {
      y += 12;
    } else {
      var property = proto[key],
          left = 120, right = 12,
          label = null, widget = null;

      if (property.isRecordAttribute) {
        var typeClass = property.get('typeClass');

        if (typeClass === String) {
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: property.label + ':'
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (property.isSingleAttribute) { // just for now so we can see layout impact
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: property.label + ':'
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return String(val);
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (property.isChildrenAttribute) { // just for now so we can see layout impact
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: property.label + ':'
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return String(val);
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass === Number) {
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: property.label + ':'
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return String(val);
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass.isNumeric) {
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: property.label + ':'
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return val? val.toLocaleString() : "";
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass === XT.DateTime) {
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: property.label + ':'
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return val? val.toLocaleDateString() : "no date set";
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass === Boolean) {
          widget = SC.CheckboxWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            title: property.label,
            valueBinding: SC.Binding.transform(function(val) {
              return !!val;
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass === Array) {
          console.log('Unknown property type', 'Array');
        } else if (typeClass === Object) {
          console.log('Unknown property type', 'Object');
        } else {
          console.log('Unknown property type', typeClass.displayName? typeClass.displayName : typeClass);
        }
      }

      if (label)  layers.pushObject(label);
      if (widget) layers.pushObject(widget);
    }
  });

  return view;
};

Postbooks.DefaultListRenderRow = function(context, width, height, index, object, isSelected) {
  console.log('Postbooks.DefaultListRenderRow()');

  context.fillStyle = isSelected? '#99CCFF' : 'white';
  context.fillRect(0, 0, width, height);

  context.strokeStyle = 'grey';
  context.lineWidth = 1;

  context.beginPath();
  context.moveTo(0, height - 0.5);
  context.lineTo(width, height - 0.5);
  context.stroke();

  var K = Postbooks;
  context.font = "12pt "+K.TYPEFACE;
  context.fillStyle = 'black';
  context.textAlign = 'center';
  context.textBaseline = 'middle';

  context.fillText(object.get('guid') + ': ' + (object.get('name') || object.get('description') || object.get('number')), width/2, height/2);
};

Postbooks.CreateListViewForClass = function(klass, controller) {
  console.log('Postbooks.CreateListViewForClass(', klass, ')');

  // See if we have an override.
  if (klass.CreateDetailListView) {
    return klass.CreateDetailListView(controller);
  }

  // Nope, generate the default tile view on the fly.
  var list = SC.ListView.create({
    layout: { top: 13, left: 0, right: 0, bottom: 0 },
    rowHeight: klass.ListRowHeight !== undefined? klass.ListRowHeight : 60,
    hasHorizontalScroller: false,

    contentBinding: SC.Binding.from('arrangedObjects', controller).oneWay(),
    selectionBinding: SC.Binding.from('selection', controller),

    baseClass: klass,

    action: function(object, index) {
      var that = this;
      var instance = this.get('content').objectAt(index);
      if (instance) {
        Postbooks.LoadModal(klass.prototype.className.slice(3), "Back", instance);

        // Deselect our row after the modal transition ends.
        setTimeout(function() {
          SC.RunLoop.begin();
          that.get('content').deselectObject(instance);
          SC.RunLoop.end();
        }, 250);
      }
    },

    willRenderLayers: function(ctx) {
      var content = this.get('content');

      if (content && content.get('length') === 0) {
        var w = ctx.width, h = ctx.height;

        var text = 'No records.',
            status = content? content.get('status') : null;

        if (status && status === SC.Record.BUSY_LOADING) {
          text = "_loading".loc();
        }

        // Clear background.
        ctx.fillStyle = base3;
        ctx.fillRect(0, 0, w, h);

        // Draw view name.
        ctx.fillStyle = base03;

        var K = Postbooks;
        ctx.font = "11pt "+K.TYPEFACE;
        ctx.textBaseline = "middle";
        ctx.textAlign = "center";
        ctx.fillText(text, w/2, h/2);
      } else {
        ctx.fillStyle = base3;
        ctx.fillRect(0, 0, ctx.width, ctx.height);
      }
    },

    renderRow: klass.RenderDetailListRow? klass.RenderDetailListRow : Postbooks.DefaultListRenderRow

  });

  return list;
};
<commit_msg>determine label name from property.<commit_after>// ==========================================================================
// Project:   xTuple Postbooks - Business Management System Framework
// Copyright: ©2011 OpenMFG LLC, d/b/a xTuple
// ==========================================================================
/*globals Postbooks XM sc_assert */

sc_require('views/carousel');
sc_require('views/tile_view');

var base03 =   "#002b36";
var base02 =   "#073642";
var base01 =   "#586e75";
var base00 =   "#657b83";
var base0 =    "#839496";
var base1 =    "#93a1a1";
var base2 =    "#eee8d5";
var base3 =    "#fdf6e3";
var yellow =   "#b58900";
var orange =   "#cb4b16";
var red =      "#dc322f";
var magenta =  "#d33682";
var violet =   "#6c71c4";
var blue =     "#268bd2";
var cyan =     "#2aa198";
var green =    "#859900";
var white =    "white";

Postbooks.TilesForClass = function(klass, controller, isRoot) {
  console.log('Postbooks.TilesForClass(', klass, ')');

  var tiles = [],
      proto = klass.prototype;

  // see if there is a function for this specific class
  if (Postbooks[klass] && Postbooks[klass].tiles) {
    tiles = Postbooks[klass].tiles(controller, isRoot);

  // otherwise generate automatically
  } else {
    tiles.push(Postbooks.CreateTileViewForClass(klass, controller, undefined, true, isRoot));

    for (var key in proto) {
      if (key === 'guid') continue;
      if (key === 'type') continue;
      if (key === 'dataState') continue;

      var property = proto[key];

      if (property && (property.isChildrenAttribute || property.isManyAttribute)) {
        continue;

      } else if (property && (property.isChildAttribute || property.isSingleAttribute)) {
        var objectKlass = property.get('typeClass');

        var objectController = SC.ObjectController.create({
          contentBinding: SC.Binding.from(key, controller).single().oneWay()
        });

        tiles.push(Postbooks.CreateTileViewForClass(objectKlass, objectController, property.label));
      } else if (key === 'customTileViews') {
        property.forEach(function(viewName) {
          var view = SC.objectForPropertyPath(viewName);
          if (view) {
            tiles.push(view.CreateTileView(controller));
          } else { SC.Logger.warn("Could not find view for class %@".fmt(viewName)); }
        });
      }
    }
  }

  return tiles;
};

/** Builds an SC.View subclass from all attributes that can edit properties of the record class. */
Postbooks.CreateTileViewForClass = function(klass, controller, title, isOverview, isRoot) {
  console.log('Postbooks.CreateTileViewForClass(', klass, title, isOverview, ')');

  // See if we have an override.
  if (klass.CreateTileView) {
    return klass.CreateTileView(controller, title, isOverview);
  }

  // Nope, generate the default tile view on the fly.
  var proto = klass.prototype, properties = [], commands = [];

  if (isOverview && isRoot) {
    commands = [{
      title: "\u2699",
      value: null,
      enabled: true
    }, {
      title: "Delete",
      value: 'delete',
      enabled: true
    }];

    for (var key in klass) {
      var property = klass[key];
      if (typeof property === 'function' && property.isCommand) {
        commands.push({
          title: property.commandName || "(no name)",
          value: property,
          enabled: true
        });
      } else if (typeof property === 'object' && property.isCommand && property.call && typeof property.call === 'function') {
        commands.push({
          title: property.commandName || "(no name)",
          value: property,
          enabled: true
        });
      }
    }
  }

  for (key in proto) {
   if (key === 'guid') continue;
    if (key === 'type') continue;
    if (key === 'dataState') continue;

    var property = proto[key];

    if (property && (property.isChildrenAttribute || property.isManyAttribute)) {
      continue;
    } else if (property && (property.isChildAttribute || property.isSingleAttribute)) {
      continue;
    } else if (property && property.isRecordAttribute) {
      if (property.isChildrenAttribute)    continue;
      else if (property.isChildAttribute)  continue;
      else if (property.isManyAttribute)   continue;
      else if (property.isSingleAttribute) continue;

      properties.push(key);
    }
  }

  view = Postbooks.CreateTileView(klass, controller, title, properties, commands, isOverview);

  return view;
};

/** Builds an SC.View subclass from a specific property list that can edit them the record class. */
Postbooks.CreateTileView = function(klass, controller, title, properties, commands, isOverview) {
  console.log('Postbooks.CreateTileView(', klass, controller, title, properties, commands, isOverview, ')');

  title = title? title : "_overview".loc();
  var view = Postbooks.TileView.create({
    title: title,
    mouseDown: function(evt) {
      SC.EndEditingTextLayer();

      if (!isOverview) {
        Postbooks.LoadModal(title, "_back".loc(), controller.get('content'));
      }

      return true;
    }
  }),
  layers = view.get('layers'),
  y = 42,
  proto = klass.prototype,
  K = Postbooks;

  if (commands && commands.get('length')) {
    layers.pushObject(SC.SelectWidget.create({
      layout: { top: 7, right: 10, width: 60, height: 24 },
      theme: 'regular',
      items: commands,
      value: null,
      itemTitleKey: 'title',
      itemValueKey: 'value',
      itemIsEnabledKey: 'enabled',

      valueDidChange: function() {
        var value = this.get('value');
        if (value === 'delete') {
          Postbooks.statechart.sendAction('deleteRecord');
        } else {
          alert('FIXME: Execute command!');
        }
      }.observes('value')
    }));
  }

  properties.forEach(function(key) {
    if (key === 'spacer') {
      y += 12;
    } else {
      var property = proto[key],
          left = 120, right = 12,
          label = null, widget = null,
          title = (("_"+key).loc())+":";

      if (property.isRecordAttribute) {
        var typeClass = property.get('typeClass');

        if (typeClass === String) {
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: title
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (property.isSingleAttribute) { // just for now so we can see layout impact
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: title
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return String(val);
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (property.isChildrenAttribute) { // just for now so we can see layout impact
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: title
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return String(val);
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass === Number) {
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: title
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return String(val);
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass.isNumeric) {
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: title
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return val? val.toLocaleString() : "";
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass === XT.DateTime) {
          label = SC.LabelLayer.create({
            layout: { top: y + 4, left: 12, height: 24, width: left - 18 },
            backgroundColor: 'white',
            textAlign: 'right',
            value: title
          });
          widget = SC.TextFieldWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            valueBinding: SC.Binding.transform(function(val) {
              return val? val.toLocaleDateString() : "no date set";
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass === Boolean) {
          widget = SC.CheckboxWidget.create({
            layout: { top: y, left: left, height: 24, right: right },
            title: property.label,
            valueBinding: SC.Binding.transform(function(val) {
              return !!val;
            }).from(key, controller)
          });
          y += 24 + K.SPACING;
        } else if (typeClass === Array) {
          console.log('Unknown property type', 'Array');
        } else if (typeClass === Object) {
          console.log('Unknown property type', 'Object');
        } else {
          console.log('Unknown property type', typeClass.displayName? typeClass.displayName : typeClass);
        }
      }

      if (label)  layers.pushObject(label);
      if (widget) layers.pushObject(widget);
    }
  });

  return view;
};

Postbooks.DefaultListRenderRow = function(context, width, height, index, object, isSelected) {
  console.log('Postbooks.DefaultListRenderRow()');

  context.fillStyle = isSelected? '#99CCFF' : 'white';
  context.fillRect(0, 0, width, height);

  context.strokeStyle = 'grey';
  context.lineWidth = 1;

  context.beginPath();
  context.moveTo(0, height - 0.5);
  context.lineTo(width, height - 0.5);
  context.stroke();

  var K = Postbooks;
  context.font = "12pt "+K.TYPEFACE;
  context.fillStyle = 'black';
  context.textAlign = 'center';
  context.textBaseline = 'middle';

  context.fillText(object.get('guid') + ': ' + (object.get('name') || object.get('description') || object.get('number')), width/2, height/2);
};

Postbooks.CreateListViewForClass = function(klass, controller) {
  console.log('Postbooks.CreateListViewForClass(', klass, ')');

  // See if we have an override.
  var className = klass.prototype.className;
  className = className.slice(className.indexOf('.') + 1); // drop name space
  if (Postbooks[className] && Postbooks[className].RecordListView) {
  debugger
    return Postbooks[className].RecordListView(controller);
  }

  // Nope, generate the default tile view on the fly.
  var list = SC.ListView.create({
    layout: { top: 13, left: 0, right: 0, bottom: 0 },
    rowHeight: klass.ListRowHeight !== undefined? klass.ListRowHeight : 60,
    hasHorizontalScroller: false,

    contentBinding: SC.Binding.from('arrangedObjects', controller).oneWay(),
    selectionBinding: SC.Binding.from('selection', controller),

    baseClass: klass,

    action: function(object, index) {
      var that = this;
      var instance = this.get('content').objectAt(index);
      if (instance) {
        Postbooks.LoadModal(klass.prototype.className.slice(3), "Back", instance);

        // Deselect our row after the modal transition ends.
        setTimeout(function() {
          SC.RunLoop.begin();
          that.get('content').deselectObject(instance);
          SC.RunLoop.end();
        }, 250);
      }
    },

    willRenderLayers: function(ctx) {
      var content = this.get('content');

      if (content && content.get('length') === 0) {
        var w = ctx.width, h = ctx.height;

        var text = 'No records.',
            status = content? content.get('status') : null;

        if (status && status === SC.Record.BUSY_LOADING) {
          text = "_loading".loc();
        }

        // Clear background.
        ctx.fillStyle = base3;
        ctx.fillRect(0, 0, w, h);

        // Draw view name.
        ctx.fillStyle = base03;

        var K = Postbooks;
        ctx.font = "11pt "+K.TYPEFACE;
        ctx.textBaseline = "middle";
        ctx.textAlign = "center";
        ctx.fillText(text, w/2, h/2);
      } else {
        ctx.fillStyle = base3;
        ctx.fillRect(0, 0, ctx.width, ctx.height);
      }
    },

    renderRow: klass.RenderDetailListRow? klass.RenderDetailListRow : Postbooks.DefaultListRenderRow

  });

  return list;
};
<|endoftext|>