<commit_before>import _ from 'koa-route'
import koa from 'koa'
import conf from '../conf'
import compose from 'koa-compose'
import Twit from 'twit'
import thunkify from 'thunkify'
import co from 'co'
import cache from 'memory-cache'

let app = koa()

export default app

let auth = function *(next) {
  //console.log(this.req.headers)
  //this.throw(401)
  yield next
}

let KEY = "demo_feed"

function sleep(ms) {
  return function (cb) {
    setTimeout(cb, ms);
  };
}

let fetchTwitterFeed = function *() {
  let Tw = new Twit({
    consumer_key: conf.Twitter.ConsumerKey,
    consumer_secret: conf.Twitter.ConsumerSecret,
    access_token: conf.Twitter.AccessToken,
    access_token_secret:conf.Twitter.AccessSecret
  })
  let get = thunkify(Tw.get.bind(Tw))
  let data = yield get('search/tweets', {q:'#procon26'})
  cache.put(KEY, data)
  console.log('cache updated %s', new Date())
}

co(function *(){
  for(;;){
    // refresh search results
    yield fetchTwitterFeed()
    yield sleep(1000*30)
  }
}).catch(console.error)

let getTwitterFeed = function *() {
  let data = cache.get(KEY)
  if (!data) {
    this.status = 204
    return
  }
  this.body = data
}

app.use(_.get('/social_feed/twitter', compose([auth, getTwitterFeed])))
<commit_msg>出力フォーマットを変更<commit_after>import _ from 'koa-route'
import koa from 'koa'
import conf from '../conf'
import compose from 'koa-compose'
import Twit from 'twit'
import thunkify from 'thunkify'
import co from 'co'
import cache from 'memory-cache'

let app = koa()

export default app

let auth = function *(next) {
  //console.log(this.req.headers)
  //this.throw(401)
  yield next
}

let KEY = "demo_feed"

function sleep(ms) {
  return function (cb) {
    setTimeout(cb, ms);
  };
}

let fetchTwitterFeed = function *() {
  let Tw = new Twit({
    consumer_key: conf.Twitter.ConsumerKey,
    consumer_secret: conf.Twitter.ConsumerSecret,
    access_token: conf.Twitter.AccessToken,
    access_token_secret:conf.Twitter.AccessSecret
  })
  let get = thunkify(Tw.get.bind(Tw))
  let data = yield get('search/tweets', {q:'#procon26'})
  cache.put(KEY, data[0])
  console.log('cache updated %s', new Date())
}

co(function *(){
  for(;;){
    // refresh search results
    yield fetchTwitterFeed()
    yield sleep(1000*30)
  }
}).catch(console.error)

let getTwitterFeed = function *() {
  let data = cache.get(KEY)
  if (!data) {
    this.status = 204
    return
  }
  this.body = data
}

app.use(_.get('/social_feed/twitter', compose([auth, getTwitterFeed])))
<|endoftext|>


