<commit_before>'use strict';

import express from 'express';
import createError from 'http-errors';
import OAuth2Server from 'oauth2-server';
import bodyParser from 'body-parser';
import basicAuth from 'basic-auth';
import redis from 'redis';
import moment from 'moment';
import _ from 'lodash';
import {log} from './utils';
import Model from './oauth/twolevel.model.js';
// import throttle from './throttle/throttle.middleware.js';
import {userEncode, userDecode} from './utils';

function createBasicApp(config) {
  var app = express();
  app.set('config', config);

  var storePasswordsInRedisOptions = (app.get('config').whoCaresAboutSecurityAnyway || {}).storePasswordsInRedis;
  if (storePasswordsInRedisOptions) {
    app.set('storePasswordsInRedisClient', redis.createClient(storePasswordsInRedisOptions));
  }

  app.disable('x-powered-by');
  app.set('json spaces', 2);
  app.enable('trust proxy');

  app.use((req, res, next) => {
    var timeStart = moment();
    res.logData = {};

    res.on('finish', () => {
      var timeEnd = moment();
      log.info(null, Object.assign(res.logData || {},
        {
          type: 'accessLog',
          request: {method: req.method, path: req.path, hostname: req.hostname, remoteAddress: req.ip},
          response: {status: res.statusCode},
          time: {start: timeStart, end: timeEnd, taken: timeEnd.diff(timeStart)}
        }));
    });

    next();
  });

  app.use(bodyParser.urlencoded({extended: true}));
  app.use(bodyParser.json());

  app.get('/', function (req, res) {
    res.send('Helpful text about Smaug.');
  });

  app.get('/health', (req, res) => {
    var result = {ok: {}};
    var stores = app.get('stores');

    var storePromises = Object.keys(stores).map((storeId) => {
      var tStart = moment();
      return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
        stores[storeId].ping()
          .then(() => {
            resolve({responseTime: moment().diff(tStart), result: 'ok'});
          })
          .catch((err) => {
            resolve({responseTime: moment().diff(tStart), result: err});
          });
      });
    });

    Promise.all(storePromises).then((results) => {
      _.zip(Object.keys(stores), results).forEach((zipElem) => {
        let [storeId, status] = zipElem;
        if (status.result instanceof Error) {
          if (typeof result.errors === 'undefined') {
            result.errors = {};
          }
          result.errors[storeId] = {name: status.result.name, msg: status.result.message, stacktrace: status.result.stack, responseTime: status.responseTime};
        }
        else {
          result.ok[storeId] = {responseTime: status.responseTime};
        }
      });
      if (Object.keys(result.errors || {}).length > 0) {
        res.status(500);
      }
      res.logData.health = result;
      res.json(result);
    });
  });

  return app;
}

export function createConfigurationApp(config) {
  var app = createBasicApp(config);

  app.get('/configuration', (req, res, next) => {
    var bearerToken = req.query.token;

    res.logData.token = bearerToken;

    app.get('stores').tokenStore.getAccessToken(bearerToken)
      .then((tokenInfo) => {
        var user = Object.assign(userDecode(tokenInfo.userId), {clientId: tokenInfo.clientId});
        user.agency = user.libraryId;
        var client = {id: tokenInfo.clientId};
        return app.get('stores').configStore.get(user, client)
          .then((userConfig) => {
            // merge user with existing config, to get hardcoded things like 'salt'
            user = Object.assign(userConfig.user || {}, user);
            userConfig.app = Object.assign(userConfig.app || {}, {clientId: tokenInfo.clientId});

            var storePasswordsInRedisClient = app.get('storePasswordsInRedisClient');
            if (typeof storePasswordsInRedisClient !== 'undefined') {
              storePasswordsInRedisClient.get(tokenInfo.userId, (redisErr, redisRes) => { // eslint-disable-line no-unused-vars
                if (redisErr) {
                  return next(createError(500, 'I\'m still a teapot', {wrappedError: redisErr}));
                }

                var insecureUser = Object.assign({}, user, {secret: redisRes, pin: redisRes});
                res.json(Object.assign({}, userConfig, {user: insecureUser}));
              });
            }
            else {
              // success
              res.json(Object.assign({}, userConfig, {user: user}));
            }
          })
          .catch((err) => {
            return next(createError(500, 'Error creating configuration', {wrappedError: err}));
          });
      })
      .catch((err) => {
        return next(createError(404, 'Token not found', {wrappedError: err}));
      });
  });

  // error handler
  app.use((err, req, res, next) => {
    log.error(err.message, {error: {message: err.message, stacktrace: err.stack}});
    next();
  });

  return app;
}

export function createOAuthApp(config = {}) {
  var app = createBasicApp(config);

  app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
    next();
  });

  app.oauth = OAuth2Server({
    model: new Model(app),
    grants: ['password'],
    debug: true,
    accessTokenLifetime: 60*60*24*30 // 30 days
  });

  // app.use(throttle());

  // Add implicit libraryId to anonymous user without libraryId, and change the password from accordingly.
  // The password must be equal to the username for an anonymous request, and userEncode(libraryId, null) returns the proper anonymous username/password for this
  app.use('/oauth/token', (req, res, next) => {
    if (req.body.username === userEncode(null, null)) {
      if (typeof config.defaultLibraryId === 'undefined') {
        log.error('No default library id. Set config.defaultLibraryId');
      }
      else {
        req.body.username += config.defaultLibraryId;
        if (req.body.password === userEncode(null, null)) {
          req.body.password += config.defaultLibraryId;
        }
      }
    }
    next();
  });
  app.post('/oauth/token', app.oauth.grant());
  app.use(app.oauth.errorHandler());

  return app;
}

export function createApp(config = {}) {
  var app = express();
  app.disable('x-powered-by');

  app.use(createConfigurationApp(config));
  app.use(createOAuthApp(config));

  return app;
}

export function filterClient(client) {
  var filteredClient = Object.assign({}, client);
  delete filteredClient.secret;
  return filteredClient; // eslint-disable-line no-undefined
}

export function filterClients(clients) {
  return clients.map(filterClient);
}

export function clientWithId(client, id) {
  return Object.assign({}, client, {id: id});
}

export function createAdminApp(config = {}) {
  var app = createBasicApp(config);
  app.set('config', config);
  app.use((req, res, next) => {
    var credentials = basicAuth(req) || {};
    if (_.every([typeof credentials.name === 'string', typeof credentials.pass === 'string'])) {
      var users = (app.get('config').admin || {}).users || {};
      if (users[credentials.name] === credentials.pass) {
        res.logData.user = credentials.name;
        return next();
      }
    }
    return res.sendStatus(403);
  });

  var clientEndpoint = express.Router();
  var configEndpoint = express.Router();

  clientEndpoint.use((req, res, next) => {
    next();
  });

  clientEndpoint.route('/')
    .get((req, res) => {
      // list clients
      app.get('stores').clientStore.getAll()
        .then(filterClients)
        .then((clients) => {
          res.json(clients);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .post((req, res) => {
      // create client
      var client = {
        name: req.body.name
      };

      app.get('stores').clientStore.create(client)
        .then(filterClient)
        .then((persistedClient) => {
          res.json(persistedClient);
        })
        .catch((err) => {
          res.json({err: err});
        });
    });

  clientEndpoint.route('/:clientId')
    .get((req, res) => {
      // get client
      app.get('stores').clientStore.get(req.params.clientId)
        .then(filterClient)
        .then((client) => {
          res.json(client);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .put((req, res) => {
      // update client
      var clientId = req.params.clientId;
      var client = {
        name: req.body.name
      };
      app.get('stores').clientStore.update(clientId, client)
        .then((persistedClient) => {
          res.json(persistedClient);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .delete((req, res) => {
      // delete client
      app.get('stores').clientStore.delete(req.params.clientId)
        .then(() => {
          res.json({});
        })
        .catch((err) => {
          res.json({err: err});
        });

    });

  configEndpoint.route('/')
    .get((req, res) => {
      res.json(app.get('config'));
    });

  app.use('/clients', clientEndpoint);
  app.use('/config', configEndpoint);
  return app;
}

export default createApp;
<commit_msg>log error when generating configuration fails<commit_after>'use strict';

import express from 'express';
import createError from 'http-errors';
import OAuth2Server from 'oauth2-server';
import bodyParser from 'body-parser';
import basicAuth from 'basic-auth';
import redis from 'redis';
import moment from 'moment';
import _ from 'lodash';
import {log} from './utils';
import Model from './oauth/twolevel.model.js';
// import throttle from './throttle/throttle.middleware.js';
import {userEncode, userDecode} from './utils';

function createBasicApp(config) {
  var app = express();
  app.set('config', config);

  var storePasswordsInRedisOptions = (app.get('config').whoCaresAboutSecurityAnyway || {}).storePasswordsInRedis;
  if (storePasswordsInRedisOptions) {
    app.set('storePasswordsInRedisClient', redis.createClient(storePasswordsInRedisOptions));
  }

  app.disable('x-powered-by');
  app.set('json spaces', 2);
  app.enable('trust proxy');

  app.use((req, res, next) => {
    var timeStart = moment();
    res.logData = {};

    res.on('finish', () => {
      var timeEnd = moment();
      log.info(null, Object.assign(res.logData || {},
        {
          type: 'accessLog',
          request: {method: req.method, path: req.path, hostname: req.hostname, remoteAddress: req.ip},
          response: {status: res.statusCode},
          time: {start: timeStart, end: timeEnd, taken: timeEnd.diff(timeStart)}
        }));
    });

    next();
  });

  app.use(bodyParser.urlencoded({extended: true}));
  app.use(bodyParser.json());

  app.get('/', function (req, res) {
    res.send('Helpful text about Smaug.');
  });

  app.get('/health', (req, res) => {
    var result = {ok: {}};
    var stores = app.get('stores');

    var storePromises = Object.keys(stores).map((storeId) => {
      var tStart = moment();
      return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars
        stores[storeId].ping()
          .then(() => {
            resolve({responseTime: moment().diff(tStart), result: 'ok'});
          })
          .catch((err) => {
            resolve({responseTime: moment().diff(tStart), result: err});
          });
      });
    });

    Promise.all(storePromises).then((results) => {
      _.zip(Object.keys(stores), results).forEach((zipElem) => {
        let [storeId, status] = zipElem;
        if (status.result instanceof Error) {
          if (typeof result.errors === 'undefined') {
            result.errors = {};
          }
          result.errors[storeId] = {name: status.result.name, msg: status.result.message, stacktrace: status.result.stack, responseTime: status.responseTime};
        }
        else {
          result.ok[storeId] = {responseTime: status.responseTime};
        }
      });
      if (Object.keys(result.errors || {}).length > 0) {
        res.status(500);
      }
      res.logData.health = result;
      res.json(result);
    });
  });

  return app;
}

export function createConfigurationApp(config) {
  var app = createBasicApp(config);

  app.get('/configuration', (req, res, next) => {
    var bearerToken = req.query.token;

    res.logData.token = bearerToken;

    app.get('stores').tokenStore.getAccessToken(bearerToken)
      .then((tokenInfo) => {
        var user = Object.assign(userDecode(tokenInfo.userId), {clientId: tokenInfo.clientId});
        user.agency = user.libraryId;
        var client = {id: tokenInfo.clientId};
        return app.get('stores').configStore.get(user, client)
          .then((userConfig) => {
            // merge user with existing config, to get hardcoded things like 'salt'
            user = Object.assign(userConfig.user || {}, user);
            userConfig.app = Object.assign(userConfig.app || {}, {clientId: tokenInfo.clientId});

            var storePasswordsInRedisClient = app.get('storePasswordsInRedisClient');
            if (typeof storePasswordsInRedisClient !== 'undefined') {
              storePasswordsInRedisClient.get(tokenInfo.userId, (redisErr, redisRes) => { // eslint-disable-line no-unused-vars
                if (redisErr) {
                  return next(createError(500, 'I\'m still a teapot', {wrappedError: redisErr}));
                }

                var insecureUser = Object.assign({}, user, {secret: redisRes, pin: redisRes});
                res.json(Object.assign({}, userConfig, {user: insecureUser}));
              });
            }
            else {
              // success
              res.json(Object.assign({}, userConfig, {user: user}));
            }
          })
          .catch((err) => {
            log.error('Error creating configuration', {error: {message: err.message, stacktrace: err.stack}});
            return next(createError(500, 'Error creating configuration', {wrappedError: err}));
          });
      })
      .catch((err) => {
        log.error('Error creating configuration', {error: {message: err.message, stacktrace: err.stack}});
        return next(createError(404, 'Token not found', {wrappedError: err}));
      });
  });

  // error handler
  app.use((err, req, res, next) => {
    log.error(err.message, {error: {message: err.message, stacktrace: err.stack}});
    next();
  });

  return app;
}

export function createOAuthApp(config = {}) {
  var app = createBasicApp(config);

  app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
    next();
  });

  app.oauth = OAuth2Server({
    model: new Model(app),
    grants: ['password'],
    debug: true,
    accessTokenLifetime: 60*60*24*30 // 30 days
  });

  // app.use(throttle());

  // Add implicit libraryId to anonymous user without libraryId, and change the password from accordingly.
  // The password must be equal to the username for an anonymous request, and userEncode(libraryId, null) returns the proper anonymous username/password for this
  app.use('/oauth/token', (req, res, next) => {
    if (req.body.username === userEncode(null, null)) {
      if (typeof config.defaultLibraryId === 'undefined') {
        log.error('No default library id. Set config.defaultLibraryId');
      }
      else {
        req.body.username += config.defaultLibraryId;
        if (req.body.password === userEncode(null, null)) {
          req.body.password += config.defaultLibraryId;
        }
      }
    }
    next();
  });
  app.post('/oauth/token', app.oauth.grant());
  app.use(app.oauth.errorHandler());

  return app;
}

export function createApp(config = {}) {
  var app = express();
  app.disable('x-powered-by');

  app.use(createConfigurationApp(config));
  app.use(createOAuthApp(config));

  return app;
}

export function filterClient(client) {
  var filteredClient = Object.assign({}, client);
  delete filteredClient.secret;
  return filteredClient; // eslint-disable-line no-undefined
}

export function filterClients(clients) {
  return clients.map(filterClient);
}

export function clientWithId(client, id) {
  return Object.assign({}, client, {id: id});
}

export function createAdminApp(config = {}) {
  var app = createBasicApp(config);
  app.set('config', config);
  app.use((req, res, next) => {
    var credentials = basicAuth(req) || {};
    if (_.every([typeof credentials.name === 'string', typeof credentials.pass === 'string'])) {
      var users = (app.get('config').admin || {}).users || {};
      if (users[credentials.name] === credentials.pass) {
        res.logData.user = credentials.name;
        return next();
      }
    }
    return res.sendStatus(403);
  });

  var clientEndpoint = express.Router();
  var configEndpoint = express.Router();

  clientEndpoint.use((req, res, next) => {
    next();
  });

  clientEndpoint.route('/')
    .get((req, res) => {
      // list clients
      app.get('stores').clientStore.getAll()
        .then(filterClients)
        .then((clients) => {
          res.json(clients);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .post((req, res) => {
      // create client
      var client = {
        name: req.body.name
      };

      app.get('stores').clientStore.create(client)
        .then(filterClient)
        .then((persistedClient) => {
          res.json(persistedClient);
        })
        .catch((err) => {
          res.json({err: err});
        });
    });

  clientEndpoint.route('/:clientId')
    .get((req, res) => {
      // get client
      app.get('stores').clientStore.get(req.params.clientId)
        .then(filterClient)
        .then((client) => {
          res.json(client);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .put((req, res) => {
      // update client
      var clientId = req.params.clientId;
      var client = {
        name: req.body.name
      };
      app.get('stores').clientStore.update(clientId, client)
        .then((persistedClient) => {
          res.json(persistedClient);
        })
        .catch((err) => {
          res.json({err: err});
        });
    })
    .delete((req, res) => {
      // delete client
      app.get('stores').clientStore.delete(req.params.clientId)
        .then(() => {
          res.json({});
        })
        .catch((err) => {
          res.json({err: err});
        });

    });

  configEndpoint.route('/')
    .get((req, res) => {
      res.json(app.get('config'));
    });

  app.use('/clients', clientEndpoint);
  app.use('/config', configEndpoint);
  return app;
}

export default createApp;
<|endoftext|>


<commit_before>import { Base } from 'yeoman-generator';
import { init, write, configure } from '../_helper';
import assign from 'deep-assign';

global.devjs = global.devjs || {};

class Gulp extends Base {
  initializing() { init.call(this, 'gulp'); }

  prompting() {
    const done = this.async();
    const prompts = [];

    if (devjs.babel) prompts.push({
      name: 'gulp_babel',
      message: 'Babel plugin for Gulp?',
      type: 'confirm',
      default: true,
    });

    if (devjs.eslint) prompts.push({
      name: 'gulp_eslint',
      message: 'ESLint plugin for Gulp?',
      type: 'confirm',
      default: true,
    });

    this.prompt(prompts, gulp => {
      assign(devjs, gulp);
      done();
    });
  }

  configuring() {
    const pack = this.fs.readJSON(this.destinationPath('package.json'), {});
    configure.call(this, {
      scripts: {
        build: 'gulp',
        prepublish: 'gulp',
      },
    });

    if (pack.scripts.test) {
      configure.call(this, {
        scripts: {
          test: 'gulp; ' + pack.scripts.test
        }
      });
    }
  }

  writing() {
    write.call(this, [devjs.babel ? 'gulpfile.babel.js' : 'gulpfile.js']);
  }

  install() {
    const deps = ['gulp'];

    if (devjs.babel) deps.push('gulp-babel', 'del');
    if (devjs.eslint) deps.push('gulp-eslint');

    this.npmInstall(deps, { saveDev: true });
  }
}

export default Gulp;
<commit_msg>Check pack.scripts before pack.scripts.test<commit_after>import { Base } from 'yeoman-generator';
import { init, write, configure } from '../_helper';
import assign from 'deep-assign';

global.devjs = global.devjs || {};

class Gulp extends Base {
  initializing() { init.call(this, 'gulp'); }

  prompting() {
    const done = this.async();
    const prompts = [];

    if (devjs.babel) prompts.push({
      name: 'gulp_babel',
      message: 'Babel plugin for Gulp?',
      type: 'confirm',
      default: true,
    });

    if (devjs.eslint) prompts.push({
      name: 'gulp_eslint',
      message: 'ESLint plugin for Gulp?',
      type: 'confirm',
      default: true,
    });

    this.prompt(prompts, gulp => {
      assign(devjs, gulp);
      done();
    });
  }

  configuring() {
    const pack = this.fs.readJSON(this.destinationPath('package.json'), {});
    configure.call(this, {
      scripts: {
        build: 'gulp',
        prepublish: 'gulp',
      },
    });

    if (typeof pack.scripts !== 'undefined' && pack.scripts.test) {
      configure.call(this, {
        scripts: {
          test: 'gulp; ' + pack.scripts.test
        }
      });
    }
  }

  writing() {
    write.call(this, [devjs.babel ? 'gulpfile.babel.js' : 'gulpfile.js']);
  }

  install() {
    const deps = ['gulp'];

    if (devjs.babel) deps.push('gulp-babel', 'del');
    if (devjs.eslint) deps.push('gulp-eslint');

    this.npmInstall(deps, { saveDev: true });
  }
}

export default Gulp;
<|endoftext|>


<commit_before>import test from 'tape';
import aon from './';

test('And Operator', t => {
  t.plan(5);

  const interpreter = {
    bool: (model, value) => value
  }

  t.equal(aon(
    ['&&', ['bool', true], ['bool', true], ['bool', true]],
    interpreter)(), true, 'And(true, true, true) === true');

  t.equal(aon(
    ['&&', ['bool', false], ['bool', false], ['bool', false]],
    interpreter)(), false, 'And(false, false, false) === false');

  t.equal(aon(
    ['&&', ['bool', false], ['bool', true], ['bool', true]],
    interpreter)(), false, 'And(false, true, true) === false');

  t.equal(aon(
    ['&&', ['bool', true], ['bool', true], ['bool', false]],
    interpreter)(), false, 'And(true, true, false) === false');

  t.test('And: Eagerness', st => {
    st.plan(1);

    let count = 0;
    const countInterpreter = {
      bool: (model, value) => {
        count += 1;
        return value;
      }
    }

    aon(['&&', ['bool', true],
      ['bool', false], ['bool', true]],
      countInterpreter)();

    st.equal(count, 2, 'And bails on first falsy predicate()');
  })
});

test('Or Operator', t => {
  t.plan(4);

  const interpreter = {
    bool: (model, value) => value
  }

  t.equal(aon(
    ['||', ['bool', true], ['bool', true], ['bool', true]],
    interpreter)(), true, 'Or(true, true, true) === true');

  t.equal(aon(
    ['||', ['bool', false], ['bool', false], ['bool', true]],
    interpreter)(), true, 'Or(false, false, true) === true');

  t.equal(aon(
    ['||', ['bool', false], ['bool', false], ['bool', false]],
    interpreter)(), false, 'Or(false, false, false) === false');

  t.test('Or: Eagerness', st => {
    st.plan(1);

    let count = 0;
    const countInterpreter = {
      bool: (model, value) => {
        count += 1;
        return value;
      }
    }

    aon(['||', ['bool', true],
      ['bool', true], ['bool', true]],
      countInterpreter)();

    st.equal(count, 1, 'Or bails on first truthy predicate()');
  });
});

test('Interpreter', t => {
  t.plan(4);

  const interpreter = {
    test: (model, a, b, c, d) => {
      t.deepLooseEqual([a, b, c, d], [1, 2, 3, 4], 'should pass through operands as arguments');
      t.deepLooseEqual(model, {model: true}, 'should pass the model to the predicate');
      return true;
    }
  }

  aon(['||', ['test', 1, 2, 3, 4]], interpreter)({model: true});

  const notInterpreter = {
    test: (model, a, b, c, d) => {
      t.deepLooseEqual([a, b, c, d], [1, 2, 3, 4], 'should pass through operands as arguments');
      t.deepLooseEqual(model, {model: true}, 'should pass the model to the predicate');
      return true;
    }
  }

  aon(['!', ['test', 1, 2, 3, 4]], interpreter)({model: true});
});

// TODO: Test how `this` is affected

<commit_msg>adding tests for not opperator and composition<commit_after>import test from 'tape';
import aon from './';

test('And Operator', t => {
  t.plan(5);

  const interpreter = {
    bool: (model, value) => value
  }

  t.equal(aon(
    ['&&', ['bool', true], ['bool', true], ['bool', true]],
    interpreter)(), true, 'And(true, true, true) === true');

  t.equal(aon(
    ['&&', ['bool', false], ['bool', false], ['bool', false]],
    interpreter)(), false, 'And(false, false, false) === false');

  t.equal(aon(
    ['&&', ['bool', false], ['bool', true], ['bool', true]],
    interpreter)(), false, 'And(false, true, true) === false');

  t.equal(aon(
    ['&&', ['bool', true], ['bool', true], ['bool', false]],
    interpreter)(), false, 'And(true, true, false) === false');

  t.test('And: Eagerness', st => {
    st.plan(1);

    let count = 0;
    const countInterpreter = {
      bool: (model, value) => {
        count += 1;
        return value;
      }
    }

    aon(['&&', ['bool', true],
      ['bool', false], ['bool', true]],
      countInterpreter)();

    st.equal(count, 2, 'And bails on first falsy predicate()');
  })
});

test('Or Operator', t => {
  t.plan(4);

  const interpreter = {
    bool: (model, value) => value
  }

  t.equal(aon(
    ['||', ['bool', true], ['bool', true], ['bool', true]],
    interpreter)(), true, 'Or(true, true, true) === true');

  t.equal(aon(
    ['||', ['bool', false], ['bool', false], ['bool', true]],
    interpreter)(), true, 'Or(false, false, true) === true');

  t.equal(aon(
    ['||', ['bool', false], ['bool', false], ['bool', false]],
    interpreter)(), false, 'Or(false, false, false) === false');

  t.test('Or: Eagerness', st => {
    st.plan(1);

    let count = 0;
    const countInterpreter = {
      bool: (model, value) => {
        count += 1;
        return value;
      }
    }

    aon(['||', ['bool', true],
      ['bool', true], ['bool', true]],
      countInterpreter)();

    st.equal(count, 1, 'Or bails on first truthy predicate()');
  });
});

test('Not Operator', t => {
  t.plan(2);

  const interpreter = {
    bool: (model, value) => value
  }

  t.equal(aon(
    ['!', ['bool', true]],
    interpreter)(), false, 'Not(true) === false');

  t.equal(aon(
    ['!', ['bool', false]],
    interpreter)(), true, 'Not(true) === false');
});

// TODO: Not opperator

test('Interpreter', t => {
  t.plan(4);

  const interpreter = {
    test: (model, a, b, c, d) => {
      t.deepLooseEqual([a, b, c, d], [1, 2, 3, 4], 'should pass through operands as arguments');
      t.deepLooseEqual(model, {model: true}, 'should pass the model to the predicate');
      return true;
    }
  }

  aon(['||', ['test', 1, 2, 3, 4]], interpreter)({model: true});

  const notInterpreter = {
    test: (model, a, b, c, d) => {
      t.deepLooseEqual([a, b, c, d], [1, 2, 3, 4], 'should pass through operands as arguments');
      t.deepLooseEqual(model, {model: true}, 'should pass the model to the predicate');
      return true;
    }
  }

  aon(['!', ['test', 1, 2, 3, 4]], interpreter)({model: true});
});

test('Composition', t => {
  t.plan(6);

  const interpreter = {
    lessThan: (model, key, threshold) => {
      return model[key] < threshold;
    },
    divisibleBy: (model, key, modulus) => {
      return model[key] % modulus === 0;
    }
  }

  const data = ['&&', ['lessThan', 'v', 15],
                      ['!', ['lessThan', 'v', 5]],
                      ['||', ['divisibleBy', 'v', 2],
                             ['divisibleBy', 'v', 3]]]

  t.equal(aon(data, interpreter)({v: 6}), true,
    '6 is: less than 15, and not less than 5, and divisible by either 2 or 3');

  t.equal(aon(data, interpreter)({v: 8}), true,
    '8 is: less than 15, and not less than 5, and divisible by either 2 or 3');

  t.equal(aon(data, interpreter)({v: 9}), true,
    '9 is: less than 15, and not less than 5, and divisible by either 2 or 3');

  t.equal(aon(data, interpreter)({v: 7}), false,
    '7 is not: less than 15, and not less than 5, and divisible by either 2 or 3');

  t.equal(aon(data, interpreter)({v: 3}), false,
    '3 is not: less than 15, and not less than 5, and divisible by either 2 or 3');

  t.equal(aon(data, interpreter)({v: 17}), false,
    '17 is not: less than 15, and not less than 5, and divisible by either 2 or 3');
});

// TODO: Test how `this` is affected

<|endoftext|>


<commit_before>if (!window.Worker) {
	alert('This website can not be used, because your browser does not support the Worker api!');
}
var reformatters = [
	new Reformatter('Replacer', ['replace', 'with']),
	new Reformatter('Hoffelner-Cashdesk', ['Decimal mark', 'Products filename', 'Taxes filename'])
];
reformatters.forEach(function(r) {
	reformatters[r.name] = r;
});
var selectedReformatter = null;

$(document).ready(function() {
	$('#reformatter').html(
		'<option value="">-----</option>' +
		reformatters
			.map(function(r) {
				return '<option value="' + r.name + '">' + r.name + '</option>';
			})
			.join("\n")
	).change(function(e) {
		var selectedReformatterName = $(e.target).val();
		selectedReformatter = selectedReformatterName === '' ? null : reformatters[selectedReformatterName];
		$('#submit').attr('disabled', selectedReformatter === null);
		if (selectedReformatter) {
			$('#arguments').html(
				selectedReformatter.argumentNames.map(function(a, i) {
					return a + ': <input type="text" />';
				})
			);
		} else {
			$('#arguments').html('');
		}
	});

	$('#submit').click(function() {
		var inputFiles = $('#inputfiles')[0].files;
		var fileContents = [];
		var finished = [];
		for (var i = 0; i < inputFiles.length; i++) {
			(function(index) {
				finished[index] = false;
				var reader = new FileReader();
				reader.onload = function(e) {
					fileContents[index] = {
						'name': inputFiles[index].name,
						'content': reader.result
					};
					finished[index] = true;
					if (finished.indexOf(false) == -1) { // all files read
						var args = [fileContents];
						$('#arguments input').each(function(i, e) {
							args.push($(e).val());
						});
						console.log(fileContents, args);
						selectedReformatter.reformat(args);
					}
				}
				reader.readAsText(inputFiles[index]);
			})(i);
		};
	});

	// var html = `

	//
1

	//
2

	//
3
	//

	//
s1

	//
s2

	//

	//

	//
`;
	// var $progress = $('#progress');
	// 			$progress.find('> ul').replaceWith($(html));
	// 			$progress.jstree({
	// 				"core" : {
	// 					"themes" : {
	// 						"variant" : "large"
	// 					}
	// 				},
	// 				"types" : {
	// 					"default" : {
	// 						"icon" : "glyphicon glyphicon-remove"
	// 					},
	// 					"pending" : {
	// 						"icon" : "glyphicon glyphicon-flash"
	// 					},
	// 					"complete" : {
	// 						"icon" : "glyphicon glyphicon-ok"
	// 					}
	// 				},
	// 				"plugins" : [ "types", "wholerow" ]
	// 			});
	var $tree = $('#progress');
	$tree.jstree({
		"core": {
			"check_callback" : true,
			"themes": {
				"variant": "large"
			}
		},
		"types": {
			"default": {
				"icon": "glyphicon glyphicon-remove"
			},
			"pending": {
				"icon": "glyphicon glyphicon-flash"
			},
			"complete": {
				"icon": "glyphicon glyphicon-ok"
			}
		},
		"plugins": [ "types", "wholerow" ]
	});
	$tree.on('refresh.jstree', function () {
		var $e = $("#progress li[type='pending']");
		if ($e.length > 0) {
			$('html, body').animate({
				scrollTop: $e.offset().top - $e.height() * 2
			}, 20);
		}
	});
});

function Reformatter(name, argumentNames) {
	this.name = name;
	this.argumentNames = argumentNames;
	this.worker = null;
}
Reformatter.prototype.reformat = function(args) {
	if (this.worker === null) {
		this.worker = new Worker('reformatters/' + this.name + '.js');
		var lastProgressUpdateTime = 0;
		var nextProgressUpdateTimeout = null;
		var progressTimeout = 1000;
		var oldProgressTree = null;
		this.worker.onmessage = function(e) {
			console.log('Reformatter: ', e.data);
			if (e.data.updateCounter != undefined) { // no debug message
				var updateProgress = function() {
					var data = (function generateData(stages, completedStages) {
						return stages.map(function(stage, index) {
							var node = {
								'text': stage.name,
								'children': generateData(stage.substages, stage.completedSubstages)
							};
							if (index < completedStages) {
								node.type = 'complete';
							} else if (index == completedStages) {
								node.type = 'pending';
								node.state = {
									'opened': true
								};
							}
							node.li_attr = {
								'type': node.type
							};
							return node;
						});
					})(e.data.stages, e.data.completedStages);
					console.log(data);
					var $tree = $('#progress').jstree(true);
					$tree.settings.core.data = data;
					$tree.refresh();
					lastProgressUpdateTime = new Date().getTime();
				};
				clearTimeout(nextProgressUpdateTimeout);
				if (nextProgressUpdateTimeout)
					console.log('Cancel update');
				if (new Date().getTime() - lastProgressUpdateTime >= progressTimeout) {
					console.log('Update now');
					lastProgressUpdateTime = new Date().getTime();
					updateProgress();
				} else {
					console.log('Update later');
					nextProgressUpdateTimeout = setTimeout(updateProgress, progressTimeout);
				}
			}
			if (e.data.completedStages == e.data.stages.length) { // reformatting complete
				e.data.data.forEach(function(resultFile, i) {
					downloadStringAsFile(resultFile.name, resultFile.content);
				});
			}
		};
	}
	var code = this.base.toString();
	code = code.substr(code.indexOf('{') + 1, code.lastIndexOf('}')-code.indexOf('{') - 1);
	args.splice(0, 0, code); // pass code of Reformatter.prototype.base as first argument
	this.worker.postMessage(args);
};

function downloadStringAsFile(filename, contents) {
	$a = $('', {
		'href': 'data:text/plain;charset=utf-8,' + encodeURIComponent(contents),
		'download': filename,
		'target': '_blank'
		//'style': 'display: none'
	});
	$('body').append($a);
	var evObj = document.createEvent('MouseEvents');
	evObj.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
	$a[0].dispatchEvent(evObj);
	$a.remove();
}<commit_msg>Remove code comment<commit_after>if (!window.Worker) {
	alert('This website can not be used, because your browser does not support the Worker api!');
}
var reformatters = [
	new Reformatter('Replacer', ['replace', 'with']),
	new Reformatter('Hoffelner-Cashdesk', ['Decimal mark', 'Products filename', 'Taxes filename'])
];
reformatters.forEach(function(r) {
	reformatters[r.name] = r;
});
var selectedReformatter = null;

$(document).ready(function() {
	$('#reformatter').html(
		'<option value="">-----</option>' +
		reformatters
			.map(function(r) {
				return '<option value="' + r.name + '">' + r.name + '</option>';
			})
			.join("\n")
	).change(function(e) {
		var selectedReformatterName = $(e.target).val();
		selectedReformatter = selectedReformatterName === '' ? null : reformatters[selectedReformatterName];
		$('#submit').attr('disabled', selectedReformatter === null);
		if (selectedReformatter) {
			$('#arguments').html(
				selectedReformatter.argumentNames.map(function(a, i) {
					return a + ': <input type="text" />';
				})
			);
		} else {
			$('#arguments').html('');
		}
	});

	$('#submit').click(function() {
		var inputFiles = $('#inputfiles')[0].files;
		var fileContents = [];
		var finished = [];
		for (var i = 0; i < inputFiles.length; i++) {
			(function(index) {
				finished[index] = false;
				var reader = new FileReader();
				reader.onload = function(e) {
					fileContents[index] = {
						'name': inputFiles[index].name,
						'content': reader.result
					};
					finished[index] = true;
					if (finished.indexOf(false) == -1) { // all files read
						var args = [fileContents];
						$('#arguments input').each(function(i, e) {
							args.push($(e).val());
						});
						console.log(fileContents, args);
						selectedReformatter.reformat(args);
					}
				}
				reader.readAsText(inputFiles[index]);
			})(i);
		};
	});

	var $tree = $('#progress');
	$tree.jstree({
		"core": {
			"check_callback" : true,
			"themes": {
				"variant": "large"
			}
		},
		"types": {
			"default": {
				"icon": "glyphicon glyphicon-remove"
			},
			"pending": {
				"icon": "glyphicon glyphicon-flash"
			},
			"complete": {
				"icon": "glyphicon glyphicon-ok"
			}
		},
		"plugins": [ "types", "wholerow" ]
	});
	$tree.on('refresh.jstree', function () {
		var $e = $("#progress li[type='pending']");
		if ($e.length > 0) {
			$('html, body').animate({
				scrollTop: $e.offset().top - $e.height() * 2
			}, 20);
		}
	});
});

function Reformatter(name, argumentNames) {
	this.name = name;
	this.argumentNames = argumentNames;
	this.worker = null;
}
Reformatter.prototype.reformat = function(args) {
	if (this.worker === null) {
		this.worker = new Worker('reformatters/' + this.name + '.js');
		var lastProgressUpdateTime = 0;
		var nextProgressUpdateTimeout = null;
		var progressTimeout = 1000;
		var oldProgressTree = null;
		this.worker.onmessage = function(e) {
			console.log('Reformatter: ', e.data);
			if (e.data.updateCounter != undefined) { // no debug message
				var updateProgress = function() {
					var data = (function generateData(stages, completedStages) {
						return stages.map(function(stage, index) {
							var node = {
								'text': stage.name,
								'children': generateData(stage.substages, stage.completedSubstages)
							};
							if (index < completedStages) {
								node.type = 'complete';
							} else if (index == completedStages) {
								node.type = 'pending';
								node.state = {
									'opened': true
								};
							}
							node.li_attr = {
								'type': node.type
							};
							return node;
						});
					})(e.data.stages, e.data.completedStages);
					console.log(data);
					var $tree = $('#progress').jstree(true);
					$tree.settings.core.data = data;
					$tree.refresh();
					lastProgressUpdateTime = new Date().getTime();
				};
				clearTimeout(nextProgressUpdateTimeout);
				if (nextProgressUpdateTimeout)
					console.log('Cancel update');
				if (new Date().getTime() - lastProgressUpdateTime >= progressTimeout) {
					console.log('Update now');
					lastProgressUpdateTime = new Date().getTime();
					updateProgress();
				} else {
					console.log('Update later');
					nextProgressUpdateTimeout = setTimeout(updateProgress, progressTimeout);
				}
			}
			if (e.data.completedStages == e.data.stages.length) { // reformatting complete
				e.data.data.forEach(function(resultFile, i) {
					downloadStringAsFile(resultFile.name, resultFile.content);
				});
			}
		};
	}
	var code = this.base.toString();
	code = code.substr(code.indexOf('{') + 1, code.lastIndexOf('}')-code.indexOf('{') - 1);
	args.splice(0, 0, code); // pass code of Reformatter.prototype.base as first argument
	this.worker.postMessage(args);
};

function downloadStringAsFile(filename, contents) {
	$a = $('', {
		'href': 'data:text/plain;charset=utf-8,' + encodeURIComponent(contents),
		'download': filename,
		'target': '_blank'
		//'style': 'display: none'
	});
	$('body').append($a);
	var evObj = document.createEvent('MouseEvents');
	evObj.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
	$a[0].dispatchEvent(evObj);
	$a.remove();
}<|endoftext|>


<commit_before>/**
 * Moovie: an advanced HTML5 video player for MooTools.
 * @copyright 2010 Colin Aarts
 * @license MIT
 */

/**
 * Strip directory and suffix from filenames.
 * @link http://locutus.io/php/basename/
 * @author Kevin van Zonneveld (http://kvz.io)
 * @author Ash Searle (http://hexmen.com/blog/)
 * @author Lincoln Ramsay
 * @author djmix
 * @author Dmitry Gorelenkov
 * @param  {string} path   [description]
 * @param  {string} suffix If specified, removes suffix from returned string.
 * @return {string}        [description]
 */
export function basename(path, suffix) {
    let b = path;
    const lastChar = b.charAt(b.length - 1);

    if (lastChar === '/' || lastChar === '\\') {
        b = b.slice(0, -1);
    }

    b = b.replace(/^.*[\/\\]/g, '');

    if (typeof suffix === 'string' && b.substr(b.length - suffix.length) === suffix) {
        b = b.substr(0, b.length - suffix.length);
    }

    return b;
}

/**
 * Converts a floating point value into a time string.
 * @param  {Number} value A floating point value represented as seconds.milliseconds.
 * @return {string} A string formatted to either: hh:mm:ss or mm:ss or m:ss
 */
export function formatSeconds(value) {
    const input = Math.round(value);
    let hours = Math.floor(input / 3600);
    let minutes = Math.floor(input % 3600 / 60);
    let seconds = input % 3600 % 60;

    if (Number.isNaN(value) || !Number.isFinite(value)) {
        return '-:--';
    }

    if (value < 0) {
        return '0:00';
    }

    hours = hours > 0 ? hours + ':' : '';
    minutes = (hours && minutes < 10 ? '0' + minutes : minutes) + ':';
    seconds = seconds < 10 ? '0' + seconds : seconds;

    return hours + minutes + seconds;
}

/**
 * Retrieve attributes from an element.
 * @param  {Element} element An Element instance.
 * @return {Object} An object containing all defined element attributes.
 */
export function getAttributes(element) {
    const attributes = {};

    Array.convert(element.attributes).forEach((attribute) => {
        attributes[attribute.name] = attribute.value;
    });

    return attributes;
}

/**
 * Polls the DOM periodically to check for the existance of an element.
 * @see https://davidwalsh.name/javascript-polling
 * @param  {Element}  element   The Element instance to check for.
 * @param  {Function} onsuccess Called if the element was found before the timeout expired.
 * @param  {Function} onerror   Called if the element was not found and the timeout has expired.
 * @param  {Number}   timeout   How long to poll the DOM for. (Default is 2 seconds)
 * @return {undefined}
 */
export function isInDOM(element, onsuccess, onerror, timeout) {
    const expiry = Date.now() + (timeout || 2000);
    const condition = function () {
        return document.body.contains(element);
    };

    (function poller() {
        // If the condition was met, we're done!
        if (condition()) {
            onsuccess();

        // If the condition wasn't met and the timeout hasn't elapsed, try again.
        } else if (Date.now() < expiry) {
            setTimeout(poller, 100);

        // Condition wasn't matched and too much time elapsed, reject!
        } else {
            onerror(new Error('Element could not be found in DOM before timeout occurred.'));
        }
    })();

    // @todo return Promise
}
<commit_msg>style: remove unnecessary escape character<commit_after>/**
 * Moovie: an advanced HTML5 video player for MooTools.
 * @copyright 2010 Colin Aarts
 * @license MIT
 */

/**
 * Strip directory and suffix from filenames.
 * @link http://locutus.io/php/basename/
 * @author Kevin van Zonneveld (http://kvz.io)
 * @author Ash Searle (http://hexmen.com/blog/)
 * @author Lincoln Ramsay
 * @author djmix
 * @author Dmitry Gorelenkov
 * @param  {string} path   [description]
 * @param  {string} suffix If specified, removes suffix from returned string.
 * @return {string}        [description]
 */
export function basename(path, suffix) {
    let b = path;
    const lastChar = b.charAt(b.length - 1);

    if (lastChar === '/' || lastChar === '\\') {
        b = b.slice(0, -1);
    }

    b = b.replace(/^.*[/\\]/g, '');

    if (typeof suffix === 'string' && b.substr(b.length - suffix.length) === suffix) {
        b = b.substr(0, b.length - suffix.length);
    }

    return b;
}

/**
 * Converts a floating point value into a time string.
 * @param  {Number} value A floating point value represented as seconds.milliseconds.
 * @return {string} A string formatted to either: hh:mm:ss or mm:ss or m:ss
 */
export function formatSeconds(value) {
    const input = Math.round(value);
    let hours = Math.floor(input / 3600);
    let minutes = Math.floor(input % 3600 / 60);
    let seconds = input % 3600 % 60;

    if (Number.isNaN(value) || !Number.isFinite(value)) {
        return '-:--';
    }

    if (value < 0) {
        return '0:00';
    }

    hours = hours > 0 ? hours + ':' : '';
    minutes = (hours && minutes < 10 ? '0' + minutes : minutes) + ':';
    seconds = seconds < 10 ? '0' + seconds : seconds;

    return hours + minutes + seconds;
}

/**
 * Retrieve attributes from an element.
 * @param  {Element} element An Element instance.
 * @return {Object} An object containing all defined element attributes.
 */
export function getAttributes(element) {
    const attributes = {};

    Array.convert(element.attributes).forEach((attribute) => {
        attributes[attribute.name] = attribute.value;
    });

    return attributes;
}

/**
 * Polls the DOM periodically to check for the existance of an element.
 * @see https://davidwalsh.name/javascript-polling
 * @param  {Element}  element   The Element instance to check for.
 * @param  {Function} onsuccess Called if the element was found before the timeout expired.
 * @param  {Function} onerror   Called if the element was not found and the timeout has expired.
 * @param  {Number}   timeout   How long to poll the DOM for. (Default is 2 seconds)
 * @return {undefined}
 */
export function isInDOM(element, onsuccess, onerror, timeout) {
    const expiry = Date.now() + (timeout || 2000);
    const condition = function () {
        return document.body.contains(element);
    };

    (function poller() {
        // If the condition was met, we're done!
        if (condition()) {
            onsuccess();

        // If the condition wasn't met and the timeout hasn't elapsed, try again.
        } else if (Date.now() < expiry) {
            setTimeout(poller, 100);

        // Condition wasn't matched and too much time elapsed, reject!
        } else {
            onerror(new Error('Element could not be found in DOM before timeout occurred.'));
        }
    })();

    // @todo return Promise
}
<|endoftext|>


<commit_before>var tristis_config = {
        base: "../node_modules/yui/",
        filter: "raw",
        groups: {
            "template": {
                patterns: {
                    "template-": {
                        configFn: function (me) {
                            "use strict";
                            me.fullpath = "templates/compiled/" + me.name.replace(me.group + "-", "") + ".js";
                            me.requires = ["template"];
                        }
                    }
                }
            },
            "css": {
                base: "css/",
                patterns: {
                    "css-": {
                        configFn: function (me) {
                            "use strict";
                            me.path = me.name.replace("css-", "") + ".css";
                            me.type = "css";
                        }
                    }
                }
            },
            "/": {
                base: "js/",
                modules: {
                    "app-tristis": {
                        path: "app-tristis.js",
                        requires: [
                            "base-build",
                            "app",
                            "extension-view-classes",
                            "extension-view-parent",
                            "extension-tristis-events",
                            "extension-tristis-routes",
                            "model-user",
                            "model-list-timelines",
                            "view-nav",
                            "css-nav",
                            "stream-user",
                            "stream-users"
                        ]
                    },
                    "extension-list-users": {
                        path: "extension-list-users.js",
                        requires: [
                            "promise",
                            "array-extras",
                            "stream-users"
                        ]
                    },
                    "extension-timeline-menus": {
                        path: "extension-timeline-menus.js",
                        requires: ["node-event-html5"]
                    },
                    "extension-tristis-events": {
                        path: "extension-tristis-events.js",
                        requires: [
                            "stream-user",
                            "model-list-friends"
                        ]
                    },
                    "extension-tristis-routes": {
                        path: "extension-tristis-routes.js",
                        requires: ["gallery-lazy-load"]
                    },
                    "model-list-friends": {
                        path: "model-list-friends.js",
                        requires: [
                            "base-build",
                            "lazy-model-list"
                        ]
                    },
                    "model-list-timelines": {
                        path: "model-list-timelines.js",
                        requires: [
                            "base-build",
                            "model-list",
                            "model-timeline-home",
                            "model-timeline-mentions",
                            "model-timeline-list",
                            "extension-list-users"
                        ]
                    },
                    "model-list-tweets": {
                        path: "model-list-tweets.js",
                        requires: [
                            "base-build",
                            "lazy-model-list",
                            "extension-model-list-more"
                        ]
                    },
                    "model-timeline-base": {
                        path: "model-timeline-base.js",
                        requires: [
                            "base-build",
                            "model",
                            "model-list-tweets"
                        ]
                    },
                    "model-timeline-home": {
                        path: "model-timeline-home.js",
                        requires: [
                            "base-build",
                            "model-timeline-base",
                            "stream-user"
                        ]
                    },
                    "model-timeline-list": {
                        path: "model-timeline-list.js",
                        requires: [
                            "base-build",
                            "model-timeline-base"
                        ]
                    },
                    "model-timeline-mentions": {
                        path: "model-timeline-mentions.js",
                        requires: [
                            "base-build",
                            "model-timeline-base"
                        ]
                    },
                    "model-user": {
                        path: "model-user.js",
                        requires: [
                            "base-build",
                            "model"
                        ]
                    },
                    "stream-base": {
                        path: "stream-base.js",
                        requires: [
                            "oop",
                            "event-custom"
                        ]
                    },
                    "stream-user": {
                        path: "stream-user.js",
                        requires: [
                            "oop",
                            "event-custom",
                            "stream-base"
                        ]
                    },
                    "stream-users": {
                        path: "stream-users.js",
                        requires: [
                            "oop",
                            "event-custom",
                            "stream-base"
                        ]
                    },
                    "view-list": {
                        path: "view-list.js",
                        requires: [
                            "base-build",
                            "view",
                            "template-timeline",
                            "template-tweet"
                        ]
                    },
                    "view-nav": {
                        path: "view-nav.js",
                        requires: [
                            "base-build",
                            "view",
                            "template-nav",
                            "template-nav-timelines"
                        ]
                    },
                    "view-timeline": {
                        path: "view-timeline.js",
                        requires: [
                            "base-build",
                            "view",
                            "extension-timeline-menus",
                            "template-timeline",
                            "template-tweet"
                        ]
                    }
                }
            },
            "/extensions/": {
                base: "js/extensions/",
                modules: {
                    "extension-model-list-more": { path: "extension-model-list-more.js" },
                    "extension-view-classes": {
                        path: "extension-view-classes.js",
                        requires: ["event-custom"]
                    },
                    "extension-view-parent": {
                        path: "extension-view-parent.js",
                        requires: [
                            "view",
                            "event-custom"
                        ]
                    }
                }
            },
            "/gallery/": {
                base: "js/gallery/",
                modules: {
                    "gallery-debounce": { path: "gallery-debounce.js" },
                    "gallery-lazy-load": {
                        path: "gallery-lazy-load.js",
                        requires: ["oop"]
                    }
                }
            },
            "/oauth/": {
                base: "js/oauth/",
                modules: {
                    "model-oauth": {
                        path: "model-oauth.js",
                        requires: [
                            "base-build",
                            "model"
                        ]
                    },
                    "view-link": {
                        path: "view-link.js",
                        requires: [
                            "base-build",
                            "view",
                            "model-oauth",
                            "template-oauth-link"
                        ]
                    }
                }
            }
        }
    };<commit_msg>Updated config<commit_after>var tristis_config = {
        base: "../node_modules/yui/",
        filter: "raw",
        groups: {
            "template": {
                patterns: {
                    "template-": {
                        configFn: function (me) {
                            "use strict";
                            me.fullpath = "templates/compiled/" + me.name.replace(me.group + "-", "") + ".js";
                            me.requires = ["template"];
                        }
                    }
                }
            },
            "css": {
                base: "css/",
                patterns: {
                    "css-": {
                        configFn: function (me) {
                            "use strict";
                            me.path = me.name.replace("css-", "") + ".css";
                            me.type = "css";
                        }
                    }
                }
            },
            "/": {
                base: "js/",
                modules: {
                    "app-tristis": {
                        path: "app-tristis.js",
                        requires: [
                            "base-build",
                            "app",
                            "extension-view-classes",
                            "extension-view-parent",
                            "extension-tristis-events",
                            "extension-tristis-routes",
                            "model-user",
                            "model-list-timelines",
                            "view-nav",
                            "css-app",
                            "css-nav",
                            "stream-user",
                            "stream-users"
                        ]
                    },
                    "extension-list-users": {
                        path: "extension-list-users.js",
                        requires: [
                            "promise",
                            "array-extras",
                            "stream-users"
                        ]
                    },
                    "extension-timeline-menus": {
                        path: "extension-timeline-menus.js",
                        requires: ["node-event-html5"]
                    },
                    "extension-tristis-events": {
                        path: "extension-tristis-events.js",
                        requires: [
                            "stream-user",
                            "model-list-friends"
                        ]
                    },
                    "extension-tristis-routes": {
                        path: "extension-tristis-routes.js",
                        requires: ["gallery-lazy-load"]
                    },
                    "model-list-friends": {
                        path: "model-list-friends.js",
                        requires: [
                            "base-build",
                            "lazy-model-list"
                        ]
                    },
                    "model-list-timelines": {
                        path: "model-list-timelines.js",
                        requires: [
                            "base-build",
                            "model-list",
                            "model-timeline-home",
                            "model-timeline-mentions",
                            "model-timeline-list",
                            "extension-list-users"
                        ]
                    },
                    "model-list-tweets": {
                        path: "model-list-tweets.js",
                        requires: [
                            "base-build",
                            "lazy-model-list",
                            "extension-model-list-more"
                        ]
                    },
                    "model-timeline-base": {
                        path: "model-timeline-base.js",
                        requires: [
                            "base-build",
                            "model",
                            "model-list-tweets"
                        ]
                    },
                    "model-timeline-home": {
                        path: "model-timeline-home.js",
                        requires: [
                            "base-build",
                            "model-timeline-base",
                            "stream-user"
                        ]
                    },
                    "model-timeline-list": {
                        path: "model-timeline-list.js",
                        requires: [
                            "base-build",
                            "model-timeline-base"
                        ]
                    },
                    "model-timeline-mentions": {
                        path: "model-timeline-mentions.js",
                        requires: [
                            "base-build",
                            "model-timeline-base"
                        ]
                    },
                    "model-user": {
                        path: "model-user.js",
                        requires: [
                            "base-build",
                            "model"
                        ]
                    },
                    "stream-base": {
                        path: "stream-base.js",
                        requires: [
                            "oop",
                            "event-custom"
                        ]
                    },
                    "stream-user": {
                        path: "stream-user.js",
                        requires: [
                            "oop",
                            "event-custom",
                            "stream-base"
                        ]
                    },
                    "stream-users": {
                        path: "stream-users.js",
                        requires: [
                            "oop",
                            "event-custom",
                            "stream-base"
                        ]
                    },
                    "view-list": {
                        path: "view-list.js",
                        requires: [
                            "base-build",
                            "view",
                            "template-timeline",
                            "template-tweet"
                        ]
                    },
                    "view-nav": {
                        path: "view-nav.js",
                        requires: [
                            "base-build",
                            "view",
                            "template-nav",
                            "template-nav-timelines"
                        ]
                    },
                    "view-timeline": {
                        path: "view-timeline.js",
                        requires: [
                            "base-build",
                            "view",
                            "extension-timeline-menus",
                            "template-timeline",
                            "template-tweet",
                            "css-timeline"
                        ]
                    }
                }
            },
            "/extensions/": {
                base: "js/extensions/",
                modules: {
                    "extension-model-list-more": { path: "extension-model-list-more.js" },
                    "extension-view-classes": {
                        path: "extension-view-classes.js",
                        requires: ["event-custom"]
                    },
                    "extension-view-parent": {
                        path: "extension-view-parent.js",
                        requires: [
                            "view",
                            "event-custom"
                        ]
                    }
                }
            },
            "/gallery/": {
                base: "js/gallery/",
                modules: {
                    "gallery-debounce": { path: "gallery-debounce.js" },
                    "gallery-lazy-load": {
                        path: "gallery-lazy-load.js",
                        requires: ["oop"]
                    }
                }
            },
            "/oauth/": {
                base: "js/oauth/",
                modules: {
                    "model-oauth": {
                        path: "model-oauth.js",
                        requires: [
                            "base-build",
                            "model"
                        ]
                    },
                    "view-link": {
                        path: "view-link.js",
                        requires: [
                            "base-build",
                            "view",
                            "model-oauth",
                            "template-oauth-link"
                        ]
                    }
                }
            }
        }
    };<|endoftext|>


<commit_before>(function(factory) {
    if (typeof define === 'function' && define.amd) {
        define([
            '$',
            'velocity',
            'plugin'
        ], factory);
    } else {
        var framework = window.Zepto || window.jQuery;
        factory(framework, framework.Velocity, window.Plugin);
    }
}(function($, Velocity, Plugin) {
    var cssClasses = {
        ITEM: 'bellows__item',
        HEADER: 'bellows__header',
        OPENED: 'bellows--is-open',
        OPENING: 'bellows--is-opening',
        CLOSING: 'bellows--is-closing'
    };

    var selectors = {
        ITEM_HEADER: '> .bellows__item > .bellows__header',
        ITEM_CONTENT_WRAPPER: '> .bellows__content-wrapper',
        ITEM_CONTENT: '> .bellows__item > .bellows__content'
    };

    function Bellows(element, options) {
        Bellows.__super__.call(this, element, options, Bellows.DEFAULTS);
    }

    Bellows.VERSION = '0';

    Bellows.DEFAULTS = {
        singleItemOpen: false,
        event: 'click',
        duration: 200,
        easing: 'swing',
        open: $.noop,
        opened: $.noop,
        close: $.noop,
        closed: $.noop
    };

    Plugin.create('bellows', Bellows, {

        _init: function(element) {
            this.$bellows = $(element);

            this._wrapContent(this.$bellows);

            this._bindEvents();
        },

        _bindEvents: function() {
            var plugin = this;

            /**
             * Ghetto Event Delegation™

               Zepto doesn't support descendant selectors in event delegation,
               so we compare against the closest bellows to ensure we are invoking
               the event from a direct child, not a bellows child from a nested bellows.
             */
            this.$bellows
                .on(this.options.event, function(e) {
                    var $target = $(e.target);
                    var $closestBellows = $target.closest('.bellows');

                    // We don't want to continue if we're clicking on an anchor
                    if ($target.is('a') || !!$target.parents('a').length) {
                        return;
                    }

                    // We need to verify not only that we're inside the direct bellows of the item, but also if the item is a header/child of a header
                    if ($closestBellows[0] === plugin.$bellows[0] && ($target.hasClass(cssClasses.HEADER) || !!$target.closest('.bellows__header').length)) {
                        e.preventDefault();

                        plugin.toggle($target.closest('.bellows__item'));
                    }
                });
        },

        /*
         Gets an element's height using Velocity's built-in property cache.
         Used for getting heights before animations, for animating into an
         element's space.
         */
        _getHeight: function($element) {
            return parseFloat(Velocity.CSS.getPropertyValue($element[0], 'height'));
        },

        /*
         Sets the height of bellows so we animate into
         the space rather than re-flowing the entire document
         */
        _setHeight: function(height) {
            this.$bellows.css('height', height || '');
        },

        /*
         Allow items to be found using an index
         */
        _item: function(item) {
            if (typeof item === 'number') {
                item = this.$bellows.find('.' + cssClasses.ITEM).eq(item);
            }

            return item;
        },

        _wrapContent: function($items) {
            $items
                .find(selectors.ITEM_CONTENT)
                // wrap content section of each item to facilitate padding
                .wrap('
')
                // add aria-hidden attribute to all hidden content wrappers
                .parents('.bellows__item:not(.bellows--is-open)')
                .find(selectors.ITEM_CONTENT_WRAPPER)
                .attr('aria-hidden', true);
        },

        toggle: function($item) {
            $item = this._item($item);

            this[$item.hasClass(cssClasses.OPENED) ? 'close' : 'open']($item);
        },

        open: function($item) {
            $item = this._item($item);

            if ($item.hasClass(cssClasses.OPENED)) {
                return;
            }

            var plugin = this;
            var $contentWrapper = $item.find(selectors.ITEM_CONTENT_WRAPPER);

            if (this.options.singleItemOpen) {
                this.closeAll();
            }

            this._trigger('open', { item: $item });

            Velocity
                .animate($contentWrapper, 'slideDown', {
                    begin: function() {
                        plugin._setHeight(plugin._getHeight(plugin.$bellows) + plugin._getHeight($contentWrapper));
                        $item.addClass(cssClasses.OPENING);
                    },
                    duration: this.options.duration,
                    easing: this.options.easing,
                    complete: function() {
                        $item
                            .removeClass(cssClasses.OPENING)
                            .addClass(cssClasses.OPENED)
                            .find(selectors.ITEM_CONTENT_WRAPPER)
                            .removeAttr('aria-hidden');

                        plugin._setHeight();

                        plugin._trigger('opened', { item: $item });
                    }
                });
        },

        close: function($item) {
            $item = this._item($item);

            if (!$item.hasClass(cssClasses.OPENED)) {
                return;
            }

            var plugin = this;
            var $contentWrapper = $item.find(selectors.ITEM_CONTENT_WRAPPER);

            this._trigger('close', { item: $item });

            Velocity
                .animate($contentWrapper, 'slideUp', {
                    begin: function() {
                        plugin._setHeight(plugin._getHeight(plugin.$bellows));
                        $item
                            .removeClass(cssClasses.OPENED)
                            .addClass(cssClasses.CLOSING);
                    },
                    duration: this.options.duration,
                    easing: this.options.easing,
                    complete: function() {
                        $item
                            .removeClass(cssClasses.CLOSING)
                            .find(selectors.ITEM_CONTENT_WRAPPER)
                            .attr('aria-hidden', true);

                        plugin._setHeight();

                        plugin._trigger('closed', { item: $item });
                    }
                });
        },

        closeAll: function() {
            var plugin = this;

            this.$bellows.find('.' + cssClasses.OPENED).each(function() {
                plugin.close($(this));
            });
        },

        add: function(items, replace) {
            var $container = $('
');
            $(items).appendTo($container);

            replace && this.$bellows.empty();

            this._wrapContent($container);
            this.$bellows.append($container.children());
        }
    });

    $('[data-bellows]').bellows();

    return $;
}));
<commit_msg>If bellows item is disabled, do nothing on 'open'<commit_after>(function(factory) {
    if (typeof define === 'function' && define.amd) {
        define([
            '$',
            'velocity',
            'plugin'
        ], factory);
    } else {
        var framework = window.Zepto || window.jQuery;
        factory(framework, framework.Velocity, window.Plugin);
    }
}(function($, Velocity, Plugin) {
    var cssClasses = {
        ITEM: 'bellows__item',
        HEADER: 'bellows__header',
        OPENED: 'bellows--is-open',
        OPENING: 'bellows--is-opening',
        CLOSING: 'bellows--is-closing',
        DISABLED: 'bellows--is-disabled'
    };

    var selectors = {
        ITEM_HEADER: '> .bellows__item > .bellows__header',
        ITEM_CONTENT_WRAPPER: '> .bellows__content-wrapper',
        ITEM_CONTENT: '> .bellows__item > .bellows__content'
    };

    function Bellows(element, options) {
        Bellows.__super__.call(this, element, options, Bellows.DEFAULTS);
    }

    Bellows.VERSION = '0';

    Bellows.DEFAULTS = {
        singleItemOpen: false,
        event: 'click',
        duration: 200,
        easing: 'swing',
        open: $.noop,
        opened: $.noop,
        close: $.noop,
        closed: $.noop
    };

    Plugin.create('bellows', Bellows, {

        _init: function(element) {
            this.$bellows = $(element);

            this._wrapContent(this.$bellows);

            this._bindEvents();
        },

        _bindEvents: function() {
            var plugin = this;

            /**
             * Ghetto Event Delegation™

               Zepto doesn't support descendant selectors in event delegation,
               so we compare against the closest bellows to ensure we are invoking
               the event from a direct child, not a bellows child from a nested bellows.
             */
            this.$bellows
                .on(this.options.event, function(e) {
                    var $target = $(e.target);
                    var $closestBellows = $target.closest('.bellows');

                    // We don't want to continue if we're clicking on an anchor
                    if ($target.is('a') || !!$target.parents('a').length) {
                        return;
                    }

                    // We need to verify not only that we're inside the direct bellows of the item, but also if the item is a header/child of a header
                    if ($closestBellows[0] === plugin.$bellows[0] && ($target.hasClass(cssClasses.HEADER) || !!$target.closest('.bellows__header').length)) {
                        e.preventDefault();

                        plugin.toggle($target.closest('.bellows__item'));
                    }
                });
        },

        /*
         Gets an element's height using Velocity's built-in property cache.
         Used for getting heights before animations, for animating into an
         element's space.
         */
        _getHeight: function($element) {
            return parseFloat(Velocity.CSS.getPropertyValue($element[0], 'height'));
        },

        /*
         Sets the height of bellows so we animate into
         the space rather than re-flowing the entire document
         */
        _setHeight: function(height) {
            this.$bellows.css('height', height || '');
        },

        /*
         Allow items to be found using an index
         */
        _item: function(item) {
            if (typeof item === 'number') {
                item = this.$bellows.find('.' + cssClasses.ITEM).eq(item);
            }

            return item;
        },

        _wrapContent: function($items) {
            $items
                .find(selectors.ITEM_CONTENT)
                // wrap content section of each item to facilitate padding
                .wrap('
')
                // add aria-hidden attribute to all hidden content wrappers
                .parents('.bellows__item:not(.bellows--is-open)')
                .find(selectors.ITEM_CONTENT_WRAPPER)
                .attr('aria-hidden', true);
        },

        toggle: function($item) {
            $item = this._item($item);

            this[$item.hasClass(cssClasses.OPENED) ? 'close' : 'open']($item);
        },

        open: function($item) {
            $item = this._item($item);

            if ($item.hasClass(cssClasses.OPENED) || $item.hasClass(cssClasses.DISABLED)) {
                return;
            }

            var plugin = this;
            var $contentWrapper = $item.find(selectors.ITEM_CONTENT_WRAPPER);

            if (this.options.singleItemOpen) {
                this.closeAll();
            }

            this._trigger('open', { item: $item });

            Velocity
                .animate($contentWrapper, 'slideDown', {
                    begin: function() {
                        plugin._setHeight(plugin._getHeight(plugin.$bellows) + plugin._getHeight($contentWrapper));
                        $item.addClass(cssClasses.OPENING);
                    },
                    duration: this.options.duration,
                    easing: this.options.easing,
                    complete: function() {
                        $item
                            .removeClass(cssClasses.OPENING)
                            .addClass(cssClasses.OPENED)
                            .find(selectors.ITEM_CONTENT_WRAPPER)
                            .removeAttr('aria-hidden');

                        plugin._setHeight();

                        plugin._trigger('opened', { item: $item });
                    }
                });
        },

        close: function($item) {
            $item = this._item($item);

            if (!$item.hasClass(cssClasses.OPENED)) {
                return;
            }

            var plugin = this;
            var $contentWrapper = $item.find(selectors.ITEM_CONTENT_WRAPPER);

            this._trigger('close', { item: $item });

            Velocity
                .animate($contentWrapper, 'slideUp', {
                    begin: function() {
                        plugin._setHeight(plugin._getHeight(plugin.$bellows));
                        $item
                            .removeClass(cssClasses.OPENED)
                            .addClass(cssClasses.CLOSING);
                    },
                    duration: this.options.duration,
                    easing: this.options.easing,
                    complete: function() {
                        $item
                            .removeClass(cssClasses.CLOSING)
                            .find(selectors.ITEM_CONTENT_WRAPPER)
                            .attr('aria-hidden', true);

                        plugin._setHeight();

                        plugin._trigger('closed', { item: $item });
                    }
                });
        },

        closeAll: function() {
            var plugin = this;

            this.$bellows.find('.' + cssClasses.OPENED).each(function() {
                plugin.close($(this));
            });
        },

        add: function(items, replace) {
            var $container = $('
');
            $(items).appendTo($container);

            replace && this.$bellows.empty();

            this._wrapContent($container);
            this.$bellows.append($container.children());
        }
    });

    $('[data-bellows]').bellows();

    return $;
}));
<|endoftext|>


<commit_before>(function (root,$) {
    var vars = root.vars;
    var bigdraw ={};
    /* index */
    bigdraw.index ={
        init: function () {
            $(function () {
                FastClick.attach(document.body);
                $('.btn1').on('click', function () {
                    location.href = "create.html";
                });
            });
        }
    };

    /* create */
    bigdraw.create ={
        init:function () {
            var self = this;
            $(function () {
                FastClick.attach(document.body);

                self.evens();

            });
        },
        evens:function () {

            $('#sin').on('click', function () {
                var slc=$(this).attr('data-sin');
                $(this).attr('class','sin sin'+slc);
                $('#tin').attr('class','tin p'+slc);
                $('#tin').show();

            });

            $('.ys-opts .ys').on('click', function () {
                var me =this;
                var ys = $('.ys');
                $('#tin').hide();
                $('.dl-rlt').hide();
                var slc = $(this).attr('data-sin');
                var tips = $('#sin');
                $.each(ys, function (i, v) {
                    if(v==me){
                        $(me).addClass('current');
                     }else{
                        $(v).removeClass('current');
                     }
                 });

                var sinClass=['sin' , 'sin'+slc , 'sin'+slc+'-tips','flipInCardY'].join(' ');
                tips.attr('class',sinClass);
                tips.attr('data-sin',slc);
                tips.removeClass().addClass(sinClass + ' animated').one(
                    'webkitAnimationEnd ' +
                    'mozAnimationEnd ' +
                    'MSAnimationEnd ' +
                    'oanimationend ' +
                    'animationend ',
                    function(){
                        $(this).removeClass('flipInCardY');
                    });

                $('#ys-choice').removeClass().addClass('ys-choice co'+slc);

            });

            $(document.body).on('cvsImageData',function(evt,kind, bx64 ){
                bx64 = bx64 ||  vars.getLocalStorage('cvsImageData');
                kind = kind ||  vars.getLocalStorage('cvsImageKind');
                root.draw.upload(kind,bx64,function (rt) {
                    var data = rt && rt.data || "";
                    var cbUrl= bx64;
                    if(data && data.url) {
                        cbUrl = data.url || bx64;
                    }
                    vars.setLocalStorage('cvsImageUrl',cbUrl);
                    $('#sin').hide();
                    $('#tin').hide();

                    // var _timer = setTimeout(function () {

                        location.href = "rlt.html?kind=" +kind+"&url="+ cbUrl;

                    // },0);
                });
            });

            $('.btn2').on('click', function () {
                var sin = $('#sin').attr('data-sin');
                var wd  = $('#sin_input').val()||'';
                if(wd) {
                    if (wd.length > 10) {
                        wd = wd.substring(1,10);
                    }
                    draw.drawCanvas(wd, sin); //make photo
                }
            });

            var checkCountChar = function () {
                var txtAre =  $("#sin_input");
                var x = txtAre.val().length;
                if (x > 10) {
                    vars.showTip('最多输入10个字符',1000);
                }
                return x;
            };

            $("#sin_input").on('change keyup',function (e) {
                  checkCountChar();
            });

        }

    };

    bigdraw.rlt = {
        init: function () {
            var self = this;
            $(function () {
                FastClick.attach(document.body);
                var imgdata = vars.getLocalStorage('cvsImageData')||'';
                var imgUrl  = vars.getLocalStorage('cvsImageUrl')|| vars.getParam('url') || imgdata;
                var kind    = vars.getLocalStorage('cvsImageKind')|| vars.getParam('kind') || 3;
                var dlPic = $('#dl-pic');
                dlPic.attr('src',imgUrl);
                dlPic.removeClass().addClass('dl-pic dl-c'+kind);
                self.events();
                var indexpage = location.href;
                indexpage = indexpage.replace('rlt.html','index.html');
                window.initShareEvents({
                    'img_url': imgUrl,
                    'img_width': '100',
                    'img_height': '100',
                    'link': indexpage,
                    'desc': '现在朋友圈流行这样装逼',
                    'title':  '朋友圈大字'
                } );
            });
        },
        events:function () {
            $('.btn3').on('click', function () {
                location.href = "index.html";
            });

        }
    };

 root.bigdraw = bigdraw;
}(window,window.jQuery || window.Zepto ));

<commit_msg>choid<commit_after>(function (root,$) {
    var vars = root.vars;
    var bigdraw ={};
    /* index */
    bigdraw.index ={
        init: function () {
            $(function () {
                FastClick.attach(document.body);
                $('.btn1').on('click', function () {
                    location.href = "create.html";
                });
            });
        }
    };

    /* create */
    bigdraw.create ={
        init:function () {
            var self = this;
            $(function () {
                FastClick.attach(document.body);

                self.evens();

            });
        },
        evens:function () {

            $('#sin').on('click', function () {
                var slc=$(this).attr('data-sin');
                $(this).attr('class','sin sin'+slc);
                $('#tin').attr('class','tin p'+slc);
                $('#tin').show();

            });

            $('.ys-opts .ys').on('click', function () {
                var me =this;
                var ys = $('.ys');
                $('#tin').hide();
                $('.dl-rlt').hide();
                var slc = $(this).attr('data-sin');
                var tips = $('#sin');
                $('#ys-choice').removeClass().addClass('ys-choice co'+slc);
                $.each(ys, function (i, v) {
                    if(v==me){
                        $(me).addClass('current');
                     }else{
                        $(v).removeClass('current');
                     }
                 });

                var sinClass=['sin' , 'sin'+slc , 'sin'+slc+'-tips','flipInCardY'].join(' ');
                tips.attr('class',sinClass);
                tips.attr('data-sin',slc);
                tips.removeClass().addClass(sinClass + ' animated').one(
                    'webkitAnimationEnd ' +
                    'mozAnimationEnd ' +
                    'MSAnimationEnd ' +
                    'oanimationend ' +
                    'animationend ',
                    function(){
                        $(this).removeClass('flipInCardY');
                    });

            });

            $(document.body).on('cvsImageData',function(evt,kind, bx64 ){
                bx64 = bx64 ||  vars.getLocalStorage('cvsImageData');
                kind = kind ||  vars.getLocalStorage('cvsImageKind');
                root.draw.upload(kind,bx64,function (rt) {
                    var data = rt && rt.data || "";
                    var cbUrl= bx64;
                    if(data && data.url) {
                        cbUrl = data.url || bx64;
                    }
                    vars.setLocalStorage('cvsImageUrl',cbUrl);
                    $('#sin').hide();
                    $('#tin').hide();

                    // var _timer = setTimeout(function () {

                        location.href = "rlt.html?kind=" +kind+"&url="+ cbUrl;

                    // },0);
                });
            });

            $('.btn2').on('click', function () {
                var sin = $('#sin').attr('data-sin');
                var wd  = $('#sin_input').val()||'';
                if(wd) {
                    if (wd.length > 10) {
                        wd = wd.substring(1,10);
                    }
                    draw.drawCanvas(wd, sin); //make photo
                }
            });

            var checkCountChar = function () {
                var txtAre =  $("#sin_input");
                var x = txtAre.val().length;
                if (x > 10) {
                    vars.showTip('最多输入10个字符',1000);
                }
                return x;
            };

            $("#sin_input").on('change keyup',function (e) {
                  checkCountChar();
            });

        }

    };

    bigdraw.rlt = {
        init: function () {
            var self = this;
            $(function () {
                FastClick.attach(document.body);
                var imgdata = vars.getLocalStorage('cvsImageData')||'';
                var imgUrl  = vars.getLocalStorage('cvsImageUrl')|| vars.getParam('url') || imgdata;
                var kind    = vars.getLocalStorage('cvsImageKind')|| vars.getParam('kind') || 3;
                var dlPic = $('#dl-pic');
                dlPic.attr('src',imgUrl);
                dlPic.removeClass().addClass('dl-pic dl-c'+kind);
                self.events();
                var indexpage = location.href;
                indexpage = indexpage.replace('rlt.html','index.html');
                window.initShareEvents({
                    'img_url': imgUrl,
                    'img_width': '100',
                    'img_height': '100',
                    'link': indexpage,
                    'desc': '现在朋友圈流行这样装逼',
                    'title':  '朋友圈大字'
                } );
            });
        },
        events:function () {
            $('.btn3').on('click', function () {
                location.href = "index.html";
            });

        }
    };

 root.bigdraw = bigdraw;
}(window,window.jQuery || window.Zepto ));

<|endoftext|>