<commit_before>module.exports = function (config) {
  var express = require('express');
  var passport = require('passport');
  var crypto = require('crypto');
  var async = require('async');
  var nodemailer = require('nodemailer');
  var i18n = require('i18n');
  var mcapi = require('mailchimp-api');

  var mc = new mcapi.Mailchimp(config.mailchimp.key);

  var User = require('../models/User');
  var Ticket = require('../models/Ticket');

  var _ = require('underscore');

  var router = express.Router();

  passport.use(User.createStrategy());
  passport.serializeUser(User.serializeUser());
  passport.deserializeUser(User.deserializeUser());

  router.get('/login', function (req,res) {
    res.render('login');
  });

  router.post('/login',  function (req, res) {
    return passport.authenticate('local', {
      successRedirect: req.session.lastPage,
      failureRedirect: '/login',
      failureFlash: i18n.__('Incorrect e-mail of wachtwoord')
    })(req,res);
  });

  router.get('/logout', function(req,res) {
    req.logout();
    res.redirect('/');
  });

  router.get('/register', function (req, res) {
    res.render('register', {verenigingen: config.verenigingen, opened:true, body:req.session.body || {}});
  });

  function subscribe(conf, cb) {
    mc.lists.subscribe(conf, function () { return cb(null); }, function (err) { return cb(err); });
  }

  router.post('/register', function (req, res, next) {

    // #AssumeTheWorst

    // if (req.body.email === undefined || !req.body.email.match(/@/i)) {
    //   req.flash('error', i18n.__('Geen geldig e-mailadres gegeven!'));
    //   return res.redirect('/login');
    // }

    // if (req.body.password === undefined ||
    //     req.body.confirm  === undefined ||
    //     (req.body.password !== req.body.confirm)) {
    //   req.flash('error', i18n.__('De wachtwoorden kwamen niet overeen!'));
    //   return res.redirect('/login');
    // }

    // if (req.body.firstname === undefined || )

    req.checkBody('code',      i18n.__('Geen activatiecode gegeven.')).notEmpty();
    req.checkBody('firstname', i18n.__('Geen voornaam gegeven.')).notEmpty();
    req.checkBody('surname',   i18n.__('Geen achternaam gegeven.')).notEmpty();
    req.checkBody('email',     i18n.__('Geen e-mailadres gegeven.')).notEmpty();
    req.checkBody('email',     i18n.__('Geen valide e-mailadres gegeven.')).isEmail();
    req.checkBody('password',  i18n.__('Wachtwoord moet minstens 5 karakters lang zijn')).len(5);
    req.checkBody('password',  i18n.__('Wachtwoordden verschillen.')).equals(req.body.confirm);
    req.checkBody('vereniging',i18n.__('Geen vereniging gegeven.')).notEmpty();
    req.checkBody('vereniging',i18n.__('Geen valide vereniging gegeven.')).isIn(Object.keys(config.verenigingen));

    req.body.bus = req.body.bus || false;
    req.body.vegetarian = req.body.vegetarian || false;
    req.body.subscribe = req.body.subscribe || false;
    req.sanitize('bus').toBoolean();
    req.sanitize('vegetarian').toBoolean();
    req.sanitize('subscribe').toBoolean();

    console.log(req.body);
    var errors = req.validationErrors();

    if (errors) {

      var msg = '';
      errors.forEach(function (err) {
        req.flash('error', err.msg);
      });
      req.session.body = req.body;
      return res.redirect('/register');
    }

    var user = new User({
      firstname: req.body.firstname,
      surname: req.body.surname,
      vereniging: req.body.vereniging,
      email: req.body.email,
      bus: req.body.bus,
      vegetarian: req.body.vegetarian,
      specialNeeds: req.body.specialNeeds
    });

    async.waterfall([
      function (next) {
        Ticket.findById(req.body.code).populate('ownedBy').exec(next);
      },
      function (ticket, next) {
        if (ticket) {
          if(ticket.ownedBy) {
            next(new Error(i18n.__('Dit ticket is al geactiveerd!')));
          } else {
            user.ticket = ticket;
            User.register(user, req.body.password, function (err, user) {
              next(err, ticket, user);
            });
          }
        } else {
          next(new Error(i18n.__('Geen geldige activatiecode gegeven!')));
        }
      },
      function (ticket,user, next) {
        ticket.ownedBy = user;
        ticket.save(function (err, ticket, numAffected) {
          next(err,user);
        });
      },
      function (user,next) {
        req.login(user,next);
      },
      function (next) {
        if (req.body.subscribe) {
          subscribe({id:config.mailchimp.id, email:{email:req.body.email}, double_optin: false, send_welcome: true}, next);
        } else {
          next(null);
        }
      }
    ], function (err) {
      if (err) {
        req.flash('error', err.message || err.error || 'Error');
        console.log(err.stack);
        req.session.body = req.body;
        return res.redirect('/register');
      } else {
        req.flash('success', i18n.__('Je bent succesvol geregistreerd!'));
        return res.redirect('/profile');
      }
    });
  });

var transport = nodemailer.createTransport('SMTP', {
    resolveHostname: true,
    host: config.email.host,
    secureConnection: true,
    port: config.email.port,
    auth: {
      user: config.email.auth.user,
      pass: config.email.auth.pass
    },
  });

  router.get('/forgot', function(req, res) {
    res.render('forgot', {
      user: req.user
    });
  });

  /// forgot password
  router.post('/forgot', function (req, res, next) {
    async.waterfall([
      function (done) {
        crypto.randomBytes(20, function (err, buf) {
          done(err, buf.toString('hex'));
        });
      },
      function (token, done) {
        User.findOne({ email: req.body.email}, function (err, user) {
          if (!user) {
            req.flash('error', i18n.__('Er lijkt geen gebruiker met dit e-mail adres in ons systeem te zijn.', req.email));
            return res.redirect('/forgot');
          }
          user.resetPasswordToken = token;
          user.resetPasswordExpires = Date.now() + 3600000;
          user.save(function (err) {
            done(err, token, user);
          });
        });
      },
      function (token, user, done) {
        var mailOptions = {
          to: user.email,
          from: config.email.auth.user,
          subject: i18n.__('Wachtwoord resetten'),
          text: i18n.__('Je hebt deze e-mail ontvangen omdat jij (of ieman anders) een wachtwoordreset hebt aangevraagd. \n\n' +
                        'Klik op de volgende link of plak hem in de adresbalk van je browser om het proces te voltooien: %s://%s/reset/%s\n\n'+
                        'Als jij deze wachtwoordreset niet hebt aangevraagd, negeer dan deze e-mail en je wachtwoord zal onveranderd blijven.\n\n',
                        req.protocol, req.get('host'), token)
        };

        transport.sendMail(mailOptions, function (err) {
          req.flash('info', i18n.__('Een e-mail is gestuurd naar %s met verdere instructies om je wachtwoord te resetten', user.email));
          done(err, 'done');
        });
      }
    ], function (err) {
      if (err) {
        return next(err);
      }
      res.redirect('/forgot');
    });
  });

  router.get('/reset/:token', function (req, res) {
    User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: {$gt : Date.now() } }, function (err, user) {
      if (!user) {
        req.flash('error', i18n.__('Wachtwoord reset token is invalid.'));
        return res.redirect('/forgot');
      }
    });
    res.render('reset', { user: req.user });
  });

  router.post('/reset/:token', function (req, res, next) {
    async.waterfall([
      function (done) {
        User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
          if (!user) {
            req.flash('error', 'Wachtwoord reset token is invalid.');
            return res.redirect('back');
          }
          user.setPassword(req.body.password, function(err, user) {
            user.resetPasswordToken = undefined;
            user.resetPasswordExpires = undefined;

            user.save(function (err) {
              if (err) { return done(err); }
              req.login(user, function (err) {
                console.log(err);
                done(err, user);
              });
            });
          });
        });
      },
      function (user, done) {
        var mailOptions = {
          to: user.email,
          from: config.email.auth.user,
          subject: i18n.__('Je wachtwoord is veranderd!'),
          text: i18n.__('Hallo,\n\n Dit is een bevestiging dat he wacthwoord voor %s is veranerd.\n', user.email),
        };
        transport.sendMail(mailOptions, function (err) {
          req.flash('success', 'Je wachtwoord is veranderd.');
          done(err);
        });
      }
    ], function (err) {
      if (err) {
        return next(err);
      }
      res.redirect('/forgot');
    });
  });

  router.post('/mailing', function (req,res) {
    subscribe({id:config.mailchimp.id, email:{email:req.body.email}}, function (err) {
      if (err) {
        req.flash('error', 'Registration failed.');
      } else {
        req.flash('success',  'Success!');
      }
      res.redirect('/mailing');
    });
  });
  return router;
};
<commit_msg>fix the bug with double mails<commit_after>module.exports = function (config) {
  var express = require('express');
  var passport = require('passport');
  var crypto = require('crypto');
  var async = require('async');
  var nodemailer = require('nodemailer');
  var i18n = require('i18n');
  var mcapi = require('mailchimp-api');

  var mc = new mcapi.Mailchimp(config.mailchimp.key);

  var User = require('../models/User');
  var Ticket = require('../models/Ticket');

  var _ = require('underscore');

  var router = express.Router();

  passport.use(User.createStrategy());
  passport.serializeUser(User.serializeUser());
  passport.deserializeUser(User.deserializeUser());

  router.get('/login', function (req,res) {
    res.render('login');
  });

  router.post('/login',  function (req, res) {
    return passport.authenticate('local', {
      successRedirect: req.session.lastPage,
      failureRedirect: '/login',
      failureFlash: i18n.__('Incorrect e-mail of wachtwoord')
    })(req,res);
  });

  router.get('/logout', function(req,res) {
    req.logout();
    res.redirect('/');
  });

  router.get('/register', function (req, res) {
    res.render('register', {verenigingen: config.verenigingen, opened:true, body:req.session.body || {}});
  });

  function subscribe(conf, cb) {
    mc.lists.subscribe(conf, function () { return cb(null); }, function (err) { return cb(err); });
  }

  router.post('/register', function (req, res, next) {

    // #AssumeTheWorst

    // if (req.body.email === undefined || !req.body.email.match(/@/i)) {
    //   req.flash('error', i18n.__('Geen geldig e-mailadres gegeven!'));
    //   return res.redirect('/login');
    // }

    // if (req.body.password === undefined ||
    //     req.body.confirm  === undefined ||
    //     (req.body.password !== req.body.confirm)) {
    //   req.flash('error', i18n.__('De wachtwoorden kwamen niet overeen!'));
    //   return res.redirect('/login');
    // }

    // if (req.body.firstname === undefined || )

    req.checkBody('code',      i18n.__('Geen activatiecode gegeven.')).notEmpty();
    req.checkBody('firstname', i18n.__('Geen voornaam gegeven.')).notEmpty();
    req.checkBody('surname',   i18n.__('Geen achternaam gegeven.')).notEmpty();
    req.checkBody('email',     i18n.__('Geen e-mailadres gegeven.')).notEmpty();
    req.checkBody('email',     i18n.__('Geen valide e-mailadres gegeven.')).isEmail();
    req.checkBody('password',  i18n.__('Wachtwoord moet minstens 5 karakters lang zijn')).len(5);
    req.checkBody('password',  i18n.__('Wachtwoordden verschillen.')).equals(req.body.confirm);
    req.checkBody('vereniging',i18n.__('Geen vereniging gegeven.')).notEmpty();
    req.checkBody('vereniging',i18n.__('Geen valide vereniging gegeven.')).isIn(Object.keys(config.verenigingen));

    req.body.bus = req.body.bus || false;
    req.body.vegetarian = req.body.vegetarian || false;
    req.body.subscribe = req.body.subscribe || false;
    req.sanitize('bus').toBoolean();
    req.sanitize('vegetarian').toBoolean();
    req.sanitize('subscribe').toBoolean();

    var errors = req.validationErrors();

    if (errors) {

      var msg = '';
      errors.forEach(function (err) {
        req.flash('error', err.msg);
      });
      req.session.body = req.body;
      return res.redirect('/register');
    }

    var user = new User({
      firstname: req.body.firstname,
      surname: req.body.surname,
      vereniging: req.body.vereniging,
      email: req.body.email,
      bus: req.body.bus,
      vegetarian: req.body.vegetarian,
      specialNeeds: req.body.specialNeeds
    });

    async.waterfall([
      function (next) {
        Ticket.findById(req.body.code).populate('ownedBy').exec(next);
      },
      function (ticket, next) {
        if (ticket) {
          if(ticket.ownedBy) {
            next(new Error(i18n.__('Dit ticket is al geactiveerd!')));
          } else {
            user.ticket = ticket;
            User.register(user, req.body.password, function (err, user) {
              next(err, ticket, user);
            });
          }
        } else {
          next(new Error(i18n.__('Geen geldige activatiecode gegeven!')));
        }
      },
      function (ticket,user, next) {
        ticket.ownedBy = user;
        ticket.save(function (err, ticket, numAffected) {
          next(err,user);
        });
      },
      function (user,next) {
        req.login(user,next);
      },
      function (next) {
        if (req.body.subscribe) {
          subscribe({id:config.mailchimp.id, email:{email:req.body.email}, double_optin: false, send_welcome: true}, next);
        } else {
          next(null);
        }
      }
    ], function (err) {
      if (err) {
        req.flash('error', err.message || err.error || 'Error');
        console.log(err.stack);
        req.session.body = req.body;
        return res.redirect('/register');
      } else {
        req.flash('success', i18n.__('Je bent succesvol geregistreerd!'));
        return res.redirect('/profile');
      }
    });
  });

var transport = nodemailer.createTransport('SMTP', {
    resolveHostname: true,
    host: config.email.host,
    secureConnection: true,
    port: config.email.port,
    auth: {
      user: config.email.auth.user,
      pass: config.email.auth.pass
    },
  });

  router.get('/forgot', function(req, res) {
    res.render('forgot', {
      user: req.user
    });
  });

  /// forgot password
  router.post('/forgot', function (req, res, next) {
    async.waterfall([
      function (done) {
        crypto.randomBytes(20, function (err, buf) {
          done(err, buf.toString('hex'));
        });
      },
      function (token, done) {
        User.findOne({ email: req.body.email}, function (err, user) {
          if (!user) {
            req.flash('error', i18n.__('Er lijkt geen gebruiker met dit e-mail adres in ons systeem te zijn.', req.email));
            return res.redirect('/forgot');
          }
          user.resetPasswordToken = token;
          user.resetPasswordExpires = Date.now() + 3600000;
          user.save(function (err) {
            done(err, token, user);
          });
        });
      },
      function (token, user, done) {
        var mailOptions = {
          to: user.email,
          from: config.email.auth.user,
          subject: i18n.__('Wachtwoord resetten'),
          text: i18n.__('Je hebt deze e-mail ontvangen omdat jij (of ieman anders) een wachtwoordreset hebt aangevraagd. \n\n' +
                        'Klik op de volgende link of plak hem in de adresbalk van je browser om het proces te voltooien: %s://%s/reset/%s\n\n'+
                        'Als jij deze wachtwoordreset niet hebt aangevraagd, negeer dan deze e-mail en je wachtwoord zal onveranderd blijven.\n\n',
                        req.protocol, req.get('host'), token)
        };

        transport.sendMail(mailOptions, function (err) {
          req.flash('info', i18n.__('Een e-mail is gestuurd naar %s met verdere instructies om je wachtwoord te resetten', user.email));
          done(err, 'done');
        });
      }
    ], function (err) {
      if (err) {
        return next(err);
      }
      res.redirect('/forgot');
    });
  });

  router.get('/reset/:token', function (req, res) {
    User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: {$gt : Date.now() } }, function (err, user) {
      if (!user) {
        req.flash('error', i18n.__('Wachtwoord reset token is invalid.'));
        return res.redirect('/forgot');
      }
    });
    res.render('reset', { user: req.user });
  });

  router.post('/reset/:token', function (req, res, next) {
    async.waterfall([
      function (done) {
        User.findOne({ resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
          if (!user) {
            req.flash('error', 'Wachtwoord reset token is invalid.');
            return res.redirect('back');
          }
          user.setPassword(req.body.password, function(err, user) {
            user.resetPasswordToken = undefined;
            user.resetPasswordExpires = undefined;

            user.save(function (err) {
              if (err) { return done(err); }
              req.login(user, function (err) {
                console.log(err);
                done(err, user);
              });
            });
          });
        });
      },
      function (user, done) {
        var mailOptions = {
          to: user.email,
          from: config.email.auth.user,
          subject: i18n.__('Je wachtwoord is veranderd!'),
          text: i18n.__('Hallo,\n\n Dit is een bevestiging dat he wacthwoord voor %s is veranerd.\n', user.email),
        };
        transport.sendMail(mailOptions, function (err) {
          req.flash('success', 'Je wachtwoord is veranderd.');
          done(err);
        });
      }
    ], function (err) {
      if (err) {
        return next(err);
      }
      res.redirect('/forgot');
    });
  });

  router.post('/mailing', function (req,res) {
    subscribe({id:config.mailchimp.id, email:{email:req.body.email}}, function (err) {
      if (err) {
        req.flash('error', 'Registration failed.');
      } else {
        req.flash('success',  'Success!');
      }
      res.redirect('/mailing');
    });
  });
  return router;
};
<|endoftext|>


<commit_before>'use strict';

var config = require('../config');
var twilio = require('twilio');
var client = twilio(config.accountSid, config.authToken);

module.exports = function(app) {
  app.post('/call', function(req, res) {
    console.log(req.body.phoneNumber);
    client.makeCall({
            to: req.body.phoneNumber,
            from: config.twilioNumber,
            url: process.env.URL + '/outbound'
        }, function(err) {
          console.log(err);
          if (err) {
            res.status(500).send(err);
          } else {
            res.send({
                    message: 'Thank you! We will be calling you shortly.'
                });
          }
        });
  });

  app.post('/outbound/:firstName/:lastName/:phoneNumber/', function(req, res) {
        // We could use twilio.TwimlResponse, but Jade works too - here's how
        // we would render a TwiML (XML) response using Jade
    console.log('twilio request: ' + req.body.CallSid);
    res.type('text/xml');
    res.render('outbound', {firstName: req.params.firstName, lastName: req.params.lastName, phoneNumber: req.params.phoneNumber});
  });
  app.post('/outboundNoConcierge/:firstName/:lastName/', function(req, res) {
        // We could use twilio.TwimlResponse, but Jade works too - here's how
        // we would render a TwiML (XML) response using Jade
    console.log('twilio request:' + req.body.CallSid);
    res.type('text/xml');
    res.render('outboundNoConcierge', {firstName: req.params.firstName, lastName: req.params.lastName});
  });
};
<commit_msg>callback wip<commit_after>'use strict';

var config = require('../config');
var twilio = require('twilio');
var client = twilio(config.accountSid, config.authToken);

module.exports = function(app) {
  app.post('/call', function(req, res) {
    console.log(req.body.phoneNumber);
    client.makeCall({
            to: req.body.phoneNumber,
            from: config.twilioNumber,
            StatusCallBack: process.env.URL + '/StatusCallBack',
            url: process.env.URL + '/outbound'
        }, function(err) {
          console.log(err);
          if (err) {
            res.status(500).send(err);
          } else {
            res.send({
                    message: 'Thank you! We will be calling you shortly.'
                });
          }
        });
  });

  app.post('/outbound/:firstName/:lastName/:phoneNumber/', function(req, res) {
        // We could use twilio.TwimlResponse, but Jade works too - here's how
        // we would render a TwiML (XML) response using Jade
    console.log('twilio request: ' + req.body.CallSid);
    res.type('text/xml');
    res.render('outbound', {firstName: req.params.firstName, lastName: req.params.lastName, phoneNumber: req.params.phoneNumber});
  });
  app.post('/outboundNoConcierge/:firstName/:lastName/', function(req, res) {
        // We could use twilio.TwimlResponse, but Jade works too - here's how
        // we would render a TwiML (XML) response using Jade
    console.log('twilio request:' + req.body.CallSid);
    res.type('text/xml');
    res.render('outboundNoConcierge', {firstName: req.params.firstName, lastName: req.params.lastName});
  });
};
<|endoftext|>


<commit_before>// Post view
var express = require('express')
var router = express.Router()
var prompts = require('../server/seeders/prompts')

/* Post story page */
router.get('/', function (req, res, next) {
  req.HTTP.get('/api/prompts').then(function (response) {
    console.log(response.data)
    res.render('post', {
      title: 'Share a story',
      prompts: JSON.stringify(response.data)
    })
  }, function (err) {
    console.error('error getting stories: ')
    console.error(err)
  })
})

router.post('/', function (req, res, next) {
  // Variables are in req.body.prompt and req.body.story
  // Route to about page
  var story = {
    promptId: req.body.promptId,
    text: req.body.story
  }
  // res.render('thanks', {
  //   title: 'Thank You'
  // })
  req.HTTP.post('/api/stories', story).then(function (response) {
    console.log(response.data)
    res.render('thanks', {
      title: 'Thank You'
    })
  }, function (err) {
    console.error('error posting story :( ')
    console.error(err)
  })
})

module.exports = router
<commit_msg>load prompts from db<commit_after>// Post view
var express = require('express')
var router = express.Router()

/* Post story page */
router.get('/', function (req, res, next) {
  req.HTTP.get('/api/prompts').then(function (response) {
    console.log(response.data)
    res.render('post', {
      title: 'Share a story',
      prompts: JSON.stringify(response.data)
    })
  }, function (err) {
    console.error('error getting stories: ')
    console.error(err)
  })
})

router.post('/', function (req, res, next) {
  // Variables are in req.body.prompt and req.body.story
  // Route to about page
  var story = {
    promptId: req.body.promptId,
    text: req.body.story
  }
  // res.render('thanks', {
  //   title: 'Thank You'
  // })
  req.HTTP.post('/api/stories', story).then(function (response) {
    console.log(response.data)
    res.render('thanks', {
      title: 'Thank You'
    })
  }, function (err) {
    console.error('error posting story :( ')
    console.error(err)
  })
})

module.exports = router
<|endoftext|>


<commit_before>import {Project} from '../app/project'
import {RouteManager} from '../app/routeManager'
import {it} from 'jasmine-await'

const mockProject = new Project({
  project: {
    routeHandlers: () => ({
      testHandler1: {
        handles: async () => ['a'],
        handlesArguments: async () => ({}),
      }
    })
  }
})

describe('RouteManager', () => {
  it('returns handled url list', async () => {
    const routeManager = new RouteManager({project: mockProject})
    const handledUrls = await routeManager.handledUrls()
    expect(handledUrls.length).toEqual(1)
  })
})
<commit_msg>Make eslint happy<commit_after>import {Project} from '../app/project'
import {RouteManager} from '../app/routeManager'
import {it} from 'jasmine-await'

const mockProject = new Project({
  project: {
    routeHandlers: () => ({
      testHandler1: {
        handles: async () => ['a'],
        handlesArguments: async () => ({})
      }
    })
  }
})

describe('RouteManager', () => {
  it('returns handled url list', async () => {
    const routeManager = new RouteManager({project: mockProject})
    const handledUrls = await routeManager.handledUrls()
    expect(handledUrls.length).toEqual(1)
  })
})
<|endoftext|>


<commit_before>var config = require("config");
var utility = require('../utility');
var classMapping = config.get('classes');

module.exports = function(accuser) {
  var addressBookLevel1 = accuser.addRepository('nus-cs2103-AY1617S1', 'addressbook-level1');
  var FormatCheckLabel = "FormatCheckRequested";

  var warnInvalidTitle = function(repo, issue) {
    if (hasNoFormatCheckRequestedLabel(issue)) {
      return;
    }

    console.log("Adding warning for format fail to PR #" + issue.number);
    accuser.addLabels(repo, issue, ["FormatCheckRequested"]);
    var comment = "Hi @" + issue.user.login + ", your pull request title is invalid."
      + " It should be in the format of `[Activity ID][Team ID] Your name`,"
      + " where `[Activity Id]` has no dashes or spaces (e.g. `[T2A3]` stands"
      + " for Tutorial 2 Activity 3) and `[Team ID]` has one dash only and no"
      + " spaces (e.g. `[W14-A2]` means Wednesday 2pm (14 hrs), Phase A, Team 2)."
      + " Please follow the instructions given strictly and edit your title for reprocessing."
      + "\n\nNote that this comment is posted by a bot sorting all the pull request submissions."
    accuser.comment(repo, issue, comment);
  };

  var hasNoFormatCheckRequestedLabel = function(issue) {
    var result = true;
    issue.labels.forEach(function(label){
      if (label.name === FormatCheckLabel) {
        result = false;
      }
    });
    return result;
  };

  addressBookLevel1.newWorker()
    .filter(function(repository, issue){
      // ensure that we only work with PRs that do not have an assignee
      return issue.pull_request;
    })
    .do(function(repository, issue) {
      var result = utility._titleRegex.exec(issue.title);

      if (result === null) {
        // we ignore the PR if we cannot parse the title into our issuee-defined regex
        warnInvalidTitle(repository, issue);
        return;
      }

      var activityId = result[1];
      var classId = result[2];
      var teamId = result[4];

      if (!classMapping[classId]) {
        // the class ID fetched is invalid.
        warnInvalidTitle(repository, issue);
        return;
      }

      var tutor = classMapping[classId][teamId];
      if (tutor) {
        if (hasNoFormatCheckRequestedLabel(issue)) {
          console.log("Removing format check label from PR #" + issue.number);
          accuser.removeLabel(repository, issue, FormatCheckLabel);
        }

        console.log("Assigning tutors to PR #" + issue.number);
        accuser.accuse(repository, issue, tutor);
      }
    });
};
<commit_msg>minor fix for checking label<commit_after>var config = require("config");
var utility = require('../utility');
var classMapping = config.get('classes');

module.exports = function(accuser) {
  var addressBookLevel1 = accuser.addRepository('nus-cs2103-AY1617S1', 'addressbook-level1');
  var FormatCheckLabel = "FormatCheckRequested";

  var warnInvalidTitle = function(repo, issue) {
    if (hasFormatCheckRequestedLabel(issue)) {
      return;
    }

    console.log("Adding warning for format fail to PR #" + issue.number);
    accuser.addLabels(repo, issue, ["FormatCheckRequested"]);
    var comment = "Hi @" + issue.user.login + ", your pull request title is invalid."
      + " It should be in the format of `[Activity ID][Team ID] Your name`,"
      + " where `[Activity Id]` has no dashes or spaces (e.g. `[T2A3]` stands"
      + " for Tutorial 2 Activity 3) and `[Team ID]` has one dash only and no"
      + " spaces (e.g. `[W14-A2]` means Wednesday 2pm (14 hrs), Phase A, Team 2)."
      + " Please follow the instructions given strictly and edit your title for reprocessing."
      + "\n\nNote that this comment is posted by a bot sorting all the pull request submissions."
    accuser.comment(repo, issue, comment);
  };

  var hasFormatCheckRequestedLabel = function(issue) {
    var result = false;
    issue.labels.forEach(function(label){
      if (label.name.toLowerCase() == FormatCheckLabel.toLowerCase()) {
        result = true;
      }
    });
    return result;
  };

  addressBookLevel1.newWorker()
    .filter(function(repository, issue){
      // ensure that we only work with PRs that do not have an assignee
      return issue.pull_request;
    })
    .do(function(repository, issue) {
      var result = utility._titleRegex.exec(issue.title);

      if (result === null) {
        // we ignore the PR if we cannot parse the title into our issuee-defined regex
        warnInvalidTitle(repository, issue);
        return;
      }

      var activityId = result[1];
      var classId = result[2];
      var teamId = result[4];

      if (!classMapping[classId]) {
        // the class ID fetched is invalid.
        warnInvalidTitle(repository, issue);
        return;
      }

      var tutor = classMapping[classId][teamId];
      if (tutor) {
        if (hasFormatCheckRequestedLabel(issue)) {
          console.log("Removing format check label from PR #" + issue.number);
          accuser.removeLabel(repository, issue, FormatCheckLabel);
        }

        console.log("Assigning tutors to PR #" + issue.number);
        accuser.accuse(repository, issue, tutor);
      }
    });
};
<|endoftext|>


<commit_before>(function ($) {
    "use strict";

    Mapbender.Digitizer = Mapbender.Digitizer || {};

    $.fn.dataTable.ext.errMode = 'throw';

    /**
     * Escape HTML chars
     * @returns {string}
     */
    String.prototype.escapeHtml = function () {

        return this.replace(/["&'\/<>]/g, function (a) {
            return {
                '"': '"',
                '&': '&',
                "'": ''',
                '/': '/',
                '<': '<',
                '>': '>'
            }[a];
        });
    };

    $.widget("mapbender.mbDigitizer", {

        options: {
            classes: {},
            create: null,
            debug: false,
            // disabled: false,
            fileURI: "uploads/featureTypes",
            schemes: {},
            target: null,
        },
        schemes: null,
        map: null,

        styles: {
            'default': {
                strokeWidth: 1,
                strokeColor: '#6fb536',
                fillColor: "#6fb536",
                fillOpacity: 0.3
                //, label: '${label}'
            },
            'select': {
                strokeWidth: 3,
                fillColor: "#F7F79A",
                strokeColor: '#6fb536',
                fillOpacity: 0.5,
                graphicZIndex: 15
            },
            // 'selected': {
            //     strokeWidth: 3,
            //     fillColor: "#74b1f7",
            //     strokeColor: '#b5ac14',
            //     fillOpacity: 0.7,
            //     graphicZIndex: 15
            // },
            'copy': {
                strokeWidth: 5,
                fillColor: "#f7ef7e",
                strokeColor: '#4250b5',
                fillOpacity: 0.7,
                graphicZIndex: 1000
            },
            'unsaved': {
                strokeWidth: 3,
                fillColor: "#FFD14F",
                strokeColor: '#F5663C',
                fillOpacity: 0.5
            },

            'invisible': {
                display: 'none'
            },

            'labelText': {
                strokeWidth: 0,
                fillColor: '#cccccc',
                fillOpacity: 0,
                strokeColor: '#5e1a2b',
                strokeOpacity: 0,
                pointRadius: 15,
                label: '${label}',
                fontSize: 15
            },
            'labelTextHover': {
                strokeWidth: 0,
                fillColor: '#cccccc',
                strokeColor: '#2340d3',
                fillOpacity: 1,
                pointRadius: 15,
                label: '${label}',
                fontSize: 15
            },

        },
        printClient: null,

        useAllScheme: true,

        displayOnInactive: false,

        openLayersCloudImagePath: null,

        disabled: true,

        isFullyActive: true,

        _create: function () {

            var widget = this.widget = this;
            var element = widget.element;

            widget.id = element.attr("id");

            if (!Mapbender.checkTarget("mbDigitizer", widget.options.target)) {
                return;
            }

            if (typeof widget.options.useAllScheme !== "undefined") {
                widget.useAllScheme = widget.options.useAllScheme;
            }

            widget.openLayersCloudImagePath = widget.options.openLayersCloudImagePath;

            widget.displayOnInactive = widget.options.displayOnInactive;

            widget.dataManager = Mapbender.elementRegistry.listWidgets()['mapbenderMbDataManager'];

            var qe = new Mapbender.Digitizer.QueryEngine(widget);
            widget.query = qe.query;
            widget.getElementURL = qe.getElementURL;

            var createSpinner = function() {

                widget.spinner = new function () {
                    var spinner = this;

                    spinner.openRequests = 0;

                    var $parent = $('#' + widget.id).parents('.container-accordion').prev().find('.tablecell').prepend("

");
                    spinner.$element = $parent.find(".spinner");

                    spinner.addRequest = function () {
                        spinner.openRequests++;
                        if (spinner.openRequests >= 1) {
                            spinner.$element.show();
                        }
                    };

                    spinner.removeRequest = function () {
                        spinner.openRequests--;
                        if (spinner.openRequests === 0) {
                            spinner.$element.hide();
                        }
                    };

                };
            };

            createSpinner();

            Mapbender.elementRegistry.waitReady(widget.options.target).then(widget.setup.bind(widget));

            Mapbender.elementRegistry.waitCreated('.mb-element-printclient').then(function (printClient) {
                widget.printClient = printClient;
                $.extend(widget.printClient, Mapbender.Digitizer.printPlugin);
            });
        },

        setup: function () {
            var widget = this;
            var element = $(widget.element);
            var options = widget.options;
            widget.selector = $("select.selector", element);

            widget.map = $('#' + options.target).data('mapbenderMbMap').map.olMap;

            // TODO Kanonen->Spatzen: refactoring
            var initializeActivationContainer = function () {

                var containerInfo = new MapbenderContainerInfo(widget, {
                    onactive: function () {
                        widget.activate();
                    },
                    oninactive: function () {
                        widget.deactivate();
                    }
                });

                return containerInfo;

            };

            var initializeSelectorOrTitleElement = function () {

                var options = widget.options;
                var element = $(widget.element);
                var titleElement = $("> div.title", element);

                widget.hasOnlyOneScheme = _.size(options.schemes) === 1;

                if (widget.hasOnlyOneScheme) {
                    titleElement.html(_.toArray(options.schemes)[0].label);
                    widget.selector.hide();
                } else {
                    titleElement.hide();
                }
            };

            var usesAllScheme = function() {
                return !widget.hasOnlyOneScheme && widget.useAllScheme;
            };

            // TODO this is not the proper implementation - fix that
            var isOpenByDefault = function() {
                var sidePane = $(widget.element).closest(".sidePane");

                var accordion = $(".accordionContainer", sidePane);
                return accordion.length === 0;
            };

            var createSchemes = function () {

                var createSchemaOption = function (schema) {
                    var option = $("<option/>");
                    option.val(schema.schemaName).html(schema.label);
                    option.data("schemaSettings", schema);
                    return option;

                };

                var rawSchemes = widget.options.schemes;
                widget.schemes = {};
                var index = 0;
                _.each(rawSchemes, function (rawScheme, schemaName) {
                    rawScheme.schemaName = schemaName;
                    widget.schemes[schemaName] = new Mapbender.Digitizer.Scheme(rawScheme, widget, index++);
                    widget.selector.append(createSchemaOption(widget.schemes[schemaName]));
                });

                var basicScheme = Object.keys(widget.schemes)[0];

                if (usesAllScheme()) {
                    widget.schemes['all'] = new Mapbender.Digitizer.AllScheme({
                        label: Mapbender.DigitizerTranslator.translate('schema.allgeometries'),
                        schemaName: 'all'
                    }, widget, index++);
                    widget.selector.prepend(createSchemaOption(widget.schemes['all']));
                    basicScheme = 'all';
                }

                widget.selector.val(basicScheme);

                if (isOpenByDefault()) {
                    widget.activate();
                }

            };

            var createMapContextMenu = function () {
                var map = widget.map;

                var options = {
                    selector: 'div',
                    events: {
                        show: function (options) {
                            return widget.isFullyActive && widget.getCurrentSchema && widget.getCurrentSchema().mapContextMenu.allowUseContextMenu(options);
                        }
                    },
                    build: function (trigger, e) {
                        return widget.isFullyActive && widget.getCurrentSchema && widget.getCurrentSchema().mapContextMenu.buildContextMenu(trigger, e);
                    }
                };

                $(map.div).contextMenu(options);

            };

            var createElementContextMenu = function () {
                var element = $(widget.element);

                var options = {
                    position: function (opt, x, y) {
                        opt.$menu.css({top: y, left: x + 10});
                    },
                    selector: '.mapbender-element-result-table > div > table > tbody > tr',
                    events: {
                        show: function (options) {
                            return widget.getCurrentSchema && widget.getCurrentSchema().elementContextMenu.allowUseContextMenu(options);
                        }
                    },
                    build: function (trigger, e) {
                        return widget.getCurrentSchema && widget.getCurrentSchema().elementContextMenu.buildContextMenu(trigger, e);
                    }
                };

                $(element).contextMenu(options);

            };

            var initializeSelector = function () {
                var selector = widget.selector;

                selector.on('change', widget.onSelectorChange);

            };

            initializeSelectorOrTitleElement();

            widget.onSelectorChange = function () { // Do not implement in prototype because of static widget access
                var selector = widget.selector;

                var option = selector.find(":selected");
                var newSchema = option.data("schemaSettings");

                widget.getCurrentSchema && widget.getCurrentSchema().deactivateSchema();

                newSchema.activateSchema();
            };

            initializeSelector();

            createSchemes();

            initializeActivationContainer();

            createMapContextMenu();

            createElementContextMenu();

            // widget.map.div.oncontextmenu = function(e) {
            //
            //     if(!e){ //dear IE...
            //         var e = window.event;
            //         e.returnValue = false;
            //     }
            //     var f = widget.getCurrentSchema().layer.getFeatureFromEvent(e);
            //     alert(f);
            //     //f is the pointed vector.feature :)
            //
            //     return false; //Prevent display of browser context menu
            // };

            widget.registerMapEvents();

           widget._trigger('ready');

           if(widget.displayOnInactive) {
               widget.activate();
               widget.isFullyActive = false;
               widget.getCurrentSchema().selectControl.deactivate();
           }

        },

        disable: function() {
          var widget = this;
          widget.disabled = true;
        },

        enable: function() {
            var widget = this;
            widget.disabled = false;
        },

        isEnabled: function() {
            var widget = this;
            return !widget.disabled;
        },

        registerMapEvents: function () {
            var widget = this;
            var map = widget.map;

            map.events.register("moveend", this, function () {
                widget.isEnabled() && widget.getCurrentSchema().getData();
            });
            map.events.register("zoomend", this, function () {
                widget.isEnabled() && widget.getCurrentSchema().getData({ zoom: true});
            });

            map.events.register("mouseover", this, function() {
                widget.isEnabled() && widget.getCurrentSchema().mapContextMenu.enable();
            });

            map.events.register("mouseout", this, function() {
                widget.isEnabled() && widget.getCurrentSchema().mapContextMenu.disable();
            });
            map.resetLayersZIndex();
        },

        getOpenLayersCloudImagePath: function() {
            var widget = this;
            return widget.openLayersCloudImagePath ? Mapbender.Digitizer.Utilities.getAssetsPath(widget.openLayersCloudImagePath) : OpenLayers.ImgPath;
        },

        getBasicSchemes: function () {
            var widget = this;

            return _.pick(widget.schemes, function (value, key) {
                return key !== "all";
            });
        },

        getSchemaByName: function (schemaName) {
            var widget = this;
            var scheme = widget.getBasicSchemes()[schemaName];
            if (!scheme) {
                throw new Error("No Basic Scheme exists with the name " + schemaName);
            }
            return scheme;
        },

        activate: function () {
            var widget = this;
            widget.enable();
            widget.isFullyActive = true;
            widget.onSelectorChange(); // triggers schema activation

        },

        deactivate: function () {
            var widget = this;
            widget.disable();
            widget.isFullyActive = false;
            widget.getCurrentSchema && widget.getCurrentSchema().deactivateSchema();
        },

        // TODO muss repariert werden
        refreshConnectedDigitizerFeatures: function (featureTypeName) {
            var widget = this;
            $(".mb-element-digitizer").not(".mb-element-data-manager").each(function (index, element) {
                var schemes = widget.schemes;
                schemes[featureTypeName] && schemes[featureTypeName].layer && schemes[featureTypeName].layer.getData();
            })

        },

    });

})(jQuery);
<commit_msg>Remove unneccessary line<commit_after>(function ($) {
    "use strict";

    Mapbender.Digitizer = Mapbender.Digitizer || {};

    $.fn.dataTable.ext.errMode = 'throw';

    /**
     * Escape HTML chars
     * @returns {string}
     */
    String.prototype.escapeHtml = function () {

        return this.replace(/["&'\/<>]/g, function (a) {
            return {
                '"': '"',
                '&': '&',
                "'": ''',
                '/': '/',
                '<': '<',
                '>': '>'
            }[a];
        });
    };

    $.widget("mapbender.mbDigitizer", {

        options: {
            classes: {},
            create: null,
            debug: false,
            // disabled: false,
            fileURI: "uploads/featureTypes",
            schemes: {},
            target: null,
        },
        schemes: null,
        map: null,

        styles: {
            'default': {
                strokeWidth: 1,
                strokeColor: '#6fb536',
                fillColor: "#6fb536",
                fillOpacity: 0.3
                //, label: '${label}'
            },
            'select': {
                strokeWidth: 3,
                fillColor: "#F7F79A",
                strokeColor: '#6fb536',
                fillOpacity: 0.5,
                graphicZIndex: 15
            },
            // 'selected': {
            //     strokeWidth: 3,
            //     fillColor: "#74b1f7",
            //     strokeColor: '#b5ac14',
            //     fillOpacity: 0.7,
            //     graphicZIndex: 15
            // },
            'copy': {
                strokeWidth: 5,
                fillColor: "#f7ef7e",
                strokeColor: '#4250b5',
                fillOpacity: 0.7,
                graphicZIndex: 1000
            },
            'unsaved': {
                strokeWidth: 3,
                fillColor: "#FFD14F",
                strokeColor: '#F5663C',
                fillOpacity: 0.5
            },

            'invisible': {
                display: 'none'
            },

            'labelText': {
                strokeWidth: 0,
                fillColor: '#cccccc',
                fillOpacity: 0,
                strokeColor: '#5e1a2b',
                strokeOpacity: 0,
                pointRadius: 15,
                label: '${label}',
                fontSize: 15
            },
            'labelTextHover': {
                strokeWidth: 0,
                fillColor: '#cccccc',
                strokeColor: '#2340d3',
                fillOpacity: 1,
                pointRadius: 15,
                label: '${label}',
                fontSize: 15
            },

        },
        printClient: null,

        useAllScheme: true,

        displayOnInactive: false,

        openLayersCloudImagePath: null,

        disabled: true,

        isFullyActive: true,

        _create: function () {

            var widget = this.widget = this;
            var element = widget.element;

            widget.id = element.attr("id");

            if (!Mapbender.checkTarget("mbDigitizer", widget.options.target)) {
                return;
            }

            if (typeof widget.options.useAllScheme !== "undefined") {
                widget.useAllScheme = widget.options.useAllScheme;
            }

            widget.openLayersCloudImagePath = widget.options.openLayersCloudImagePath;

            widget.displayOnInactive = widget.options.displayOnInactive;

            widget.dataManager = Mapbender.elementRegistry.listWidgets()['mapbenderMbDataManager'];

            var qe = new Mapbender.Digitizer.QueryEngine(widget);
            widget.query = qe.query;
            widget.getElementURL = qe.getElementURL;

            var createSpinner = function() {

                widget.spinner = new function () {
                    var spinner = this;

                    spinner.openRequests = 0;

                    var $parent = $('#' + widget.id).parents('.container-accordion').prev().find('.tablecell').prepend("

");
                    spinner.$element = $parent.find(".spinner");

                    spinner.addRequest = function () {
                        spinner.openRequests++;
                        if (spinner.openRequests >= 1) {
                            spinner.$element.show();
                        }
                    };

                    spinner.removeRequest = function () {
                        spinner.openRequests--;
                        if (spinner.openRequests === 0) {
                            spinner.$element.hide();
                        }
                    };

                };
            };

            createSpinner();

            Mapbender.elementRegistry.waitReady(widget.options.target).then(widget.setup.bind(widget));

            Mapbender.elementRegistry.waitCreated('.mb-element-printclient').then(function (printClient) {
                widget.printClient = printClient;
                $.extend(widget.printClient, Mapbender.Digitizer.printPlugin);
            });
        },

        setup: function () {
            var widget = this;
            var element = $(widget.element);
            var options = widget.options;
            widget.selector = $("select.selector", element);

            widget.map = $('#' + options.target).data('mapbenderMbMap').map.olMap;

            // TODO Kanonen->Spatzen: refactoring
            var initializeActivationContainer = function () {

                var containerInfo = new MapbenderContainerInfo(widget, {
                    onactive: function () {
                        widget.activate();
                    },
                    oninactive: function () {
                        widget.deactivate();
                    }
                });

                return containerInfo;

            };

            var initializeSelectorOrTitleElement = function () {

                var options = widget.options;
                var element = $(widget.element);
                var titleElement = $("> div.title", element);

                widget.hasOnlyOneScheme = _.size(options.schemes) === 1;

                if (widget.hasOnlyOneScheme) {
                    titleElement.html(_.toArray(options.schemes)[0].label);
                    widget.selector.hide();
                } else {
                    titleElement.hide();
                }
            };

            var usesAllScheme = function() {
                return !widget.hasOnlyOneScheme && widget.useAllScheme;
            };

            // TODO this is not the proper implementation - fix that
            var isOpenByDefault = function() {
                var sidePane = $(widget.element).closest(".sidePane");

                var accordion = $(".accordionContainer", sidePane);
                return accordion.length === 0;
            };

            var createSchemes = function () {

                var createSchemaOption = function (schema) {
                    var option = $("<option/>");
                    option.val(schema.schemaName).html(schema.label);
                    option.data("schemaSettings", schema);
                    return option;

                };

                var rawSchemes = widget.options.schemes;
                widget.schemes = {};
                var index = 0;
                _.each(rawSchemes, function (rawScheme, schemaName) {
                    rawScheme.schemaName = schemaName;
                    widget.schemes[schemaName] = new Mapbender.Digitizer.Scheme(rawScheme, widget, index++);
                    widget.selector.append(createSchemaOption(widget.schemes[schemaName]));
                });

                var basicScheme = Object.keys(widget.schemes)[0];

                if (usesAllScheme()) {
                    widget.schemes['all'] = new Mapbender.Digitizer.AllScheme({
                        label: Mapbender.DigitizerTranslator.translate('schema.allgeometries'),
                        schemaName: 'all'
                    }, widget, index++);
                    widget.selector.prepend(createSchemaOption(widget.schemes['all']));
                    basicScheme = 'all';
                }

                widget.selector.val(basicScheme);

                if (isOpenByDefault()) {
                    widget.activate();
                }

            };

            var createMapContextMenu = function () {
                var map = widget.map;

                var options = {
                    selector: 'div',
                    events: {
                        show: function (options) {
                            return widget.isFullyActive && widget.getCurrentSchema && widget.getCurrentSchema().mapContextMenu.allowUseContextMenu(options);
                        }
                    },
                    build: function (trigger, e) {
                        return widget.isFullyActive && widget.getCurrentSchema && widget.getCurrentSchema().mapContextMenu.buildContextMenu(trigger, e);
                    }
                };

                $(map.div).contextMenu(options);

            };

            var createElementContextMenu = function () {
                var element = $(widget.element);

                var options = {
                    position: function (opt, x, y) {
                        opt.$menu.css({top: y, left: x + 10});
                    },
                    selector: '.mapbender-element-result-table > div > table > tbody > tr',
                    events: {
                        show: function (options) {
                            return widget.getCurrentSchema && widget.getCurrentSchema().elementContextMenu.allowUseContextMenu(options);
                        }
                    },
                    build: function (trigger, e) {
                        return widget.getCurrentSchema && widget.getCurrentSchema().elementContextMenu.buildContextMenu(trigger, e);
                    }
                };

                $(element).contextMenu(options);

            };

            var initializeSelector = function () {
                var selector = widget.selector;

                selector.on('change', widget.onSelectorChange);

            };

            initializeSelectorOrTitleElement();

            widget.onSelectorChange = function () { // Do not implement in prototype because of static widget access
                var selector = widget.selector;

                var option = selector.find(":selected");
                var newSchema = option.data("schemaSettings");

                widget.getCurrentSchema && widget.getCurrentSchema().deactivateSchema();

                newSchema.activateSchema();
            };

            initializeSelector();

            createSchemes();

            initializeActivationContainer();

            createMapContextMenu();

            createElementContextMenu();

            // widget.map.div.oncontextmenu = function(e) {
            //
            //     if(!e){ //dear IE...
            //         var e = window.event;
            //         e.returnValue = false;
            //     }
            //     var f = widget.getCurrentSchema().layer.getFeatureFromEvent(e);
            //     alert(f);
            //     //f is the pointed vector.feature :)
            //
            //     return false; //Prevent display of browser context menu
            // };

            widget.registerMapEvents();

           widget._trigger('ready');

           if(widget.displayOnInactive) {
               widget.activate();
               widget.isFullyActive = false;
           }

        },

        disable: function() {
          var widget = this;
          widget.disabled = true;
        },

        enable: function() {
            var widget = this;
            widget.disabled = false;
        },

        isEnabled: function() {
            var widget = this;
            return !widget.disabled;
        },

        registerMapEvents: function () {
            var widget = this;
            var map = widget.map;

            map.events.register("moveend", this, function () {
                widget.isEnabled() && widget.getCurrentSchema().getData();
            });
            map.events.register("zoomend", this, function () {
                widget.isEnabled() && widget.getCurrentSchema().getData({ zoom: true});
            });

            map.events.register("mouseover", this, function() {
                widget.isEnabled() && widget.getCurrentSchema().mapContextMenu.enable();
            });

            map.events.register("mouseout", this, function() {
                widget.isEnabled() && widget.getCurrentSchema().mapContextMenu.disable();
            });
            map.resetLayersZIndex();
        },

        getOpenLayersCloudImagePath: function() {
            var widget = this;
            return widget.openLayersCloudImagePath ? Mapbender.Digitizer.Utilities.getAssetsPath(widget.openLayersCloudImagePath) : OpenLayers.ImgPath;
        },

        getBasicSchemes: function () {
            var widget = this;

            return _.pick(widget.schemes, function (value, key) {
                return key !== "all";
            });
        },

        getSchemaByName: function (schemaName) {
            var widget = this;
            var scheme = widget.getBasicSchemes()[schemaName];
            if (!scheme) {
                throw new Error("No Basic Scheme exists with the name " + schemaName);
            }
            return scheme;
        },

        activate: function () {
            var widget = this;
            widget.enable();
            widget.isFullyActive = true;
            widget.onSelectorChange(); // triggers schema activation

        },

        deactivate: function () {
            var widget = this;
            widget.disable();
            widget.isFullyActive = false;
            widget.getCurrentSchema && widget.getCurrentSchema().deactivateSchema();
        },

        // TODO muss repariert werden
        refreshConnectedDigitizerFeatures: function (featureTypeName) {
            var widget = this;
            $(".mb-element-digitizer").not(".mb-element-data-manager").each(function (index, element) {
                var schemes = widget.schemes;
                schemes[featureTypeName] && schemes[featureTypeName].layer && schemes[featureTypeName].layer.getData();
            })

        },

    });

})(jQuery);
<|endoftext|>


<commit_before>ig.module(
	'plugins.lattice.lattice'
).requires(
	'impact.entity',
	'impact.game',
	'plugins.lattice.grid'
).defines(function () {
window.lat = window.lat || {};

// Game
ig.Game.inject({
	tilesize: 0,
	size: { x: 0, y: 0 },
	grid: null,
	round: Math.floor,
	_loaded: false,

	snap: function (pos, abs) {
		var ts = this.tilesize, rs = this._rscreen;
		return {
			x: this.round((pos.x + (abs ? rs.x : 0)) / ts) * ts,
			y: this.round((pos.y + (abs ? rs.y : 0)) / ts) * ts
		};
	},

	loadLevel: function () {
		this._loaded = false;
		var ret = this.parent.apply(this, arguments);
		this._afterLoadLevel();
		return ret;
	},

	// This function must be called at least once before `snap` will function
	// properly. Exposing this allows Entities created during the parent
	// implementation of `loadLevel` to use `snap` in their `ready` functions.
	_afterLoadLevel: function () {
		if (this._loaded) {
			return false;
		}
		this._loaded = true;
		var map = (function () {
			if (!ig.game.collisionMap.tilesize)
				return ig.game.backgroundMaps[0];
			return ig.game.collisionMap;
		})();
		this.tilesize = map.tilesize;
		this.grid = new lat.Grid({
			size: { r: map.height, c: map.width }
		});
		return true;
	},

	// Snap an entity to the grid. This includes:
	// - updating its position in the game to be grid-aligned
	// - updating which spot it occupies in `this._grid`
	snapEntity: function (ent) {
		if (ent.ignoreGrid) return;

		// Figure out where this Entity should go
		var newPos = this.snap(ent.pos), ts = this.tilesize;
		var newGridPos = { r: newPos.y/ts, c: newPos.x/ts };
		var x1 = ent.pos.x, y1 = ent.pos.y, x2 = newPos.x, y2 = newPos.y;
		var r1 = ent.gridPos.r, c1 = ent.gridPos.c,
			r2 = newGridPos.r, c2 = newGridPos.c;

		// Update entity position, if necessary and desired
		if (ent.snapping && (x1 !== x2 || y1 !== y2)) {
			ent.pos = newPos;
		}

		// Update grid, if necessary and if there isn't already a tenant at
		// the destination in a single-tenant grid
		if (r1 !== r2 || c1 !== c2 &&
			!(this.grid.singleTenant && this.grid.get(r2, c2))) {
			if (r1 >= 0 && c1 >= 0) {
				this.grid.rem(r1, c1, ent);
			}
			this.grid.put(r2, c2, ent);
			ent.gridPos = newGridPos;
		}
	},

	removeEntity: function (ent) {
		this.parent(ent);
		if (!ent.ignoreGrid) {
			this.grid.rem(ent.gridPos.r, ent.gridPos.c, ent);
		}
	}
});

ig.Entity.inject({
	ignoreGrid: false,
	snapping: true,
	gridPos: { r: -1, c: -1 },

	init: function (x, y, settings) {
		this.parent(x, y, settings);
		ig.game._loaded && ig.game.snapEntity(this);
	},

	ready: function () {
		ig.game._afterLoadLevel();
		ig.game.snapEntity(this);
	},

	update: function () {
		this.parent.apply(this, arguments);
		ig.game.snapEntity(this);
	},

	neighbors: function (Type) {
		return ig.game.grid.neighbors(this.gridPos.r, this.gridPos.c, Type);
	}
});

});<commit_msg>Fixed error in grid-snapping logic. Entities were being snapped to the grid after static collisions were processed but BEFORE dynamic collisions were resolved. This caused mis-snapping when an Entity with non-zero velocity collided with a fixed entity.<commit_after>ig.module(
	'plugins.lattice.lattice'
).requires(
	'impact.entity',
	'impact.game',
	'plugins.lattice.grid'
).defines(function () {
window.lat = window.lat || {};

// Game
ig.Game.inject({
	tilesize: 0,
	size: { x: 0, y: 0 },
	grid: null,
	_loaded: false,

	snap: function (pos, abs) {
		var ts = this.tilesize, rs = this._rscreen;
		return {
			x: Math.floor((pos.x + (abs ? rs.x : 0)) / ts) * ts,
			y: Math.floor((pos.y + (abs ? rs.y : 0)) / ts) * ts
		};
	},

	loadLevel: function () {
		this._loaded = false;
		var ret = this.parent.apply(this, arguments);
		this._afterLoadLevel();
		return ret;
	},

	// This function must be called at least once before `snap` will function
	// properly. Exposing this allows Entities created during the parent
	// implementation of `loadLevel` to use `snap` in their `ready` functions.
	_afterLoadLevel: function () {
		if (this._loaded) {
			return false;
		}
		this._loaded = true;
		var map = (function () {
			if (!ig.game.collisionMap.tilesize)
				return ig.game.backgroundMaps[0];
			return ig.game.collisionMap;
		})();
		this.tilesize = map.tilesize;
		this.grid = new lat.Grid({
			size: { r: map.height, c: map.width }
		});
		return true;
	},

	// Snap an entity to the grid. This includes:
	// - updating its position in the game to be grid-aligned
	// - updating which spot it occupies in `this.gridPos`
	snapEntity: function (ent) {

		// Figure out where this Entity should go
		var newPos = this.snap(ent.pos), ts = this.tilesize;
		var newGridPos = { r: newPos.y/ts, c: newPos.x/ts };

		var x1 = ent.pos.x, y1 = ent.pos.y, x2 = newPos.x, y2 = newPos.y;
		var r1 = ent.gridPos.r, c1 = ent.gridPos.c,
			r2 = newGridPos.r, c2 = newGridPos.c;

		// Update entity position, if necessary and desired
		if (ent.snapping && (x1 !== x2 || y1 !== y2)) {
			ent.pos = newPos;
		}

		// Update grid, if necessary and if there isn't already a tenant at
		// the destination in a single-tenant grid
		if (r1 !== r2 || c1 !== c2 &&
			!(this.grid.singleTenant && this.grid.get(r2, c2))) {
			if (r1 >= 0 && c1 >= 0) {
				this.grid.rem(r1, c1, ent);
			}
			this.grid.put(r2, c2, ent);
			ent.gridPos = newGridPos;
		}
	},

	removeEntity: function (ent) {
		this.parent(ent);
		if (!ent.ignoreGrid) {
			this.grid.rem(ent.gridPos.r, ent.gridPos.c, ent);
		}
	},

	update: function () {
		this.parent();
		for (var i = 0; i < this.entities.length; i++) {
			var ent = this.entities[i];
			if (!ent._killed) {
				ent.ignoreGrid || this.snapEntity(ent);
				ent.afterUpdate();
			}
		}
	}
});

ig.Entity.inject({
	ignoreGrid: false,
	snapping: true,
	gridPos: { r: -1, c: -1 },

	init: function (x, y, settings) {
		this.parent(x, y, settings);
		ig.game._loaded && ig.game.snapEntity(this);
	},

	ready: function () {
		ig.game._afterLoadLevel();
		ig.game.snapEntity(this);
	},

	// Called after update, after all static and dynamic collisions have been
	// resolved, and after the entity has been snapped to the grid.
	afterUpdate: function () { },

	neighbors: function (Type) {
		return ig.game.grid.neighbors(this.gridPos.r, this.gridPos.c, Type);
	}
});

});<|endoftext|>


<commit_before>/* global describe, beforeEach, afterEach, expect, Cocktail */
describe('Cocktail', function() {
    var A, B, C, D, ViewClass, ViewClass2, calls;

    beforeEach(function() {
        calls = [];

        A = {
            events: {
                'click .A': 'clickA'
            },

            zoo: {
                aardvark: 'george',
                elephant: 'edgar',
                organutan: 'fred'
            },

            initialize: function() {
                this.$el.append('

');
            },

            theFunc: function() {
                calls.push('theFunc');
                return 'func!';
            },

            clickA: function() {
                calls.push('clickA');
            },

            render: function() {
                calls.push('renderA');
            },

            awesomeSauce: function() {
                calls.push('awesomeA');
                return 'the sauce';
            },

            fooBar: function() {
                calls.push('fooBarA');
                return true;
            },

            cosmology: {
                omegaM: 0.3
            }
        };

        B = {
            events: {
                'click .B': 'clickB'
            },

            zoo : {
                antelope: 'bouregard',
                elephant: 'edward',
                zebra: 'brittania'
            },

            initialize: function() {
                this.$el.append('

');
            },

            sublime: function() {
                calls.push('sublime');
                return 'sublemon';
            },

            clickB: function() {
                calls.push('clickB');
            },

            beforeTearDown: function() {
                calls.push('beforeTearDownB');
            },

            fooBar: function() {
                calls.push('fooBarB');
                return false;
            },

            cosmology: function() {
                calls.push('cosmology');
            }
        };

        C = {
            url: function() {
                return '/sprockets';
            }
        };

        D = {
            urlRoot: '/thingamajigs',
            defaults: function() {
                return null;
            }
        };

        Cocktail.mixins.A = A;
        Cocktail.mixins.B = B;
        Cocktail.mixins.C = C;
        Cocktail.mixins.D = D;
    });

    describe('Cocktail.mixin', function() {
        beforeEach(function() {
            ViewClass = Backbone.View.extend({
                mixins: [A, 'B'],
                //should be ignored as the patch is not installed
                fooBar: function() {
                    calls.push('fooBarOriginal');
                }
            });

            var aMixin = {
                mixinmethod: function() {
                    return 'mixin';
                },

                otherMixinMethod: function() {
                    return 'other';
                },

                sampleArray: [1, 2, 3]
            };

            // Works with named mixins too
            Cocktail.mixins.fooBar = {
                fooBar: function() {
                    calls.push('fooBarInclude');
                }
            };

            var result = Cocktail.mixin(ViewClass, aMixin, 'fooBar');

            ViewClass2 = Backbone.View.extend({
                initialize: function () {
                  Cocktail.mixin(this, aMixin, 'fooBar');
                },

                //should be ignored as the patch is not installed
                fooBar: function() {
                    calls.push('fooBarOriginal');
                }
            });

        });

        it('should allow mixing in mixins after the sub class has been built (useful for coffeescript)', function() {
            var view = new ViewClass();
            expect(view.mixinmethod()).toEqual('mixin');
            expect(view.otherMixinMethod()).toEqual('other');
            view.fooBar();
            expect(calls).toEqual(['fooBarOriginal', 'fooBarInclude']);
        });

        it('should allow mixing into the instance after the subclass has been instantiated', function() {
            var view = new ViewClass2();
            expect(view.mixinmethod()).toEqual('mixin');
            expect(view.otherMixinMethod()).toEqual('other');
            view.fooBar();
            expect(calls).toEqual(['fooBarOriginal', 'fooBarInclude']);
        });

        it('should not mixin the same function reference more than once', function () {
            var A = {
                foo: function () {
                    console.log('foo');
                }
            };

            var B = {};

            var C = {
                foo: function () {
                    console.log('foo');
                }
            };

            Cocktail.mixin(B, A);
            expect(B.foo === A.foo).toBeTruthy();

            // An accidental mixin of the same base
            Cocktail.mixin(B, A);
            expect(B.foo === A.foo).toBeTruthy();

            // Expect the collision wrapper
            Cocktail.mixin(B, C);
            expect(B.foo === A.foo).toBeFalsy();
            expect(B.foo === C.foo).toBeFalsy();
        });

        it('should not convert an array attribute of a mixin into an object', function () {
            var view = new ViewClass();
            expect(_.isArray(view.sampleArray)).toBeTruthy();
        });

        it('should return the result mixed object', function () {
            var A = { b: 'c' },
                D = { e: 'f' };

            var result = Cocktail.mixin(A, D);
            expect(Cocktail.mixin(A, D) == A).toBeTruthy();
        });
    });

    describe('when patching backbone', function() {
        var ViewClass, CollectionClass, ModelClass;

        beforeEach(function() {
            Cocktail.patch(Backbone);

            ViewClass = Backbone.View.extend({
                mixins: ['A', B],

                events: {
                    'click .view': 'clickView'
                },

                zoo : {
                    aardvark: 'bob',
                    penguin: 'melvin',
                    zebra: 'zoe'
                },

                initialize: function() {
                    this.$el.append('

');
                },

                clickView: function() {
                    calls.push('clickView');
                },

                render: function() {
                    calls.push('renderView');
                    return this;
                },

                beforeTearDown: function() {
                    calls.push('beforeTearDownView');
                },

                awesomeSauce: function() {
                    calls.push('awesomeView');
                },

                cosmology: {
                    omegaL: 0.7
                }
            }),

            CollectionClass = Backbone.Collection.extend({
                mixins: ['C'],
                url: '/widgets'
            }),

            ModelClass = Backbone.Model.extend({
                mixins: [D],
                urlRoot: function() {
                    return '/gizmos';
                },
                defaults: {
                    foo: 'bar'
                }
            });
        });

        afterEach(function() {
            Cocktail.unpatch(Backbone);
        });

        it('should allow coffeescript syntax', function() {
            ViewClass.mixin(C);
            var view = new ViewClass();
            expect(view.url()).toEqual('/sprockets');
        });

        describe('mixing in mixins', function() {
            it('should mixin all the mixin methods for all the mixins', function() {
                var view = new ViewClass();
                view.theFunc();
                expect(calls).toContain('theFunc');
                view.sublime();
                expect(calls).toContain('sublime');
            });

            describe('hashes', function() {
                it('should merge in the events hash', function() {
                    var view = new ViewClass();

                    $('#content').append(view.$el);

                    $('.A').click();
                    $('.B').click();
                    $('.view').click();

                    expect(calls).toEqual(['clickA', 'clickB', 'clickView']);
                });

                it('should merge together hashes, favoring values defined by the instance over mixins, and mixins on a first in will win basis', function() {
                    var view = new ViewClass();
                    expect(view.zoo).toEqual({
                        aardvark: 'bob',
                        antelope: 'bouregard',
                        elephant: 'edgar',
                        organutan: 'fred',
                        penguin: 'melvin',
                        zebra: 'zoe'
                    });
                });
            });
        });

        describe('handling method collisions', function() {
            it('should call all the methods involved in the collision in the correct order', function() {
                var view = new ViewClass();
                view.render();
                view.awesomeSauce();
                view.fooBar();
                $('#content').append(view.$el);
                expect($('.A')[0]).toBeTruthy();
                expect($('.B')[0]).toBeTruthy();
                expect($('.view')[0]).toBeTruthy();
                view.beforeTearDown();

                expect(calls).toEqual(['renderView', 'renderA', 'awesomeView', 'awesomeA', 'fooBarA', 'fooBarB', 'beforeTearDownView', 'beforeTearDownB']);
            });

            it('should return the last return value in the collision chain', function() {
                var view = new ViewClass();
                expect(view.render()).toEqual(view);
                expect(view.theFunc()).toEqual('func!');
                expect(view.sublime()).toEqual('sublemon');
                expect(view.fooBar()).toEqual(false);
                expect(view.awesomeSauce()).toEqual('the sauce');
            });
        });

        describe('handling functional override of non-function property', function() {
            it('should return the last truthy defined return value in the collision chain', function() {
                var collection = new CollectionClass();
                expect(collection.url()).toEqual('/sprockets');
            });
            it('should return the last falsy defined return value in the collision chain', function() {
                var model = new ModelClass();
                expect(model.defaults()).toBeNull();
            });
            it('should set a function returning the base value if no mixin function has defined return', function() {
                var view = new ViewClass();
                expect(view.cosmology()).toEqual({
                    omegaM:0.3,
                    omegaL:0.7
                });
                expect(calls).toEqual(['cosmology']);
            });
        });

        describe('handling primitive override of non-events property', function() {
            describe('when class specifies prop', function() {
              it('should use the class property', function() {
                var model = new ModelClass();
                expect(model.url()).toEqual('/gizmos');
              });
            });
            describe('when class does not specify prop', function() {
              it('should use the class property', function() {
                var ModelWithoutUrlRoot = Backbone.Model.extend({
                  mixins: [D]
                }), model = new ModelWithoutUrlRoot();
                expect(model.url()).toEqual('/thingamajigs');
              });
            });
        });

        describe('when mixins are applied in the context of super/subclasses', function() {
            var BaseClass, SubClass, SubClassWithMixin;
            beforeEach(function() {
                BaseClass = Backbone.View.extend({
                    mixins: [A],
                    fooBar: function() {
                        calls.push('BaseClassFoo');
                    }
                });

                SubClass = BaseClass.extend({
                    fooBar: function() {
                        SubClass.__super__.fooBar.apply(this);
                        calls.push('SubClassFoo');
                    }
                });

                SubClassWithMixin = BaseClass.extend({
                    mixins: [B],

                    fooBar: function() {
                        SubClassWithMixin.__super__.fooBar.apply(this);
                        calls.push('SubClassWithMixinFoo');
                    }
                });
            });

            it('should behave correctly for the base class', function() {
                var baseInstance = new BaseClass();

                $('#content').append(baseInstance.$el);
                $('.A').click();
                baseInstance.fooBar();

                expect(calls).toEqual(['clickA', 'BaseClassFoo', 'fooBarA']);
            });

            it('should behave correctly for the sub class that has no mixins', function() {
                var subInstance = new SubClass();

                $('#content').html(subInstance.$el);
                $('.A').click();
                subInstance.fooBar();

                expect(calls).toEqual(['clickA', 'BaseClassFoo', 'fooBarA', 'SubClassFoo']);
            });

            it('should behave correctly for the sub class that has mixins', function() {
                var subInstance = new SubClassWithMixin();

                $('#content').html(subInstance.$el);
                $('.A').click();
                $('.B').click();
                subInstance.fooBar();

                expect(calls).toEqual(['clickA', 'clickB', 'BaseClassFoo', 'fooBarA', 'SubClassWithMixinFoo', 'fooBarB']);
            });
        });
    });
});<commit_msg>Rever/fix spec<commit_after>/* global describe, beforeEach, afterEach, expect, Cocktail */
describe('Cocktail', function() {
    var A, B, C, D, ViewClass, ViewClass2, calls;

    beforeEach(function() {
        calls = [];

        A = {
            events: {
                'click .A': 'clickA'
            },

            zoo: {
                aardvark: 'george',
                elephant: 'edgar',
                organutan: 'fred'
            },

            initialize: function() {
                this.$el.append('

');
            },

            theFunc: function() {
                calls.push('theFunc');
                return 'func!';
            },

            clickA: function() {
                calls.push('clickA');
            },

            render: function() {
                calls.push('renderA');
            },

            awesomeSauce: function() {
                calls.push('awesomeA');
                return 'the sauce';
            },

            fooBar: function() {
                calls.push('fooBarA');
                return true;
            },

            cosmology: {
                omegaM: 0.3
            }
        };

        B = {
            events: {
                'click .B': 'clickB'
            },

            zoo : {
                antelope: 'bouregard',
                elephant: 'edward',
                zebra: 'brittania'
            },

            initialize: function() {
                this.$el.append('

');
            },

            sublime: function() {
                calls.push('sublime');
                return 'sublemon';
            },

            clickB: function() {
                calls.push('clickB');
            },

            beforeTearDown: function() {
                calls.push('beforeTearDownB');
            },

            fooBar: function() {
                calls.push('fooBarB');
                return false;
            },

            cosmology: function() {
                calls.push('cosmology');
            }
        };

        C = {
            url: function() {
                return '/sprockets';
            }
        };

        D = {
            urlRoot: '/thingamajigs',
            defaults: function() {
                return null;
            }
        };

        Cocktail.mixins.A = A;
        Cocktail.mixins.B = B;
        Cocktail.mixins.C = C;
        Cocktail.mixins.D = D;
    });

    describe('Cocktail.mixin', function() {
        beforeEach(function() {
            ViewClass = Backbone.View.extend({
                mixins: [A, 'B'],
                //should be ignored as the patch is not installed
                fooBar: function() {
                    calls.push('fooBarOriginal');
                }
            });

            var aMixin = {
                mixinmethod: function() {
                    return 'mixin';
                },

                otherMixinMethod: function() {
                    return 'other';
                },

                sampleArray: [1, 2, 3]
            };

            // Works with named mixins too
            Cocktail.mixins.fooBar = {
                fooBar: function() {
                    calls.push('fooBarInclude');
                }
            };

            Cocktail.mixin(ViewClass, aMixin, 'fooBar');

            ViewClass2 = Backbone.View.extend({
                initialize: function () {
                  Cocktail.mixin(this, aMixin, 'fooBar');
                },

                //should be ignored as the patch is not installed
                fooBar: function() {
                    calls.push('fooBarOriginal');
                }
            });

        });

        it('should allow mixing in mixins after the sub class has been built (useful for coffeescript)', function() {
            var view = new ViewClass();
            expect(view.mixinmethod()).toEqual('mixin');
            expect(view.otherMixinMethod()).toEqual('other');
            view.fooBar();
            expect(calls).toEqual(['fooBarOriginal', 'fooBarInclude']);
        });

        it('should allow mixing into the instance after the subclass has been instantiated', function() {
            var view = new ViewClass2();
            expect(view.mixinmethod()).toEqual('mixin');
            expect(view.otherMixinMethod()).toEqual('other');
            view.fooBar();
            expect(calls).toEqual(['fooBarOriginal', 'fooBarInclude']);
        });

        it('should not mixin the same function reference more than once', function () {
            var A = {
                foo: function () {
                    console.log('foo');
                }
            };

            var B = {};

            var C = {
                foo: function () {
                    console.log('foo');
                }
            };

            Cocktail.mixin(B, A);
            expect(B.foo === A.foo).toBeTruthy();

            // An accidental mixin of the same base
            Cocktail.mixin(B, A);
            expect(B.foo === A.foo).toBeTruthy();

            // Expect the collision wrapper
            Cocktail.mixin(B, C);
            expect(B.foo === A.foo).toBeFalsy();
            expect(B.foo === C.foo).toBeFalsy();
        });

        it('should not convert an array attribute of a mixin into an object', function () {
            var view = new ViewClass();
            expect(_.isArray(view.sampleArray)).toBeTruthy();
        });

        it('should return the result mixed object', function () {
            var A = { b: 'c' },
                D = { e: 'f' };

            var result = Cocktail.mixin(A, D);
            expect(Cocktail.mixin(A, D) == A).toBeTruthy();
        });
    });

    describe('when patching backbone', function() {
        var ViewClass, CollectionClass, ModelClass;

        beforeEach(function() {
            Cocktail.patch(Backbone);

            ViewClass = Backbone.View.extend({
                mixins: ['A', B],

                events: {
                    'click .view': 'clickView'
                },

                zoo : {
                    aardvark: 'bob',
                    penguin: 'melvin',
                    zebra: 'zoe'
                },

                initialize: function() {
                    this.$el.append('

');
                },

                clickView: function() {
                    calls.push('clickView');
                },

                render: function() {
                    calls.push('renderView');
                    return this;
                },

                beforeTearDown: function() {
                    calls.push('beforeTearDownView');
                },

                awesomeSauce: function() {
                    calls.push('awesomeView');
                },

                cosmology: {
                    omegaL: 0.7
                }
            }),

            CollectionClass = Backbone.Collection.extend({
                mixins: ['C'],
                url: '/widgets'
            }),

            ModelClass = Backbone.Model.extend({
                mixins: [D],
                urlRoot: function() {
                    return '/gizmos';
                },
                defaults: {
                    foo: 'bar'
                }
            });
        });

        afterEach(function() {
            Cocktail.unpatch(Backbone);
        });

        it('should allow coffeescript syntax', function() {
            ViewClass.mixin(C);
            var view = new ViewClass();
            expect(view.url()).toEqual('/sprockets');
        });

        describe('mixing in mixins', function() {
            it('should mixin all the mixin methods for all the mixins', function() {
                var view = new ViewClass();
                view.theFunc();
                expect(calls).toContain('theFunc');
                view.sublime();
                expect(calls).toContain('sublime');
            });

            describe('hashes', function() {
                it('should merge in the events hash', function() {
                    var view = new ViewClass();

                    $('#content').append(view.$el);

                    $('.A').click();
                    $('.B').click();
                    $('.view').click();

                    expect(calls).toEqual(['clickA', 'clickB', 'clickView']);
                });

                it('should merge together hashes, favoring values defined by the instance over mixins, and mixins on a first in will win basis', function() {
                    var view = new ViewClass();
                    expect(view.zoo).toEqual({
                        aardvark: 'bob',
                        antelope: 'bouregard',
                        elephant: 'edgar',
                        organutan: 'fred',
                        penguin: 'melvin',
                        zebra: 'zoe'
                    });
                });
            });
        });

        describe('handling method collisions', function() {
            it('should call all the methods involved in the collision in the correct order', function() {
                var view = new ViewClass();
                view.render();
                view.awesomeSauce();
                view.fooBar();
                $('#content').append(view.$el);
                expect($('.A')[0]).toBeTruthy();
                expect($('.B')[0]).toBeTruthy();
                expect($('.view')[0]).toBeTruthy();
                view.beforeTearDown();

                expect(calls).toEqual(['renderView', 'renderA', 'awesomeView', 'awesomeA', 'fooBarA', 'fooBarB', 'beforeTearDownView', 'beforeTearDownB']);
            });

            it('should return the last return value in the collision chain', function() {
                var view = new ViewClass();
                expect(view.render()).toEqual(view);
                expect(view.theFunc()).toEqual('func!');
                expect(view.sublime()).toEqual('sublemon');
                expect(view.fooBar()).toEqual(false);
                expect(view.awesomeSauce()).toEqual('the sauce');
            });
        });

        describe('handling functional override of non-function property', function() {
            it('should return the last truthy defined return value in the collision chain', function() {
                var collection = new CollectionClass();
                expect(collection.url()).toEqual('/sprockets');
            });
            it('should return the last falsy defined return value in the collision chain', function() {
                var model = new ModelClass();
                expect(model.defaults()).toBeNull();
            });
            it('should set a function returning the base value if no mixin function has defined return', function() {
                var view = new ViewClass();
                expect(view.cosmology()).toEqual({
                    omegaM:0.3,
                    omegaL:0.7
                });
                expect(calls).toEqual(['cosmology']);
            });
        });

        describe('handling primitive override of non-events property', function() {
            describe('when class specifies prop', function() {
              it('should use the class property', function() {
                var model = new ModelClass();
                expect(model.url()).toEqual('/gizmos');
              });
            });
            describe('when class does not specify prop', function() {
              it('should use the class property', function() {
                var ModelWithoutUrlRoot = Backbone.Model.extend({
                  mixins: [D]
                }), model = new ModelWithoutUrlRoot();
                expect(model.url()).toEqual('/thingamajigs');
              });
            });
        });

        describe('when mixins are applied in the context of super/subclasses', function() {
            var BaseClass, SubClass, SubClassWithMixin;
            beforeEach(function() {
                BaseClass = Backbone.View.extend({
                    mixins: [A],
                    fooBar: function() {
                        calls.push('BaseClassFoo');
                    }
                });

                SubClass = BaseClass.extend({
                    fooBar: function() {
                        SubClass.__super__.fooBar.apply(this);
                        calls.push('SubClassFoo');
                    }
                });

                SubClassWithMixin = BaseClass.extend({
                    mixins: [B],

                    fooBar: function() {
                        SubClassWithMixin.__super__.fooBar.apply(this);
                        calls.push('SubClassWithMixinFoo');
                    }
                });
            });

            it('should behave correctly for the base class', function() {
                var baseInstance = new BaseClass();

                $('#content').append(baseInstance.$el);
                $('.A').click();
                baseInstance.fooBar();

                expect(calls).toEqual(['clickA', 'BaseClassFoo', 'fooBarA']);
            });

            it('should behave correctly for the sub class that has no mixins', function() {
                var subInstance = new SubClass();

                $('#content').html(subInstance.$el);
                $('.A').click();
                subInstance.fooBar();

                expect(calls).toEqual(['clickA', 'BaseClassFoo', 'fooBarA', 'SubClassFoo']);
            });

            it('should behave correctly for the sub class that has mixins', function() {
                var subInstance = new SubClassWithMixin();

                $('#content').html(subInstance.$el);
                $('.A').click();
                $('.B').click();
                subInstance.fooBar();

                expect(calls).toEqual(['clickA', 'clickB', 'BaseClassFoo', 'fooBarA', 'SubClassWithMixinFoo', 'fooBarB']);
            });
        });
    });
});<|endoftext|>