<commit_before>let socketCallbacks = new Map();
let serverCallbacks = new Map();
let realWebSocket = window.WebSocket;

function openSocket(socket) {
    let events = socketCallbacks.get(socket);

    setTimeout(() => {
        socket.readyState = realWebSocket.OPEN;
        events.get('open').forEach(callback => {
            callback();
        });
        if (typeof socket.onopen === 'function') {
            socket.onopen();
        }
    }, 0);
}

function initSocketEvents() {
    let events = new Map();
    ['open', 'message', 'close'].forEach(event => events.set(event, []));

    return events;
}

function transfer(eventName, data, events, receiver) {
    if (receiver.url === this.url) {
        let eventData;

        switch(eventName) {
            case 'message':
                eventData = new MessageEvent('message', {data: data});
                break;
            case 'close':
                eventData = new CloseEvent('close', {
                    code: data.code,
                    reason: data.reason
                });
                break;
        }

        events.get(eventName).forEach(callback => {
            callback(eventData);
        });
        if (typeof receiver['on' + eventName] === 'function') {
            receiver['on' + eventName](eventData);
        }
    }
}

class Connection {
    constructor(url) {
        this.url = url;
    }

    close(code, reason) {
        socketCallbacks.forEach(transfer.bind(this, 'close', {code, reason}));
        serverCallbacks.forEach(transfer.bind(this, 'close', {code, reason}));

        socketCallbacks.forEach((events, socket) => {
            if (socket.url === this.url) {
                socketCallbacks.delete(socket);
            }
        });
    }
}

export class WebMocket extends Connection {
    constructor(url) {
        super(url);
        this.readyState = realWebSocket.CONNECTING;

        let events = initSocketEvents(this);
        socketCallbacks.set(this, events);
        openSocket(this);
    }

    send(data) {
        serverCallbacks.forEach(transfer.bind(this, 'message', data));
    }

    addEventListener(event, callback) {
        let events = socketCallbacks.get(this);

        let callbacks = events.get(event);

        if (typeof callbacks !== 'undefined') {
            callbacks.push(callback);
        }
    }
}

export class MocketServer extends Connection {
    constructor(url) {
        super(url);

        let events = initSocketEvents(this);
        serverCallbacks.set(this, events);
    }

    send(data) {
        socketCallbacks.forEach(transfer.bind(this, 'message', data));
    }

    addEventListener(event, callback) {
        let events = serverCallbacks.get(this);

        let callbacks = events.get(event);

        if (typeof callbacks !== 'undefined') {
            callbacks.push(callback);
        }
    }
}<commit_msg>small naming refactoring<commit_after>let socketCallbacks = new Map();
let serverCallbacks = new Map();
let realWebSocket = window.WebSocket;

function openSocket(socket) {
    let events = socketCallbacks.get(socket);

    setTimeout(() => {
        socket.readyState = realWebSocket.OPEN;
        events.get('open').forEach(callback => {
            callback();
        });
        if (typeof socket.onopen === 'function') {
            socket.onopen();
        }
    }, 0);
}

function socketEvents() {
    let events = new Map();
    ['open', 'message', 'close'].forEach(event => events.set(event, []));

    return events;
}

function transfer(eventName, data, events, receiver) {
    if (receiver.url === this.url) {
        let eventData;

        switch(eventName) {
            case 'message':
                eventData = new MessageEvent('message', {data: data});
                break;
            case 'close':
                eventData = new CloseEvent('close', {
                    code: data.code,
                    reason: data.reason
                });
                break;
        }

        events.get(eventName).forEach(callback => {
            callback(eventData);
        });
        if (typeof receiver['on' + eventName] === 'function') {
            receiver['on' + eventName](eventData);
        }
    }
}

class Connection {
    constructor(url) {
        this.url = url;
    }

    close(code, reason) {
        socketCallbacks.forEach(transfer.bind(this, 'close', {code, reason}));
        serverCallbacks.forEach(transfer.bind(this, 'close', {code, reason}));

        socketCallbacks.forEach((events, socket) => {
            if (socket.url === this.url) {
                socketCallbacks.delete(socket);
            }
        });
    }
}

export class WebMocket extends Connection {
    constructor(url) {
        super(url);
        this.readyState = realWebSocket.CONNECTING;
        socketCallbacks.set(this, socketEvents());
        openSocket(this);
    }

    send(data) {
        serverCallbacks.forEach(transfer.bind(this, 'message', data));
    }

    addEventListener(event, callback) {
        let events = socketCallbacks.get(this);

        let callbacks = events.get(event);

        if (typeof callbacks !== 'undefined') {
            callbacks.push(callback);
        }
    }
}

export class MocketServer extends Connection {
    constructor(url) {
        super(url);
        serverCallbacks.set(this, socketEvents());
    }

    send(data) {
        socketCallbacks.forEach(transfer.bind(this, 'message', data));
    }

    addEventListener(event, callback) {
        let events = serverCallbacks.get(this);

        let callbacks = events.get(event);

        if (typeof callbacks !== 'undefined') {
            callbacks.push(callback);
        }
    }
}<|endoftext|>


<commit_before>const mongoose = require('mongoose');

let Trans = require('../models/transaction');
let Request = require('../models/request');
let User = require('../models/user');
let login = require('../helpers/login');
let contact = require('../helpers/contact');
// pas dia approve
let PropertySell = require('../models/propertySell');
let PropertyRent = require('../models/propertyRent');

const checkAuth = (req,res, next) => {
  let method = req.method;
  // let hasParam = req.path !== '/';

  if (req.headers.hasOwnProperty('token')){
    let decoded = login.getUserDetail(req.headers.token);
    if (decoded) next();
    else res.send({err:'You must login'})
  } else res.send({err:'You must login'})
}

const getRequests = (req,res) => {
  let decoded = login.getUserDetail(req.headers.token);
  if (decoded) {
    Request.find({}, (err,requests) => {
      res.send(err ? err : requests);
    })
  } else res.send({err: 'You dont have access'})

}

const getRequestsByBuyer = (req,res) => {
  let decoded = login.getUserDetail(req.headers.token);

  Request.find({_userId: decoded._id})
  .populate('_userId _sellerId')
  .populate('connections._propertyId')
  .exec( (err,requests) => {
    res.send(err? {err:err} : requests );
  })

}
const getRequestsBySeller = (req,res) => {
  let decoded = login.getUserDetail(req.headers.token);

  Request.find({_sellerId: decoded._id})
  // .populate('_userId _sellerId')
  .populate({path:'_userId', select:'phone username email name _id'})
  .populate({path:'_sellerId', select:'phone username email name _id'})
  .populate('connections._propertyId')
  .exec( (err,requests) => {
    res.send(err? {err:err} : requests );
  })
}

const getRequest = (req,res) => {
  let decoded = login.getUserDetail(req.headers.token);
  let id = req.params.id;
  Request.findById(id)
  .populate('_sellerId _userId')
  .populate('connections._propertyId')
  .exec( (err,request) => {
    if (err) res.send(err)
    else if (request._sellerId._id == decoded._id || request._userId._id == decoded._id || decoded.role === 'admin') res.send(request)
    else res.send({err:'You dont have access'})
  })
}

const addRequest = (req,res) => {
  let requestDt = req.body;
  let decoded = login.getUserDetail(req.headers.token);
  requestDt._userId = decoded._id;
  let Prop = requestDt.kind == 'PropertyRent' ? PropertyRent: PropertySell;
  if (requestDt._sellerId === requestDt._userId) res.send({err:'You cant rent/sell your own product'})
  else {

    let body =  (typeof requestDt.note !== 'undefined' && requestDt.note !== '' ? requestDt.note: 'You got a request!')
    let msg = {
      subject: 'There is a request for you',
      body: body
    }

    Prop.findById(requestDt._propertyId)
    .populate({path:'_ownerId', select:'phone username email name'})
    .exec((err,prop)=>{
      if (err){ res.send({err: 'Invalid Property'}); }
      // else if(requestDt.kind === 'PropertyRent'){
        // let start = new Date(requestDt['connections.start']);
        // let end = new Date(requestDt['connections.end']);
        //cek ketersediaan
        // let idx = prop.renter.findIndex(r => ( (start >= r.start && start <= r.end) || (end >= r.start && end <= r.end)  ))
        // if (idx > -1) res.send({err:'Booking Date are not available'})
      // }

      let newrequest = new Request({
        note: requestDt.note,
        connections: {
          kind: requestDt.kind,
          _propertyId: requestDt._propertyId
        },
        _sellerId : requestDt._sellerId,
        _userId: requestDt._userId
      });
      newrequest.save((err,request) => {
        if (err) res.send({err:err})
        else {
          if (typeof prop._ownerId !== 'undefined') contact.contact(prop._ownerId,msg);
          res.send(request);
        }
      })
    })

  }
}

const deleteRequest = (req,res) => {
  let requestDt = req.body;
  let decoded = login.getUserDetail(req.headers.token);
  let id = req.params.id;
  Request.findById(id, (err,request) => {
    if (err) res.send({err: 'Invalid Request'})
    else if (request._sellerId != decoded._id && decoded.role !== 'admin') res.send({err:'Invalid access'});
    else {

      let subject = 'Your request is ' +requestDt.response;
      // let body = 'Your request is ' +requestDt.response;

      let msg = {
        subject: subject
        // body: body
      }
      // res.send(decoded)
      // console.log(request)
      User.findById(request._userId, (err,user)=> {

        if (err) res.send({err:err})
        else if (requestDt.response === 'approved') {

          msg.body = `Your request has been approved. For further information please contact ${decoded.name} - ${decoded.phone} / ${decoded.email}`
          let transDt = req.body;
          transDt._userId = request._userId;
          transDt._sellerId = decoded._id;
          let trans = new Trans(transDt);
          let Prop = request.connections.kind === 'PropertyRent'? PropertyRent : PropertySell;

          Prop.findById( request.connections._propertyId, (err,prop) => {
            if (err) res.send({err : 'Invalid Property'});
            else if (request.connections.kind === 'PropertyRent') {
              let idx = prop.renter.findIndex(r => ( (start >= r.start && start <= r.end) || (end >= r.start && end <= r.end)  ))
              if (idx > -1) res.send({err:'Booking Date are not available'})
              else {
                trans.connections.detail =
                  {
                    start: request.connections.detail.start,
                    end: request.connections.detail.end
                  }

                trans.save((err,newtrans) => {
                  if (err) {
                    let err_msg = [];
                    for (let error in err.errors) err_msg.push(err.errors[error].message);
                    res.send({err : err_msg.join(',')});
                  }
                  else {
                    prop.renter.push({
                      start: request.connections.detail.start,
                      end: request.connections.detail.end,
                      _renterId: request._userId
                    });
                    prop.rentercount = prop.rentercount + 1;
                    prop.save((err,nprop) => {
                      res.send(err? {err:err} : newtrans);
                      contact.contact(user,msg);
                    })
                  }
                })

              }
            } else {

              msg.body = `Your request has been rejected `;
              msg.body += (typeof requestDt.note === 'undefined' || requestDt.note === '') ? '': `because ${requestDt.note}`;
              trans.save((err,newtrans) => {
                if (err) {
                  let err_msg = [];
                  for (let error in err.errors) err_msg.push(err.errors[error].message);
                  res.send({err : err_msg.join(',')});
                }
                else {
                  prop.isActive = false;
                  prop.save((err,nprop) => {
                    res.send(err? {err:err} : newtrans);
                    contact.contact(user,msg);
                  })
                }
              })

            }

          })

          //
          // trans.save((err,newtrans) => {
          //   if (err) {
          //     let err_msg = [];
          //     for (let error in err.errors) err_msg.push(err.errors[error].message);
          //     res.send({err : err_msg.join(',')});
          //   }
            //  else {
              // if (request.connections.kind === 'PropertyRent') {
                  // PropertyRent.findById(request.connections._propertyId, (err,prop) => {
                    // prop.connections.renter.push({
                    //   start: request.detail.start,
                    //   end: request.detail.end,
                    //   _renderId: request._userId
                    // });
                    // prop.save((err,nprop) => {
                    //   res.send(err? {err:err} : newtrans);
                    //   contact.contact(user,msg);
                    // })
                  // })
              // }
              // else if (request.connections.kind === 'PropertySell')
              //   PropertySell.findById(request.connections._propertyId, (err,prop) => {
              //     prop.isActive = false;
              //     prop.save((err,nprop) => {
              //       res.send(err? {err:err} : newtrans);
              //       contact.contact(user,msg);
              //     })
              //   })

            // }
          // })
        }
        else {
          request.remove((err,deleted) => {
            if (err) {res.send({err : err});}
            else {
              res.send(deleted)
              contact.contact(user,msg);
            }
          })

        }
      })
    }
  })
}

module.exports = {
  getRequests,
  getRequest,
  addRequest,
  deleteRequest,
  getRequestsByBuyer,
  getRequestsBySeller,
  checkAuth
}

<commit_msg>request change<commit_after>const mongoose = require('mongoose');

let Trans = require('../models/transaction');
let Request = require('../models/request');
let User = require('../models/user');
let login = require('../helpers/login');
let contact = require('../helpers/contact');
// pas dia approve
let PropertySell = require('../models/propertySell');
let PropertyRent = require('../models/propertyRent');

const checkAuth = (req,res, next) => {
  let method = req.method;
  // let hasParam = req.path !== '/';

  if (req.headers.hasOwnProperty('token')){
    let decoded = login.getUserDetail(req.headers.token);
    if (decoded) next();
    else res.send({err:'You must login'})
  } else res.send({err:'You must login'})
}

const getRequests = (req,res) => {
  let decoded = login.getUserDetail(req.headers.token);
  if (decoded) {
    Request.find({}, (err,requests) => {
      res.send(err ? err : requests);
    })
  } else res.send({err: 'You dont have access'})

}

const getRequestsByBuyer = (req,res) => {
  let decoded = login.getUserDetail(req.headers.token);

  Request.find({_userId: decoded._id})
  .populate('_userId _sellerId')
  .populate('connections._propertyId')
  .exec( (err,requests) => {
    res.send(err? {err:err} : requests );
  })

}
const getRequestsBySeller = (req,res) => {
  let decoded = login.getUserDetail(req.headers.token);

  Request.find({_sellerId: decoded._id})
  // .populate('_userId _sellerId')
  .populate({path:'_userId', select:'phone username email name _id'})
  .populate({path:'_sellerId', select:'phone username email name _id'})
  .populate('connections._propertyId')
  .exec( (err,requests) => {
    res.send(err? {err:err} : requests );
  })
}

const getRequest = (req,res) => {
  let decoded = login.getUserDetail(req.headers.token);
  let id = req.params.id;
  Request.findById(id)
  .populate('_sellerId _userId')
  .populate('connections._propertyId')
  .exec( (err,request) => {
    if (err) res.send(err)
    else if (request._sellerId._id == decoded._id || request._userId._id == decoded._id || decoded.role === 'admin') res.send(request)
    else res.send({err:'You dont have access'})
  })
}

const addRequest = (req,res) => {
  let requestDt = req.body;
  let decoded = login.getUserDetail(req.headers.token);
  requestDt._userId = decoded._id;
  let Prop = requestDt.kind == 'PropertyRent' ? PropertyRent: PropertySell;
  if (requestDt._sellerId === requestDt._userId) res.send({err:'You cant rent/sell your own product'})
  else {

    let body =  (typeof requestDt.note !== 'undefined' && requestDt.note !== '' ? requestDt.note: 'You got a request!')
    let msg = {
      subject: 'There is a request for you',
      body: body
    }

    Prop.findById(requestDt._propertyId)
    .populate({path:'_ownerId', select:'phone username email name'})
    .exec((err,prop)=>{
      if (err){ res.send({err: 'Invalid Property'}); }
      // else if(requestDt.kind === 'PropertyRent'){
        // let start = new Date(requestDt['connections.start']);
        // let end = new Date(requestDt['connections.end']);
        //cek ketersediaan
        // let idx = prop.renter.findIndex(r => ( (start >= r.start && start <= r.end) || (end >= r.start && end <= r.end)  ))
        // if (idx > -1) res.send({err:'Booking Date are not available'})
      // }

      let newrequest = new Request({
        note: requestDt.note,
        connections: {
          kind: requestDt.kind,
          _propertyId: requestDt._propertyId
        },
        _sellerId : requestDt._sellerId,
        _userId: requestDt._userId
      });
      newrequest.save((err,request) => {
        if (err) res.send({err:err})
        else {
          if (typeof prop._ownerId !== 'undefined') contact.contact(prop._ownerId,msg);
          res.send(request);
        }
      })
    })

  }
}

const deleteRequest = (req,res) => {
  let requestDt = req.body;
  let decoded = login.getUserDetail(req.headers.token);
  let id = req.params.id;
  Request.findById(id, (err,request) => {
    if (err) res.send({err: 'Invalid Request'})
    else if (request._sellerId != decoded._id && decoded.role !== 'admin') res.send({err:'Invalid access'});
    else {

      let subject = 'Your request is ' +requestDt.response;
      // let body = 'Your request is ' +requestDt.response;

      let msg = {
        subject: subject
        // body: body
      }
      // res.send(decoded)
      // console.log(request)
      User.findById(request._userId, (err,user)=> {

        if (err) res.send({err:err})
        else if (requestDt.response === 'approved') {

          msg.body = `Your request has been approved. For further information please contact ${decoded.name} - ${decoded.phone} / ${decoded.email}`
          let transDt = req.body;
          transDt._userId = request._userId;
          transDt._sellerId = decoded._id;
          let trans = new Trans(transDt);
          let Prop = request.connections.kind === 'PropertyRent'? PropertyRent : PropertySell;

          Prop.findById( request.connections._propertyId, (err,prop) => {
            if (err) res.send({err : 'Invalid Property'});
            else if (request.connections.kind === 'PropertyRent') {
              let idx = prop.renter.findIndex(r => ( (start >= r.start && start <= r.end) || (end >= r.start && end <= r.end)  ))
              if (idx > -1) res.send({err:'Booking Date are not available'})
              else {
                trans.connections.detail =
                  {
                    start: request.connections.detail.start,
                    end: request.connections.detail.end
                  }

                trans.save((err,newtrans) => {
                  if (err) {
                    let err_msg = [];
                    for (let error in err.errors) err_msg.push(err.errors[error].message);
                    res.send({err : err_msg.join(',')});
                  }
                  else {
                    contact.contact(user,msg);
                    // prop.renter.push({
                    //   start: request.connections.detail.start,
                    //   end: request.connections.detail.end,
                    //   _renterId: request._userId
                    // });
                    // prop.rentercount = prop.rentercount + 1;
                    // prop.save((err,nprop) => {
                    //   res.send(err? {err:err} : newtrans);
                    //   contact.contact(user,msg);
                    // })
                  }
                })

              }
            } else {

              msg.body = `Your request has been rejected `;
              msg.body += (typeof requestDt.note === 'undefined' || requestDt.note === '') ? '': `because ${requestDt.note}`;
              // trans.save((err,newtrans) => {
                // if (err) {
                //   let err_msg = [];
                //   for (let error in err.errors) err_msg.push(err.errors[error].message);
                //   res.send({err : err_msg.join(',')});
                // }
                // else {
                  prop.isActive = false;
                  prop.save((err,nprop) => {
                    res.send(err? {err:err} : 'Success');
                    contact.contact(user,msg);
                  })
                }
              // })

            }

          })

          //
          // trans.save((err,newtrans) => {
          //   if (err) {
          //     let err_msg = [];
          //     for (let error in err.errors) err_msg.push(err.errors[error].message);
          //     res.send({err : err_msg.join(',')});
          //   }
            //  else {
              // if (request.connections.kind === 'PropertyRent') {
                  // PropertyRent.findById(request.connections._propertyId, (err,prop) => {
                    // prop.connections.renter.push({
                    //   start: request.detail.start,
                    //   end: request.detail.end,
                    //   _renderId: request._userId
                    // });
                    // prop.save((err,nprop) => {
                    //   res.send(err? {err:err} : newtrans);
                    //   contact.contact(user,msg);
                    // })
                  // })
              // }
              // else if (request.connections.kind === 'PropertySell')
              //   PropertySell.findById(request.connections._propertyId, (err,prop) => {
              //     prop.isActive = false;
              //     prop.save((err,nprop) => {
              //       res.send(err? {err:err} : newtrans);
              //       contact.contact(user,msg);
              //     })
              //   })

            // }
          // })
        }
        else {
          request.remove((err,deleted) => {
            if (err) {res.send({err : err});}
            else {
              res.send(deleted)
              contact.contact(user,msg);
            }
          })

        }
      })
    }
  })
}

module.exports = {
  getRequests,
  getRequest,
  addRequest,
  deleteRequest,
  getRequestsByBuyer,
  getRequestsBySeller,
  checkAuth
}

<|endoftext|>


<commit_before>/**
 * @file error.js
 * @brief 打印错误信息，并决定是否退出程序
 * @param msg{string} 错误信息
 * @param opt.exit{boolean} 报错后是否强行退出程序
 * @author banbian, itaofe@gmail.com
 * @version 1.0.0
 * @date 2016-06-27
 */

const chalk = require("chalk")
const error = (msg, opt) => {
  console.log(chalk.red('[ERROR] ') + msg)
  if (opt.exit) process.exit(1)
}
const info = (msg) => {
  console.log(chalk.cyan('[INFO] ') + msg)
}
const success = (msg) => {
  console.log(chalk.green('[SUCCESS] ') + msg)
}
module.exports = {error, info, success}
<commit_msg>default opt in log.js<commit_after>/**
 * @file error.js
 * @brief 打印错误信息，并决定是否退出程序
 * @param msg{string} 错误信息
 * @param opt.exit{boolean} 报错后是否强行退出程序
 * @author banbian, itaofe@gmail.com
 * @version 1.0.0
 * @date 2016-06-27
 */

'use strict'
const chalk = require("chalk")
const error = (msg, opt) => {
  !opt && (opt = {})
  console.log(chalk.red('[ERROR] ') + msg)
  if (opt.exit) process.exit(1)
}
const info = (msg) => {
  console.log(chalk.cyan('[INFO] ') + msg)
}
const success = (msg) => {
  console.log(chalk.green('[SUCCESS] ') + msg)
}
module.exports = {error, info, success}
<|endoftext|>


<commit_before><commit_msg>Changed web socket port to 80<commit_after><|endoftext|>


<commit_before>/* globals anchors, jQuery, $, localStorage */
window.altinnInit = function () {
  var bpLarge = 992; var options
  // Toggle elements with the same parent + add 'open'-class
  $(function () {
    $('.js-toggle').click(function () {
      var self = $(this)
      if (self.hasClass('open')) {
        self.parent().find('.js-hide').slideUp(300); self.removeClass('open')
      } else {
        self.addClass('open'); self.parent().find('.js-hide').slideDown(300)
      }
      return false
    })
  })
  // Add dim class to panels
  $(function () {
    $('.index-heading').click(function () {
      if ($(this).hasClass('expanded')) {
        $(this).removeClass('expanded')
        if ($('.panel-heading.expanded').length === 0) {
          $('.panel-heading').removeClass('dim')
        } else $(this).addClass('dim')
      } else {
        $('.panel-heading').removeClass('expanded')
        $(this).addClass('expanded'); $('.panel-heading').addClass('dim')
        $('.panel-heading.expanded').removeClass('dim')
      }
    })
  })
  // Handle theme toggle
  $(function () {
    var toggleStuff = function () {
      $('body', $('iframe').contents()[0]).toggleClass('business')
      $('body', $('iframe').contents()[0]).toggleClass('private-person')
      $('html', $('iframe').contents()[0]).toggleClass('business')
      $('html', $('iframe').contents()[0]).toggleClass('private-person')
      localStorage
        .setItem('theme', $('body', $('iframe').contents()[0]).attr('class'))
      $('body', '.ap-profile').attr('class', '')
    }
    $('#sg-switchtheme-blue', $('iframe').contents()[0]).off('change')
    $('#sg-switchtheme-grey', $('iframe').contents()[0]).off('change')
    if (localStorage.getItem('theme') &&
      localStorage.getItem('theme') === 'business') {
      $('body', $('iframe').contents()[0]).attr('class', 'business')
      $('#sg-switchtheme-blue', $('iframe').contents()[0]).prop('checked', true)
    } else {
      $('body', $('iframe').contents()[0]).attr('class', 'private-person')
      $('#sg-switchtheme-grey', $('iframe').contents()[1]).prop('checked', true)
    }
    $('#sg-switchtheme-blue', $('iframe').contents()[0])
      .on('change', toggleStuff)
    $('#sg-switchtheme-grey', $('iframe').contents()[0])
      .on('change', toggleStuff)
    $('body', '.ap-profile').attr('class', '')
  })
  // Handle filter toggle
  $(function () {
    $('.a-collapseFilter').on('mouseup', function () {
      var actionRow = $(this).attr('data-target')
      if (!$(this).hasClass('collapsed')) {
        $(this).addClass('collapsed')
        if($(this).parent().is('td')) {
            $(actionRow).prev().removeClass('open')
            $(actionRow).css('display', 'none')
        }
      } else {
        $('.a-collapseContent').removeClass('in')
        $('.a-collapseFilter').addClass('collapsed')
        $(this).removeClass('collapsed')
        if($(this).parent().is('td')) {
            $(actionRow).css('display', 'table-row')
            $(actionRow).prev().addClass('open')
        }
      }
    })
  })

    //Make all cards in the same group the same height.

    $(function() {
        var cardGroup = $('.a-card-group');
        var maxheight = 0;
        cardGroup.children().each(function() {
            if($(this).height() > maxheight) {
                maxheight = $(this).height();
            }
        })
        cardGroup.children().children().css("min-height", maxheight);
    })

    // Adjust position of second level menu upon click:
    $(function () {
      $('#colnav').on('mouseup', function (event) {
        var target = $(event.target); var second = $('.a-colnav-secondLevel')
        var getThird = function (el) {
          if (el.attr('class') === '.a-colnav-thirdLevel') return el
          else return el.find('.a-colnav-thirdLevel')
        }
        var findOpenThird = function (el) {
          var bool = false
          el.find('.a-colnav-thirdLevel').each(function () {
            if ($(this).attr('data-ignore') === 'false') bool = true
          })
          return bool
        }
        var isOpen = function (el) {
          var x = 'expanded'
          return (el.closest('a').hasClass(x) || el.find('a').hasClass(x) ||
            el.hasClass(x))
        }
        var ul = target.closest('ul')
        if(ul.hasClass('a-colnav')) {
            second.css('margin-left', '-1px')
        }
        if (ul.hasClass('a-colnav-secondLevel' || 'a-colnav-thirdLevel')) {
          if (!findOpenThird(ul)) {
              if($(window).width() >= bpLarge) {second.animate({ 'margin-left': '-78px' }, 125)}
          }
          else {
              if($(window).width() >= bpLarge) {second.css('margin-left', '-78px') }
          }
          getThird(ul).css('margin-left', '-1px').css('left', '100%')
            .attr('data-ignore', 'false')
          if (ul.hasClass('a-colnav-secondLevel') && $(window).width() >= bpLarge) {
            ul.children('li').children('a').addClass('dim-second')
            target.closest('a').removeClass('dim-second')
            target.children('a').removeClass('dim-second')
            target.removeClass('dim-second')
          }
        } else if (ul.hasClass('a-colnav') && isOpen(target)) {
            $('#a-js-suggestionList').css('display', 'block')
          $('.dim').removeClass('dim'); second.css('margin-left', '-10000px')
          getThird(ul).css('margin-left', '-10000px')
            .attr('data-ignore', 'true')
          $('.col-md-3').removeClass('col-md-3').addClass('col-md-6')
            .removeClass('col-md-offset-4').addClass('col-md-offset-1')
        } else {
          second.each(function () {
            getThird($(this)).attr('data-ignore', 'true')
          })
          $('#a-js-suggestionList').css('display', 'none')
          $('.dim-second').removeClass('dim-second')
          $('.col-md-6').removeClass('col-md-6').addClass('col-md-3')
            .removeClass('col-md-offset-1').addClass('col-md-offset-4')
        }
      })
    })

  // INPUT Focus style
  // If state on input is "focus", add class to a-input : "a-input-focus"

  ; (function ($, undefined) {
      $(function () {

          $("input.form-control").focus(function(){
          $(this).parent().addClass("a-input-focus");

          }).blur(function(){
                 $(this).parent().removeClass("a-input-focus");
          })
      });
  }(jQuery));

  // TOOLTIP AND POPOVERS

  ; (function ($, undefined) {
      $(function () {

        $('[data-toggle="tooltip"]').tooltip();

        $('[data-toggle="popover"]').popover();

        $('#example').popover(options);

      })
  }(jQuery));

  /*!
   * COLAPSE "Mobile navigation" + add "open"-class
   */
  ; (function ($, undefined) {

      $(function () {

          $('.ap-sideNav-mobilebar').click(function () {
              var self = $(this);
              var searchButton = $('.a-toggle-search').hasClass('open');

              if (self.hasClass('open')) {
                  $('.ap-sideNav-collapse').slideUp(300);
                  self.removeClass('open');
              } else {
                  if (searchButton === true) {
                      $('.a-search').slideUp(300);
                      $('.a-toggle-search').removeClass('open');

                  }
                  self.addClass('open');
                  $('.ap-sideNav-collapse').slideDown(300);
              }

              return false;
          })
      });

  }(jQuery));

  // Add dim class to colnav FIRST LEVEL (The panels that is not active)
  // TODO: Combine first and second level javascript. On second level, make the items not DIM when menu is closed and another 2-level is opened (Reset)

  ; (function ($, undefined) {
      $(function () {

          $('.a-colnav-item').click(function () {
             $(this).parent().find('.a-colnav-item-second').eq(0).focus() // Repairs drilldown navigation (keyboard/screen reader)
             if ($(this).hasClass('expanded') && $(window).width() >= bpLarge) {
                 $(this).removeClass('expanded');
                 if ($('.a-colnav-item.expanded').length === 0) {
                     $('.a-colnav-item').removeClass('dim-second-no');
                 }
                 else {
                     $(this).addClass('dim')
                 }
             } else if($(window).width() >= bpLarge) {
                 $('.a-colnav-item').removeClass('expanded');
                 $(this).addClass('expanded');
                 $('.a-colnav-item').addClass('dim');
                 $('.a-colnav-item.expanded').removeClass('dim');
             }
         });
      });
  }(jQuery));

  // Add dim class to colnav SECOND LEVEL
  $(function () {
    $('.a-colnav-item-second').click(function () {
      $(this).parent().find('.a-colnav-item-third').eq(0).focus() // Repairs drilldown navigation (keyboard/screen reader)
           if ($(this).hasClass('expanded-second') && $(window).width() >= bpLarge) {
               $(this).removeClass('expanded-second');
               if ($('.a-colnav-item-second.expanded-second').length === 0) {
                   $('.a-colnav-item-second').removeClass('dim-second-no');
               }
               else {
                   $(this).addClass('dim-second')
               }
           } else if($(window).width() >= bpLarge){
               $('.a-colnav-item-second').removeClass('expanded-second');
               $(this).addClass('expanded-second');
               $('.a-colnav-item-second').addClass('dim-second');
               $('.a-colnav-item-second.expanded-second').removeClass('dim-second');
      }
    })
  })
  // Repair drilldown navigation (keyboard/screen reader)
  $(function () {
    $('.a-colnav-item').attr('tabindex', '0')
    $('.a-colnav-item').attr('href', '#')
    $('.a-colnav-item-second').attr('tabindex', '0')
    $('.a-colnav-item-second').attr('href', '#')
    $('.a-colnav-item-third').attr('tabindex', '0')
    $('.a-colnav-item-third').attr('href', '#')
    $('.a-colnav-item').on('focus', function () {
      if ($('.a-colnav-secondLevel.submenu.is-active').length === 1) {
        $(this).off('keydown.zf.drilldown')
        $(this).parent().find('.a-colnav-item-second').eq(0).focus()
      }
    })
  })
  // Proxy content propagator, for inclusion of content in more than one place
  $(function () {
    $('.propagated-content-destination').each(function () {
      if ($(this).hasClass('replace-me')) {
        $(this).before($('.propagated-content-origin.' +
          $(this).attr('data-refclass')).html())
        $(this).remove()
      } else {
        $(this).html($('.propagated-content-origin.' +
          $(this).attr('data-refclass')).html())
      }
    })
  })
  // Add anchors to all h1s, h2s, h3s and h4s inside of .ap-content.
  anchors.options.placement = 'left'; anchors.options.class = 'a-anchor'
  anchors.add('.ap-content h1, .ap-content h2, .ap-content h3, .ap-content h4')
}
window.altinnInit()
<commit_msg>Misc.<commit_after>/* globals anchors, $, localStorage */
window.altinnInit = function () {
  var bpLarge = 992; var options
  // Toggle elements with the same parent + add 'open'-class
  $(function () {
    $('.js-toggle').click(function () {
      var self = $(this)
      if (self.hasClass('open')) {
        self.parent().find('.js-hide').slideUp(300); self.removeClass('open')
      } else {
        self.addClass('open'); self.parent().find('.js-hide').slideDown(300)
      }
      return false
    })
  })
  // Add dim class to panels
  $(function () {
    $('.index-heading').click(function () {
      if ($(this).hasClass('expanded')) {
        $(this).removeClass('expanded')
        if ($('.panel-heading.expanded').length === 0) {
          $('.panel-heading').removeClass('dim')
        } else $(this).addClass('dim')
      } else {
        $('.panel-heading').removeClass('expanded')
        $(this).addClass('expanded'); $('.panel-heading').addClass('dim')
        $('.panel-heading.expanded').removeClass('dim')
      }
    })
  })
  // Handle theme toggle
  $(function () {
    var toggleStuff = function () {
      $('body', $('iframe').contents()[0]).toggleClass('business')
      $('body', $('iframe').contents()[0]).toggleClass('private-person')
      localStorage
        .setItem('theme', $('body', $('iframe').contents()[0]).attr('class'))
      $('body', '.ap-profile').attr('class', '')
    }
    $('#sg-switchtheme-blue', $('iframe').contents()[0]).off('change')
    $('#sg-switchtheme-grey', $('iframe').contents()[0]).off('change')
    if (localStorage.getItem('theme') &&
      localStorage.getItem('theme') === 'business') {
      $('body', $('iframe').contents()[0]).attr('class', 'business')
      $('#sg-switchtheme-blue', $('iframe').contents()[0]).prop('checked', true)
    } else {
      $('body', $('iframe').contents()[0]).attr('class', 'private-person')
      $('#sg-switchtheme-grey', $('iframe').contents()[1]).prop('checked', true)
    }
    $('#sg-switchtheme-blue', $('iframe').contents()[0])
      .on('change', toggleStuff)
    $('#sg-switchtheme-grey', $('iframe').contents()[0])
      .on('change', toggleStuff)
    $('body', '.ap-profile').attr('class', '')
  })
  // Handle filter toggle
  $(function () {
    $('.a-collapseFilter').on('mouseup', function () {
      var actionRow = $(this).attr('data-target')
      if (!$(this).hasClass('collapsed')) {
        $(this).addClass('collapsed')
        if ($(this).parent().is('td')) {
          $(actionRow).prev().removeClass('open')
          $(actionRow).css('display', 'none')
        }
      } else {
        $('.a-collapseContent').removeClass('in')
        $('.a-collapseFilter').addClass('collapsed')
        $(this).removeClass('collapsed')
        if ($(this).parent().is('td')) {
          $(actionRow).css('display', 'table-row')
          $(actionRow).prev().addClass('open')
        }
      }
    })
  })
  // Make all cards in the same group the same height
  $(function () {
    var cardGroup = $('.a-card-group'); var maxheight = 0
    cardGroup.children().each(function () {
      if ($(this).height() > maxheight) maxheight = $(this).height()
    })
    cardGroup.children().children().css('min-height', maxheight)
  })
  // Adjust position of second level menu upon click:
  $(function () {
    $('#colnav').on('mouseup', function (event) {
      var target = $(event.target); var second = $('.a-colnav-secondLevel')
      var getThird = function (el) {
        if (el.attr('class') === '.a-colnav-thirdLevel') return el
        else return el.find('.a-colnav-thirdLevel')
      }
      var findOpenThird = function (el) {
        var bool = false
        el.find('.a-colnav-thirdLevel').each(function () {
          if ($(this).attr('data-ignore') === 'false') bool = true
        })
        return bool
      }
      var isOpen = function (el) {
        var x = 'expanded'
        return (el.closest('a').hasClass(x) || el.find('a').hasClass(x) ||
          el.hasClass(x))
      }
      var ul = target.closest('ul')
      if (ul.hasClass('a-colnav')) second.css('margin-left', '-1px')
      if (ul.hasClass('a-colnav-secondLevel' || 'a-colnav-thirdLevel')) {
        if (!findOpenThird(ul)) {
          if ($(window).width() >= bpLarge) {
            second.animate({ 'margin-left': '-78px' }, 125)
          }
        } else {
          if ($(window).width() >= bpLarge) second.css('margin-left', '-78px')
        }
        getThird(ul).css('margin-left', '-1px').css('left', '100%')
          .attr('data-ignore', 'false')
        if (ul.hasClass('a-colnav-secondLevel') &&
          $(window).width() >= bpLarge) {
          ul.children('li').children('a').addClass('dim-second')
          target.closest('a').removeClass('dim-second')
          target.children('a').removeClass('dim-second')
          target.removeClass('dim-second')
        }
      } else if (ul.hasClass('a-colnav') && isOpen(target)) {
        $('#a-js-suggestionList').css('display', 'block')
        $('.dim').removeClass('dim'); second.css('margin-left', '-10000px')
        getThird(ul).css('margin-left', '-10000px').attr('data-ignore', 'true')
        $('.col-md-3').removeClass('col-md-3').addClass('col-md-6')
          .removeClass('col-md-offset-4').addClass('col-md-offset-1')
      } else {
        second.each(function () {
          getThird($(this)).attr('data-ignore', 'true')
        })
        $('#a-js-suggestionList').css('display', 'none')
        $('.dim-second').removeClass('dim-second')
        $('.col-md-6').removeClass('col-md-6').addClass('col-md-3')
          .removeClass('col-md-offset-1').addClass('col-md-offset-4')
      }
    })
  })
  // If state on input is 'focus', add class to a-input: 'a-input-focus'
  $(function () {
    $('input.form-control').focus(function () {
      $(this).parent().addClass('a-input-focus')
    }).blur(function () { $(this).parent().removeClass('a-input-focus') })
  })
  // Tooltip and popovers
  $(function () {
    $('[data-toggle="tooltip"]').tooltip()
    $('[data-toggle="popover"]').popover(); $('#example').popover(options)
  })
  // Collapse 'Mobile navigation' + add 'open'-class
  $(function () {
    $('.ap-sideNav-mobilebar').click(function () {
      var self = $(this)
      var searchButton = $('.a-toggle-search').hasClass('open')
      if (self.hasClass('open')) {
        $('.ap-sideNav-collapse').slideUp(300); self.removeClass('open')
      } else {
        if (searchButton === true) {
          $('.a-search').slideUp(300); $('.a-toggle-search').removeClass('open')
        }
        self.addClass('open'); $('.ap-sideNav-collapse').slideDown(300)
      }
      return false
    })
  })
  // Add dim class to colnav first level (the panels that are not active)
  $(function () {
    $('.a-colnav-item').click(function () {
      $(this).parent().find('.a-colnav-item-second').eq(0).focus()
      if ($(this).hasClass('expanded') && $(window).width() >= bpLarge) {
        $(this).removeClass('expanded')
        if ($('.a-colnav-item.expanded').length === 0) {
          $('.a-colnav-item').removeClass('dim-second-no')
        } else $(this).addClass('dim')
      } else if ($(window).width() >= bpLarge) {
        $('.a-colnav-item').removeClass('expanded')
        $(this).addClass('expanded'); $('.a-colnav-item').addClass('dim')
        $('.a-colnav-item.expanded').removeClass('dim')
      }
    })
  })
  // Add dim class to colnav second level
  $(function () {
    $('.a-colnav-item-second').click(function () {
      $(this).parent().find('.a-colnav-item-third').eq(0).focus()
      if ($(this).hasClass('expanded-second') && $(window).width() >= bpLarge) {
        $(this).removeClass('expanded-second')
        if ($('.a-colnav-item-second.expanded-second').length === 0) {
          $('.a-colnav-item-second').removeClass('dim-second-no')
        } else $(this).addClass('dim-second')
      } else if ($(window).width() >= bpLarge) {
        $('.a-colnav-item-second').removeClass('expanded-second')
        $(this).addClass('expanded-second')
        $('.a-colnav-item-second').addClass('dim-second')
        $('.a-colnav-item-second.expanded-second').removeClass('dim-second')
      }
    })
  })
  // Repair drilldown navigation (keyboard/screen reader)
  $(function () {
    $('.a-colnav-item').attr('tabindex', '0')
    $('.a-colnav-item').attr('href', '#')
    $('.a-colnav-item-second').attr('tabindex', '0')
    $('.a-colnav-item-second').attr('href', '#')
    $('.a-colnav-item-third').attr('tabindex', '0')
    $('.a-colnav-item-third').attr('href', '#')
    $('.a-colnav-item').on('focus', function () {
      if ($('.a-colnav-secondLevel.submenu.is-active').length === 1) {
        $(this).off('keydown.zf.drilldown')
        $(this).parent().find('.a-colnav-item-second').eq(0).focus()
      }
    })
  })
  // Proxy content propagator, for inclusion of content in more than one place
  $(function () {
    $('.propagated-content-destination').each(function () {
      if ($(this).hasClass('replace-me')) {
        $(this).before($('.propagated-content-origin.' +
          $(this).attr('data-refclass')).html())
        $(this).remove()
      } else {
        $(this).html($('.propagated-content-origin.' +
          $(this).attr('data-refclass')).html())
      }
    })
  })
  // Add anchors to all h1s, h2s, h3s and h4s inside of .ap-content.
  anchors.options.placement = 'left'; anchors.options.class = 'a-anchor'
  anchors.add('.ap-content h1, .ap-content h2, .ap-content h3, .ap-content h4')
}
window.altinnInit()
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------- \\
// File: namespace.js                                                         \\
// Module: API                                                                \\
// Author: Neil Jenkins                                                       \\
// License: © 2010-2015 FastMail Pty Ltd. MIT Licensed.                       \\
// -------------------------------------------------------------------------- \\

"use strict";

var JMAP = {};
<commit_msg>Add variable to namespace using "this"<commit_after>// -------------------------------------------------------------------------- \\
// File: namespace.js                                                         \\
// Module: API                                                                \\
// Author: Neil Jenkins                                                       \\
// License: © 2010-2015 FastMail Pty Ltd. MIT Licensed.                       \\
// -------------------------------------------------------------------------- \\

"use strict";

this.JMAP = {};
<|endoftext|>


<commit_before>/**
	_enyo.Drawer_ is a control that appears or disappears based on its _open_
	property. By default, the drawer appears or disappears with a sliding
	animation whose direction is determined by the _orient_ property.

	For more information, see the documentation on
	Drawers in the
	Enyo Developer Guide.
*/

enyo.kind({
	name: "enyo.Drawer",
	published: {
		//* The visibility state of the drawer's associated control
		open : true,
		/**
			Direction of the opening/closing animation--either "v" for vertical
			or "h" for horizontal
		*/
		orient : "v",
		//* If true, the opening/closing transition will be animated
		animated : true,
		onStep   : null,
		onEnd    : null
	},
	events: {
		/**
			Fires when the drawer has been opened or closed. The handler can determine
			whether the drawer was just opened or just closed based on the _open_
			property. If _this.getOpen()_ returns true, the drawer was opened; if not,
			it was closed.
		*/
		onDrawerAnimationEnd: ""
	},
	//* @protected
	style: "overflow: hidden; position: relative;",
	tools: [
		{kind: "Animator", onStep: "animatorStep", onEnd: "animatorEnd"},
		{name: "client", style: "position: relative;", classes: "enyo-border-box"}
	],
	create: enyo.super(function (sup) {
		return function() {
			sup.apply(this, arguments);
			this.animatedChanged();
			this.openChanged();
		};
	}),
	initComponents: enyo.super(function (sup) {
		return function() {
			this.createChrome(this.tools);
			sup.apply(this, arguments);
		};
	}),
	animatedChanged: function() {
		if (!this.animated && this.hasNode() && this.$.animator.isAnimating()) {
			this.$.animator.stop();
			this.animatorEnd();
		}
	},
	openChanged: function() {
		this.$.client.show();
		if (this.hasNode()) {
			if (this.$.animator.isAnimating()) {
				this.$.animator.reverse();
			} else {
				var v = this.orient == "v";
				var d = v ? "height" : "width";
				var p = v ? "top" : "left";
				// unfixing the height/width is needed to properly
				// measure the scrollHeight/Width DOM property, but
				// can cause a momentary flash of content on some browsers
				this.applyStyle(d, null);
				var s = this.hasNode()[v ? "scrollHeight" : "scrollWidth"];
				if (this.animated) {
					this.$.animator.play({
						startValue: this.open ? 0 : s,
						endValue: this.open ? s : 0,
						dimension: d,
						position: p
					});
				} else {
					// directly run last frame if not animating
					this.animatorEnd();
				}
			}
		} else {
			this.$.client.setShowing(this.open);
		}
	},
	animatorStep: function(inSender) {
		// the actual drawer DOM node adjusts its height
		if (this.hasNode()) {
			var d = inSender.dimension;
			this.node.style[d] = this.domStyles[d] = inSender.value + "px";
		}
		// while the client inside the drawer adjusts its position to move out of the visible area
		var cn = this.$.client.hasNode();
		if (cn) {
			var p = inSender.position;
			var o = (this.open ? inSender.endValue : inSender.startValue);
			cn.style[p] = this.$.client.domStyles[p] = (inSender.value - o) + "px";
		}
		if (this.container) {
			this.container.resized();
		}

		// Call this.onStep callback funciton
		if (typeof this.owner[this.onStep] == 'function') {
			this.owner[this.onStep].apply(this.owner, [inSender.value]);
		}
		return true;
	},
	animatorEnd: function() {
		if (!this.open) {
			this.$.client.hide();
		}
		else {
			// save changes to this.domCssText --> see ENYO-1561
			this.$.client.domCssText = enyo.Control.domStylesToCssText(this.$.client.domStyles);
			// at end of open animation, clean limit on height/width
			var v = (this.orient == "v");
			var d = v ? "height" : "width";
			var p = v ? "top" : "left";
			var cn = this.$.client.hasNode();
			// clear out changes to container position & node dimension
			if (cn) {
				cn.style[p] = this.$.client.domStyles[p] = null;
			}
			if (this.node) {
				this.node.style[d] = this.domStyles[d] = null;
			}
		}
		if (this.container) {
			this.container.resized();
		}
		this.doDrawerAnimationEnd();

		// Call this.onEnd callback funciton
		if (typeof this.owner[this.onEnd] == 'function') {
			this.owner[this.onEnd].apply(this.owner, []);
		}
		return true;
	}
});<commit_msg>Adding onAnimationStep event<commit_after>/**
	_enyo.Drawer_ is a control that appears or disappears based on its _open_
	property. By default, the drawer appears or disappears with a sliding
	animation whose direction is determined by the _orient_ property.

	For more information, see the documentation on
	Drawers in the
	Enyo Developer Guide.
*/

enyo.kind({
	name: "enyo.Drawer",
	published: {
		//* The visibility state of the drawer's associated control
		open : true,
		/**
			Direction of the opening/closing animation--either "v" for vertical
			or "h" for horizontal
		*/
		orient : "v",
		//* If true, the opening/closing transition will be animated
		animated : true,
		onStep   : null,
		onEnd    : null
	},
	events: {
		/**
			Fires when the drawer has been opened or closed. The handler can determine
			whether the drawer was just opened or just closed based on the _open_
			property. If _this.getOpen()_ returns true, the drawer was opened; if not,
			it was closed.
		*/
		onDrawerAnimationStep: "",
		onDrawerAnimationEnd: ""
	},
	//* @protected
	style: "overflow: hidden; position: relative;",
	tools: [
		{kind: "Animator", onStep: "animatorStep", onEnd: "animatorEnd"},
		{name: "client", style: "position: relative;", classes: "enyo-border-box"}
	],
	create: enyo.super(function (sup) {
		return function() {
			sup.apply(this, arguments);
			this.animatedChanged();
			this.openChanged();
		};
	}),
	initComponents: enyo.super(function (sup) {
		return function() {
			this.createChrome(this.tools);
			sup.apply(this, arguments);
		};
	}),
	animatedChanged: function() {
		if (!this.animated && this.hasNode() && this.$.animator.isAnimating()) {
			this.$.animator.stop();
			this.animatorEnd();
		}
	},
	openChanged: function() {
		this.$.client.show();
		if (this.hasNode()) {
			if (this.$.animator.isAnimating()) {
				this.$.animator.reverse();
			} else {
				var v = this.orient == "v";
				var d = v ? "height" : "width";
				var p = v ? "top" : "left";
				// unfixing the height/width is needed to properly
				// measure the scrollHeight/Width DOM property, but
				// can cause a momentary flash of content on some browsers
				this.applyStyle(d, null);
				var s = this.hasNode()[v ? "scrollHeight" : "scrollWidth"];
				if (this.animated) {
					this.$.animator.play({
						startValue: this.open ? 0 : s,
						endValue: this.open ? s : 0,
						dimension: d,
						position: p
					});
				} else {
					// directly run last frame if not animating
					this.animatorEnd();
				}
			}
		} else {
			this.$.client.setShowing(this.open);
		}
	},
	animatorStep: function(inSender) {
		// the actual drawer DOM node adjusts its height
		if (this.hasNode()) {
			var d = inSender.dimension;
			this.node.style[d] = this.domStyles[d] = inSender.value + "px";
		}
		// while the client inside the drawer adjusts its position to move out of the visible area
		var cn = this.$.client.hasNode();
		if (cn) {
			var p = inSender.position;
			var o = (this.open ? inSender.endValue : inSender.startValue);
			cn.style[p] = this.$.client.domStyles[p] = (inSender.value - o) + "px";
		}
		if (this.container) {
			this.container.resized();
		}
		this.doDrawerAnimationStep();
		return true;
	},
	animatorEnd: function() {
		if (!this.open) {
			this.$.client.hide();
		}
		else {
			// save changes to this.domCssText --> see ENYO-1561
			this.$.client.domCssText = enyo.Control.domStylesToCssText(this.$.client.domStyles);
			// at end of open animation, clean limit on height/width
			var v = (this.orient == "v");
			var d = v ? "height" : "width";
			var p = v ? "top" : "left";
			var cn = this.$.client.hasNode();
			// clear out changes to container position & node dimension
			if (cn) {
				cn.style[p] = this.$.client.domStyles[p] = null;
			}
			if (this.node) {
				this.node.style[d] = this.domStyles[d] = null;
			}
		}
		if (this.container) {
			this.container.resized();
		}
		this.doDrawerAnimationEnd();
		return true;
	}
});<|endoftext|>


<commit_before>/*
 * Utilities.js
 *
 * This is where extraneous and important functions are stored.
 * In addition to globals.
 *
 */

 var Utilities = exports.Utilities = {

	HueToRgb: function (m1, m2, hue) {
	    var v;
	    if (hue < 0)
	        hue += 1;
	    else if (hue > 1)
	        hue -= 1;

	    if (6 * hue < 1)
	        v = m1 + (m2 - m1) * hue * 6;
	    else if (2 * hue < 1)
	        v = m2;
	    else if (3 * hue < 2)
	        v = m1 + (m2 - m1) * (2 / 3 - hue) * 6;
	    else
	        v = m1;

	    return (255 * v).toString(16);
	},

	hashColor: function (name) {
	    var crypto = require('crypto');
	    var hash = crypto.createHash('md5').update(name).digest('hex');
	    var H = parseInt(hash.substr(4, 4), 16) % 360;
	    var S = parseInt(hash.substr(0, 4), 16) % 50 + 50;
	    var L = parseInt(hash.substr(8, 4), 16) % 20 + 25;

	    var m1, m2, hue;
	    var r, g, b
	        S /= 100;
	    L /= 100;
	    if (S == 0)
	        r = g = b = (L * 255).toString(16);
	    else {
	        if (L <= 0.5)
	            m2 = L * (S + 1);
	        else
	            m2 = L + S - L * S;
	        m1 = L * 2 - m2;
	        hue = H / 360;
	        r = this.HueToRgb(m1, m2, hue + 1 / 3);
	        g = this.HueToRgb(m1, m2, hue);
	        b = this.HueToRgb(m1, m2, hue - 1 / 3);
	    }

	    return 'rgb(' + r + ', ' + g + ', ' + b + ');';
	},

	formatAMPM: function(date) {
		var hours = date.getHours();
		var minutes = date.getMinutes();
		var ampm = hours >= 12 ? 'PM' : 'AM';
		hours = hours % 12;
		hours = hours ? hours : 12; // the hour '0' should be '12'
		minutes = minutes < 10 ? '0'+minutes : minutes;
		var strTime = hours + ':' + minutes + ' ' + ampm;
		return strTime;
	},

	rank: function(user){
		var data = fs.readFileSync('config/db/tourWins.csv','utf8');
		var row = (''+data).split("\n");

		var list = [];

		for (var i = row.length; i > -1; i--) {
			if (!row[i]) continue;
			var parts = row[i].split(",");
			list.push([toUserid(parts[0]),Number(parts[1])]);
		}
		list.sort(function(a,b){
    		return a[1] - b[1];
		});
		var arr = list.filter( function( el ) {
   			 return !!~el.indexOf(toUserid(user));
		});
		if (list.indexOf(arr[0]) === -1) {
			return 'Not Ranked';
		} else {
			return 'Rank ' + (list.length-list.indexOf(arr[0])) + ' out of ' + list.length;
		}
	},

	calcElo: function(winner, loser) {
		var kFactor = 32;
  		var ratingDifference = loser.elo - winner.elo;
  		var expectedScoreWinner = 1 / ( 1 + Math.pow(10, ratingDifference/400) );

  		var e = kFactor * (1 - expectedScoreWinner);
 		winner.elo = winner.elo + e;
  		loser.elo = loser.elo - e;

  		var arr = [winner.elo, loser.elo];
  		return arr;
	},

	botDelay: function(botName, room, message) {
		setTimeout(function(){
			room.add('|c|' + Users.users[toUserid(botName)].group + botName + '|' + message);
		}, (Math.floor(Math.random() * 6) * 1000));
	},

	spamProtection: function(user, room, connection, message) {
		if (user.group === ' ') {

			// flooding check
			/*if (user.numMsg >= 5 && user.group === ' ') {
				room.add('|c|'+ user.name+'|'+message);
				user.popup(botName+' has muted you for 7 minutes. '+ '(spam)');
				room.add(''+user.name+' was muted by '+ botName +' for 7 minutes.' + ' (flooding)');
				var alts = user.getAlts();
				if (alts.length) room.add(""+user.name+"'s alts were also muted: "+alts.join(", "));
				room.add('|unlink|' + user.userid);

				user.mute(room.id, 7*60*1000);
				user.numMsg = 0;
				return false;
			}*/

			// numMsgs reset
			if (user.connected === false) {
				user.numMsg = 0;
				user.warnCounter = 0;
			}
			if (user.numMsg != 0){
				setTimeout(function() {
					user.numMsg = 0;
				}, 6000);
			}

			// caps check
			var capsMatch = message.replace(/[^A-Za-z]/g, '').match(/[A-Z]/g);
			if (capsMatch && this.toId(message).length > 18 && (capsMatch.length >= Math.floor(this.toId(message).length * 0.8))) {
				room.add('|c|'+ user.name+'|'+message);
						user.warnCounter++;
						if (user.warnCounter >= 3) {
							user.popup(botName+' has muted you for 7 minutes. (caps)');
							room.add(''+user.name+' was muted by '+botName+' for 7 minutes.' + ' (caps)');
							var alts = user.getAlts();
							if (alts.length) room.add(""+user.name+"'s alts were also muted: "+alts.join(", "));
							room.add('|unlink|' + user.userid);

							user.numMsg = 0;
							user.warnCounter = 0;
							user.mute(room.id, 7*60*1000);
							return false;
						}
						room.add(''+user.name+' was warned by '+botName+'.' +  ' (caps)');
						user.send('|c|~|/warn '+'caps');
						return false;

			}

			// stretch check
			var stretchMatch = message.toLowerCase().match(/(.)\1{7,}/g); // matches the same character 8 or more times in a row
			if (stretchMatch) {
				room.add('|c|'+ user.name+'|'+message);
				user.warnCounter++;
				if (user.warnCounter >= 3) {
					user.popup(botName+' has muted you for 7 minutes. (stretching)');
					room.add(''+user.name+' was muted by '+ botName +' for 7 minutes.' + ' (stretching)');
					var alts = user.getAlts();
					if (alts.length) room.add(""+user.name+"'s alts were also muted: "+alts.join(", "));
					room.add('|unlink|' + user.userid);

					user.numMsg = 0;
					user.warnCounter = 0;
					user.mute(room.id, 7*60*1000);
					return false;
				}
				room.add(''+user.name+' was warned by '+botName+'.' +  ' (stretching)');
				user.send('|c|~|/warn '+'stretching');
				return false;
			}

			var banWords = ['fuck','bitch','nigga','fag','shit','nigger'];
			for (var i=0;i<banWords.length;i++) {
				if (message.toLowerCase().indexOf(banWords[i]) >= 0) {
					room.add('|c|'+ user.name+'|'+message);
					if (user.warnCounter >= 3) {
						user.popup(botName+' has muted you for 7 minutes. (Inappropriate word: ' + banWords[i]+')');
						room.add(''+user.name+' was muted by '+ botName +' for 7 minutes. (Inappropriate word: ' + banWords[i]+')');
						var alts = user.getAlts();
						if (alts.length) room.add(""+user.name+"'s alts were also muted: "+alts.join(", "));
						room.add('|unlink|' + user.userid);

						user.numMsg = 0;
						user.warnCounter = 0;
						user.mute(room.id, 7*60*1000);
						return false;
					}
					var botMsg = user.name + ' -> Go ahead, make my day. [Inappropriate word: '+banWords[i]+'] [warning]';
					this.botDelay(botName, room, botMsg);
					user.warnCounter++;
					return false;
				}
			}

		}

	},

	toId: function(text) {
		return text.toLowerCase().replace(/[^a-z0-9]/g, '');
	}

};

// Global Variables

// Shortcut for using Object.keys
global.k = function(o) {
	return Object.keys(o);
}<commit_msg>remove warn from bot<commit_after>/*
 * Utilities.js
 *
 * This is where extraneous and important functions are stored.
 * In addition to globals.
 *
 */

 var Utilities = exports.Utilities = {

	HueToRgb: function (m1, m2, hue) {
	    var v;
	    if (hue < 0)
	        hue += 1;
	    else if (hue > 1)
	        hue -= 1;

	    if (6 * hue < 1)
	        v = m1 + (m2 - m1) * hue * 6;
	    else if (2 * hue < 1)
	        v = m2;
	    else if (3 * hue < 2)
	        v = m1 + (m2 - m1) * (2 / 3 - hue) * 6;
	    else
	        v = m1;

	    return (255 * v).toString(16);
	},

	hashColor: function (name) {
	    var crypto = require('crypto');
	    var hash = crypto.createHash('md5').update(name).digest('hex');
	    var H = parseInt(hash.substr(4, 4), 16) % 360;
	    var S = parseInt(hash.substr(0, 4), 16) % 50 + 50;
	    var L = parseInt(hash.substr(8, 4), 16) % 20 + 25;

	    var m1, m2, hue;
	    var r, g, b
	        S /= 100;
	    L /= 100;
	    if (S == 0)
	        r = g = b = (L * 255).toString(16);
	    else {
	        if (L <= 0.5)
	            m2 = L * (S + 1);
	        else
	            m2 = L + S - L * S;
	        m1 = L * 2 - m2;
	        hue = H / 360;
	        r = this.HueToRgb(m1, m2, hue + 1 / 3);
	        g = this.HueToRgb(m1, m2, hue);
	        b = this.HueToRgb(m1, m2, hue - 1 / 3);
	    }

	    return 'rgb(' + r + ', ' + g + ', ' + b + ');';
	},

	formatAMPM: function(date) {
		var hours = date.getHours();
		var minutes = date.getMinutes();
		var ampm = hours >= 12 ? 'PM' : 'AM';
		hours = hours % 12;
		hours = hours ? hours : 12; // the hour '0' should be '12'
		minutes = minutes < 10 ? '0'+minutes : minutes;
		var strTime = hours + ':' + minutes + ' ' + ampm;
		return strTime;
	},

	rank: function(user){
		var data = fs.readFileSync('config/db/tourWins.csv','utf8');
		var row = (''+data).split("\n");

		var list = [];

		for (var i = row.length; i > -1; i--) {
			if (!row[i]) continue;
			var parts = row[i].split(",");
			list.push([toUserid(parts[0]),Number(parts[1])]);
		}
		list.sort(function(a,b){
    		return a[1] - b[1];
		});
		var arr = list.filter( function( el ) {
   			 return !!~el.indexOf(toUserid(user));
		});
		if (list.indexOf(arr[0]) === -1) {
			return 'Not Ranked';
		} else {
			return 'Rank ' + (list.length-list.indexOf(arr[0])) + ' out of ' + list.length;
		}
	},

	calcElo: function(winner, loser) {
		var kFactor = 32;
  		var ratingDifference = loser.elo - winner.elo;
  		var expectedScoreWinner = 1 / ( 1 + Math.pow(10, ratingDifference/400) );

  		var e = kFactor * (1 - expectedScoreWinner);
 		winner.elo = winner.elo + e;
  		loser.elo = loser.elo - e;

  		var arr = [winner.elo, loser.elo];
  		return arr;
	},

	botDelay: function(botName, room, message) {
		setTimeout(function(){
			room.add('|c|' + Users.users[toUserid(botName)].group + botName + '|' + message);
		}, (Math.floor(Math.random() * 6) * 1000));
	},

	spamProtection: function(user, room, connection, message) {
		if (user.group === ' ') {

			// flooding check
			/*if (user.numMsg >= 5 && user.group === ' ') {
				room.add('|c|'+ user.name+'|'+message);
				user.popup(botName+' has muted you for 7 minutes. '+ '(spam)');
				room.add(''+user.name+' was muted by '+ botName +' for 7 minutes.' + ' (flooding)');
				var alts = user.getAlts();
				if (alts.length) room.add(""+user.name+"'s alts were also muted: "+alts.join(", "));
				room.add('|unlink|' + user.userid);

				user.mute(room.id, 7*60*1000);
				user.numMsg = 0;
				return false;
			}*/

			// numMsgs reset
			if (user.connected === false) {
				user.numMsg = 0;
				user.warnCounter = 0;
			}
			if (user.numMsg != 0){
				setTimeout(function() {
					user.numMsg = 0;
				}, 6000);
			}

			// caps check
			var capsMatch = message.replace(/[^A-Za-z]/g, '').match(/[A-Z]/g);
			if (capsMatch && this.toId(message).length > 18 && (capsMatch.length >= Math.floor(this.toId(message).length * 0.8))) {
				room.add('|c|'+ user.name+'|'+message);
						user.warnCounter++;
						if (user.warnCounter >= 3) {
							user.popup(botName+' has muted you for 7 minutes. (caps)');
							room.add(''+user.name+' was muted by '+botName+' for 7 minutes.' + ' (caps)');
							var alts = user.getAlts();
							if (alts.length) room.add(""+user.name+"'s alts were also muted: "+alts.join(", "));
							room.add('|unlink|' + user.userid);

							user.numMsg = 0;
							user.warnCounter = 0;
							user.mute(room.id, 7*60*1000);
							return false;
						}
						room.add(''+user.name+' was warned by '+botName+'.' +  ' (caps)');
						user.send('|c|~|/warn '+'caps');
						return false;

			}

			// stretch check
			var stretchMatch = message.toLowerCase().match(/(.)\1{7,}/g); // matches the same character 8 or more times in a row
			if (stretchMatch) {
				room.add('|c|'+ user.name+'|'+message);
				user.warnCounter++;
				if (user.warnCounter >= 3) {
					user.popup(botName+' has muted you for 7 minutes. (stretching)');
					room.add(''+user.name+' was muted by '+ botName +' for 7 minutes.' + ' (stretching)');
					var alts = user.getAlts();
					if (alts.length) room.add(""+user.name+"'s alts were also muted: "+alts.join(", "));
					room.add('|unlink|' + user.userid);

					user.numMsg = 0;
					user.warnCounter = 0;
					user.mute(room.id, 7*60*1000);
					return false;
				}
				room.add(''+user.name+' was warned by '+botName+'.' +  ' (stretching)');
				user.send('|c|~|/warn '+'stretching');
				return false;
			}

			/*var banWords = ['fuck','bitch','nigga','fag','shit','nigger'];
			for (var i=0;i<banWords.length;i++) {
				if (message.toLowerCase().indexOf(banWords[i]) >= 0) {
					room.add('|c|'+ user.name+'|'+message);
					if (user.warnCounter >= 3) {
						user.popup(botName+' has muted you for 7 minutes. (Inappropriate word: ' + banWords[i]+')');
						room.add(''+user.name+' was muted by '+ botName +' for 7 minutes. (Inappropriate word: ' + banWords[i]+')');
						var alts = user.getAlts();
						if (alts.length) room.add(""+user.name+"'s alts were also muted: "+alts.join(", "));
						room.add('|unlink|' + user.userid);

						user.numMsg = 0;
						user.warnCounter = 0;
						user.mute(room.id, 7*60*1000);
						return false;
					}
					var botMsg = user.name + ' -> Go ahead, make my day. [Inappropriate word: '+banWords[i]+'] [warning]';
					this.botDelay(botName, room, botMsg);
					user.warnCounter++;
					return false;
				}
			}*/

		}

	},

	toId: function(text) {
		return text.toLowerCase().replace(/[^a-z0-9]/g, '');
	}

};

// Global Variables

// Shortcut for using Object.keys
global.k = function(o) {
	return Object.keys(o);
}<|endoftext|>


<commit_before>/**
 * Main JS file for Casper behaviours
 */

/* globals jQuery, document */
(function($, undefined) {
  "use strict";

  var $document = $(document);

  $document.ready(function() {

    var $postContent = $(".post-content");
    $postContent.fitVids();

    $(".scroll-down").arctic_scroll();

    $(".menu-button, .nav-cover, .nav-close").on("click", function(e) {
      e.preventDefault();
      $("body").toggleClass("nav-opened nav-closed");
    });

  });

  // Arctic Scroll by Paul Adam Davis
  // https://github.com/PaulAdamDavis/Arctic-Scroll
  $.fn.arctic_scroll = function(options) {

    var defaults = {
        elem: $(this),
        speed: 500
      },

      allOptions = $.extend(defaults, options);

    allOptions.elem.click(function(event) {
      event.preventDefault();
      var $this = $(this),
        $htmlBody = $('html, body'),
        offset = ($this.attr('data-offset')) ? $this.attr('data-offset') : false,
        position = ($this.attr('data-position')) ? $this.attr('data-position') : false,
        toMove;

      if (offset) {
        toMove = parseInt(offset);
        $htmlBody.stop(true, false).animate({ scrollTop: ($(this.hash).offset().top + toMove) }, allOptions.speed);
      } else if (position) {
        toMove = parseInt(position);
        $htmlBody.stop(true, false).animate({ scrollTop: toMove }, allOptions.speed);
      } else {
        $htmlBody.stop(true, false).animate({ scrollTop: ($(this.hash).offset().top) }, allOptions.speed);
      }
    });

  };
})(jQuery);

/* 自定义脚本 */
(function(doc) {
  var container = doc.head || doc.body
  var dsTop = $('.ds-thread')[0].offsetTop
  var disqusTop = $('#disqus_thread')[0].offsetTop
  var dsLoaded
  var disqusLoaded

  function createScript (src) {
    var script = doc.createElement('script')
    script = 'text/javascript'
    script.async = true
    script.charset = 'UTF-8'
    script.src = src
    return script
  }

  $(window).scroll(function() {
    if (!dsLoaded && this.scrollY > dsTop) {
      dsLoaded = true
      container.appendChild(createScript('//static.duoshuo.com/embed.js'))
    }
    if (!disqusLoaded && this.scrollY > disqusTop) {
      disqusLoaded = true
      container.appendChild(createScript('//sebastianblade.disqus.com/embed.js'))
    }
  })
}(document))
<commit_msg>Fixed scroll script bug<commit_after>/**
 * Main JS file for Casper behaviours
 */

/* globals jQuery, document */
(function($, undefined) {
  "use strict";

  var $document = $(document);

  $document.ready(function() {

    var $postContent = $(".post-content");
    $postContent.fitVids();

    $(".scroll-down").arctic_scroll();

    $(".menu-button, .nav-cover, .nav-close").on("click", function(e) {
      e.preventDefault();
      $("body").toggleClass("nav-opened nav-closed");
    });

  });

  // Arctic Scroll by Paul Adam Davis
  // https://github.com/PaulAdamDavis/Arctic-Scroll
  $.fn.arctic_scroll = function(options) {

    var defaults = {
        elem: $(this),
        speed: 500
      },

      allOptions = $.extend(defaults, options);

    allOptions.elem.click(function(event) {
      event.preventDefault();
      var $this = $(this),
        $htmlBody = $('html, body'),
        offset = ($this.attr('data-offset')) ? $this.attr('data-offset') : false,
        position = ($this.attr('data-position')) ? $this.attr('data-position') : false,
        toMove;

      if (offset) {
        toMove = parseInt(offset);
        $htmlBody.stop(true, false).animate({ scrollTop: ($(this.hash).offset().top + toMove) }, allOptions.speed);
      } else if (position) {
        toMove = parseInt(position);
        $htmlBody.stop(true, false).animate({ scrollTop: toMove }, allOptions.speed);
      } else {
        $htmlBody.stop(true, false).animate({ scrollTop: ($(this.hash).offset().top) }, allOptions.speed);
      }
    });

  };
})(jQuery);

/* 自定义脚本 */
(function(doc) {
  var container = doc.head || doc.body
  var dsTop = $('.ds-thread')[0].offsetTop
  var disqusTop = $('#disqus_thread')[0].offsetTop
  var dsLoaded
  var disqusLoaded

  function createScript (src) {
    var script = doc.createElement('script')
    script.type = 'text/javascript'
    script.async = true
    script.charset = 'UTF-8'
    script.src = src
    return script
  }

  $(window).scroll(function() {
    if (!dsLoaded && this.scrollY > dsTop) {
      dsLoaded = true
      container.appendChild(createScript('//static.duoshuo.com/embed.js'))
    }
    if (!disqusLoaded && this.scrollY > disqusTop) {
      disqusLoaded = true
      container.appendChild(createScript('//sebastianblade.disqus.com/embed.js'))
    }
  })
}(document))
<|endoftext|>


<commit_before>/*global $:false */
/*jshint -W116 */

/**
 * Manages the genres and their stations. Keeps track of what genres and stations have been
 * played and what will be played in the future.
 */
var NowRadio = (function(nr) {
    'use strict';
    var genreLists = [];
    var genreMarkers = [];
    var genreNum = 0;

    nr.StationsManager = {};

    nr.StationsManager.getNextGenre = function() {
        genreNum = (genreNum + 1) % genreLists.length;
        return this.getCurrentStation();
    };
    nr.StationsManager.getPrevGenre = function() {
        genreNum = (genreNum + genreLists.length - 1) % genreLists.length;
        return this.getCurrentStation();
    };
    nr.StationsManager.getNextStation = function() {
        genreMarkers[genreNum] = (genreMarkers[genreNum] + 1) % genreLists[genreNum].length;
        return this.getCurrentStation();
    };
    nr.StationsManager.getCurrentStation = function() {
        return genreLists[genreNum][genreMarkers[genreNum]];
    };
    nr.StationsManager.getPrevStation = function() {
        genreMarkers[genreNum] = (genreMarkers[genreNum] + (genreLists[genreNum].length - 1)) %
                                                            genreLists[genreNum].length;
        return this.getCurrentStation();
    };
    nr.StationsManager.getActiveGenre = function() {
        return genreNum;
    };
    nr.StationsManager.setActiveGenre = function(genreInfo) {
        if (genreNum === genreInfo) return false;
        genreNum = genreInfo;
        return true;
    };
    nr.StationsManager.removeCurrentThenNext = function() {
        genreLists[genreNum].splice(genreMarkers[genreNum], 1);
        genreMarkers[genreNum] -= 1;
        nr.StationChanger.nextStation();
    };
    nr.StationsManager.getGenreCount = function() {
        return genreLists.length;
    };
    nr.StationsManager.setStationFirstUnique = function(src) {
        callback();
        function callback() {
            if (genreMarkers.length < 1) return window.setTimeout(callback, 200);
            var currentLocation = genreLists[genreNum].indexOf(src);
            if (currentLocation != -1) {
                genreLists[genreNum][currentLocation] = genreLists[genreNum][0];
                genreLists[genreNum][0] = src;
                genreMarkers[genreNum] = 0;
            } else {
                genreLists[genreNum].push(src);
                genreMarkers[genreNum] = genreLists[genreNum].length - 1;
            }
        }
    };
    $(document).ready(function() {
        $.get('/get-initial-stations/', function(data) {
            data.stations.forEach(function(stationList) {
                genreLists.push(stationList);
                genreMarkers.push(0);
            });
            if (nr.UrlManager.getHash().length == 0) {
                var faves = JSON.parse(localStorage.getItem('faves'));
                var faveStations = {};
                for(var i=0; i < faves.length; i++){
                    if(faves[i]['genreNum'] in faveStations) {
                        faveStations[faves[i]['genreNum']]++;
                    }
                    else {
                        faveStations[faves[i]['genreNum']] = 1;
                    }
                }
                var max_value = 0;
                var genreNumList = new Array();
                for(var key in faveStations) {
                    if(faveStations[key] > max_value) {
                        genreNumList = new Array(key);
                        max_value = faveStations[key];
                    }
                    else if (faveStations[key] == max_value) {
                        genreNumList.push(key);
                    }
                }
                genreNum = genreNumList[Math.floor(Math.random() * genreNumList.length)];
            }
            nr.MainController.initialStationsLoaded();
        });
    });

    return nr;
}(NowRadio || {}));
<commit_msg>cleaning up code for smart genre selection<commit_after>/*global $:false */
/*jshint -W116 */

/**
 * Manages the genres and their stations. Keeps track of what genres and stations have been
 * played and what will be played in the future.
 */
var NowRadio = (function(nr) {
    'use strict';
    var genreLists = [];
    var genreMarkers = [];
    var genreNum = 0;

    nr.StationsManager = {};

    nr.StationsManager.getNextGenre = function() {
        genreNum = (genreNum + 1) % genreLists.length;
        return this.getCurrentStation();
    };
    nr.StationsManager.getPrevGenre = function() {
        genreNum = (genreNum + genreLists.length - 1) % genreLists.length;
        return this.getCurrentStation();
    };
    nr.StationsManager.getNextStation = function() {
        genreMarkers[genreNum] = (genreMarkers[genreNum] + 1) % genreLists[genreNum].length;
        return this.getCurrentStation();
    };
    nr.StationsManager.getCurrentStation = function() {
        return genreLists[genreNum][genreMarkers[genreNum]];
    };
    nr.StationsManager.getPrevStation = function() {
        genreMarkers[genreNum] = (genreMarkers[genreNum] + (genreLists[genreNum].length - 1)) %
                                                            genreLists[genreNum].length;
        return this.getCurrentStation();
    };
    nr.StationsManager.getActiveGenre = function() {
        return genreNum;
    };
    nr.StationsManager.setActiveGenre = function(genreInfo) {
        if (genreNum === genreInfo) return false;
        genreNum = genreInfo;
        return true;
    };
    nr.StationsManager.removeCurrentThenNext = function() {
        genreLists[genreNum].splice(genreMarkers[genreNum], 1);
        genreMarkers[genreNum] -= 1;
        nr.StationChanger.nextStation();
    };
    nr.StationsManager.getGenreCount = function() {
        return genreLists.length;
    };
    nr.StationsManager.setStationFirstUnique = function(src) {
        callback();
        function callback() {
            if (genreMarkers.length < 1) return window.setTimeout(callback, 200);
            var currentLocation = genreLists[genreNum].indexOf(src);
            if (currentLocation != -1) {
                genreLists[genreNum][currentLocation] = genreLists[genreNum][0];
                genreLists[genreNum][0] = src;
                genreMarkers[genreNum] = 0;
            } else {
                genreLists[genreNum].push(src);
                genreMarkers[genreNum] = genreLists[genreNum].length - 1;
            }
        }
    };
    $(document).ready(function() {
        $.get('/get-initial-stations/', function(data) {
            data.stations.forEach(function(stationList) {
                genreLists.push(stationList);
                genreMarkers.push(0);
            });
            if (nr.UrlManager.getHash().length == 0) {
                // selecting genreNum based on the current
                var faves = JSON.parse(localStorage.getItem('faves'));
                if (faves.length == 0) {
                    genreNum = Math.floor(Math.random() * genreLists.length);
                } else {
                    var faveStations = {};
                    faves.forEach(function(element, index, array) {
                        if (element['genreNum'] in faveStations) {
                            faveStations[element['genreNum']]++;
                        } else {
                            faveStations[element['genreNum']] = 1;
                        }
                    });

                    var max_value = 0;
                    var genreNumList = [];
                    $.each(faveStations, function(key, value) {
                        if (value > max_value) {
                            genreNumList = [key];
                            max_value = value;
                        } else if (value == max_value) {
                            genreNumList.push(key);
                        }
                    });
                    genreNum = genreNumList[Math.floor(Math.random() * genreNumList.length)];
                }
            }
            nr.MainController.initialStationsLoaded();
        });
    });

    return nr;
}(NowRadio || {}));
<|endoftext|>


<commit_before>/* ============================================================
 * bootstrapSwitch v1.3 by Larentis Mattia @spiritualGuru
 * http://www.larentis.eu/switch/
 * ============================================================
 * Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 * ============================================================ */

!function ($) {
  "use strict";

  $.fn['bootstrapSwitch'] = function (method) {
    var methods = {
      init: function () {
        return this.each(function () {
            var $element = $(this)
              , $div
              , $switchLeft
              , $switchRight
              , $label
              , myClasses = ""
              , classes = $element.attr('class')
              , color
              , moving
              , onLabel = "ON"
              , offLabel = "OFF"
              , icon = false;

            $.each(['switch-mini', 'switch-small', 'switch-large'], function (i, el) {
              if (classes.indexOf(el) >= 0)
                myClasses = el;
            });

            $element.addClass('has-switch');

            if ($element.data('on') !== undefined)
              color = "switch-" + $element.data('on');

            if ($element.data('on-label') !== undefined)
              onLabel = $element.data('on-label');

            if ($element.data('off-label') !== undefined)
              offLabel = $element.data('off-label');

            if ($element.data('icon') !== undefined)
              icon = $element.data('icon');

            $switchLeft = $('')
              .addClass("switch-left")
              .addClass(myClasses)
              .addClass(color)
              .html(onLabel);

            color = '';
            if ($element.data('off') !== undefined)
              color = "switch-" + $element.data('off');

            $switchRight = $('')
              .addClass("switch-right")
              .addClass(myClasses)
              .addClass(color)
              .html(offLabel);

            $label = $('')
              .html(" ")
              .addClass(myClasses)
              .attr('for', $element.find('input').attr('id'));

            if (icon) {
              $label.html('');
            }

            $div = $element.find(':checkbox').wrap($('
')).parent().data('animated', false);

            if ($element.data('animated') !== false)
              $div.addClass('switch-animate').data('animated', true);

            $div
              .append($switchLeft)
              .append($label)
              .append($switchRight);

            $element.find('>div').addClass(
              $element.find('input').is(':checked') ? 'switch-on' : 'switch-off'
            );

            if ($element.find('input').is(':disabled'))
              $(this).addClass('deactivate');

            var changeStatus = function ($this) {
              $this.siblings('label').trigger('mousedown').trigger('mouseup').trigger('click');
            };

            $element.on('keydown', function (e) {
              if (e.keyCode === 32) {
                e.stopImmediatePropagation();
                e.preventDefault();
                changeStatus($(e.target).find('span:first'));
              }
            });

            $switchLeft.on('click', function (e) {
              changeStatus($(this));
            });

            $switchRight.on('click', function (e) {
              changeStatus($(this));
            });

            $element.find('input').on('change', function (e, skipOnChange) {
              var $this = $(this)
                , $element = $this.parent()
                , thisState = $this.is(':checked')
                , state = $element.is('.switch-off');

              e.preventDefault();

              $element.css('left', '');

              if (state === thisState) {

                if (thisState)
                  $element.removeClass('switch-off').addClass('switch-on');
                else $element.removeClass('switch-on').addClass('switch-off');

                if ($element.data('animated') !== false)
                  $element.addClass("switch-animate");

                if (typeof skipOnChange === 'boolean' && skipOnChange)
                  return;

                $element.parent().trigger('switch-change', {'el': $this, 'value': thisState})
              }
            });

            $element.find('label').on('mousedown touchstart', function (e) {
              var $this = $(this);
              moving = false;

              e.preventDefault();
              e.stopImmediatePropagation();

              $this.closest('div').removeClass('switch-animate');

              if ($this.closest('.has-switch').is('.deactivate'))
                $this.unbind('click');
              else {
                $this.on('mousemove touchmove', function (e) {
                  var $element = $(this).closest('.switch')
                    , relativeX = (e.pageX || e.originalEvent.targetTouches[0].pageX) - $element.offset().left
                    , percent = (relativeX / $element.width()) * 100
                    , left = 25
                    , right = 75;

                  moving = true;

                  if (percent < left)
                    percent = left;
                  else if (percent > right)
                    percent = right;

                  $element.find('>div').css('left', (percent - right) + "%")
                });

                $this.on('click touchend', function (e) {
                  var $this = $(this)
                    , $target = $(e.target)
                    , $myCheckBox = $target.siblings('input');

                  e.stopImmediatePropagation();
                  e.preventDefault();

                  $this.unbind('mouseleave');

                  if (moving)
                    $myCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25));
                  else $myCheckBox.prop("checked", !$myCheckBox.is(":checked"));

                  moving = false;
                  $myCheckBox.trigger('change');
                });

                $this.on('mouseleave', function (e) {
                  var $this = $(this)
                    , $myCheckBox = $this.siblings('input');

                  e.preventDefault();
                  e.stopImmediatePropagation();

                  $this.unbind('mouseleave');
                  $this.trigger('mouseup');

                  $myCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25)).trigger('change');
                });

                $this.on('mouseup', function (e) {
                  e.stopImmediatePropagation();
                  e.preventDefault();

                  $(this).unbind('mousemove');
                });
              }
            });
          }
        );
      },
      toggleActivation: function () {
        $(this).toggleClass('deactivate');
      },
      isActive: function () {
        return !$(this).hasClass('deactivate');
      },
      setActive: function (active) {
        if (active)
          $(this).removeClass('deactivate');
        else $(this).addClass('deactivate');
      },
      toggleState: function (skipOnChange) {
        var $input = $(this).find('input:checkbox');
        $input.prop('checked', !$input.is(':checked')).trigger('change', skipOnChange);
      },
      setState: function (value, skipOnChange) {
        $(this).find('input:checkbox').prop('checked', value).trigger('change', skipOnChange);
      },
      status: function () {
        return $(this).find('input:checkbox').is(':checked');
      },
      destroy: function () {
        var $div = $(this).find('div')
          , $checkbox;

        $div.find(':not(input:checkbox)').remove();

        $checkbox = $div.children();
        $checkbox.unwrap().unwrap();

        $checkbox.unbind('change');

        return $checkbox;
      }
    };

    if (methods[method])
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    else if (typeof method === 'object' || !method)
      return methods.init.apply(this, arguments);
    else
      $.error('Method ' + method + ' does not exist!');
  };
}(jQuery);

$(function () {
  $('.switch')['bootstrapSwitch']();
});
<commit_msg>Update to V1.3.1<commit_after>/* ============================================================
 * bootstrapSwitch v1.3 by Larentis Mattia @spiritualGuru
 * http://www.larentis.eu/switch/
 *
 * bootstrapSwitch v1.3.1 by Stein, Peter @BdMdesigN
 *
 * enhanced by BdMdesigN
 * http://www.bdmdesign.org
 * ============================================================
 * Licensed under the Apache License, Version 2.0
 * http://www.apache.org/licenses/LICENSE-2.0
 * ============================================================ */

!function ($) {
  "use strict";

  $.fn['bootstrapSwitch'] = function (method) {
    var methods = {
      init: function () {
        return this.each(function () {
            var $element = $(this)
              , $div
              , $switchLeft
              , $switchRight
              , $label
              , myClasses = ""
              , classes = $element.attr('class')
              , color
              , moving
              , onLabel = "ON"
              , offLabel = "OFF"
              , icon = false;

            $.each(['switch-mini', 'switch-small', 'switch-large'], function (i, el) {
              if (classes.indexOf(el) >= 0)
                myClasses = el;
            });

            $element.addClass('has-switch');

            if ($element.data('on') !== undefined)
              color = "switch-" + $element.data('on');

            if ($element.data('on-label') !== undefined)
              onLabel = $element.data('on-label');

            if ($element.data('off-label') !== undefined)
              offLabel = $element.data('off-label');

            if ($element.data('icon') !== undefined)
              icon = $element.data('icon');

            $switchLeft = $('')
              .addClass("switch-left")
              .addClass(myClasses)
              .addClass(color)
              .html(onLabel);

            color = '';
            if ($element.data('off') !== undefined)
              color = "switch-" + $element.data('off');

            $switchRight = $('')
              .addClass("switch-right")
              .addClass(myClasses)
              .addClass(color)
              .html(offLabel);

            $label = $('')
              .html(" ")
              .addClass(myClasses)
              .attr('for', $element.find('input').attr('id'));

            if (icon) {
              $label.html('');
            }

            $div = $element.find('input[type=radio],input[type=checkbox]').wrap($('
')).parent().data('animated', false);

            if ($element.data('animated') !== false)
              $div.addClass('switch-animate').data('animated', true);

            $div
              .append($switchLeft)
              .append($label)
              .append($switchRight);

            $element.find('>div').addClass(
              $element.find('input[type=radio],input[type=checkbox]').is(':checked') ? 'switch-on' : 'switch-off'
            );

            if ($element.find('input[type=radio],input[type=checkbox]').is(':disabled'))
              $(this).addClass('deactivate');

            var changeStatus = function ($this) {
              $this.siblings('label').trigger('mousedown').trigger('mouseup').trigger('click');
            };

            $element.on('keydown', function (e) {
              if (e.keyCode === 32) {
                e.stopImmediatePropagation();
                e.preventDefault();
                changeStatus($(e.target).find('span:first'));
              }
            });

            $switchLeft.on('click', function (e) {
              changeStatus($(this));
            });

            $switchRight.on('click', function (e) {
              changeStatus($(this));
            });

            $element.find('input[type=radio],input[type=checkbox]').on('change', function (e, skipOnChange) {
              var $this = $(this)
                , $element = $this.parent()
                , thisState = $this.is(':checked')
                , state = $element.is('.switch-off');

              e.preventDefault();

              $element.css('left', '');

              if (state === thisState) {

                if (thisState)
                  $element.removeClass('switch-off').addClass('switch-on');
                else $element.removeClass('switch-on').addClass('switch-off');

                if ($element.data('animated') !== false)
                  $element.addClass("switch-animate");

                if (typeof skipOnChange === 'boolean' && skipOnChange)
                  return;

                $element.parent().trigger('switch-change', {'el': $this, 'value': thisState})
              }
            });

            $element.find('label').on('mousedown touchstart', function (e) {
              var $this = $(this);
              moving = false;

              e.preventDefault();
              e.stopImmediatePropagation();

              $this.closest('div').removeClass('switch-animate');

              if ($this.closest('.has-switch').is('.deactivate'))
                $this.unbind('click');
              else {
                $this.on('mousemove touchmove', function (e) {
                  var $element = $(this).closest('.switch')
                    , relativeX = (e.pageX || e.originalEvent.targetTouches[0].pageX) - $element.offset().left
                    , percent = (relativeX / $element.width()) * 100
                    , left = 25
                    , right = 75;

                  moving = true;

                  if (percent < left)
                    percent = left;
                  else if (percent > right)
                    percent = right;

                  $element.find('>div').css('left', (percent - right) + "%")
                });

                $this.on('click touchend', function (e) {
                  var $this = $(this)
                    , $target = $(e.target)
                    , $myRadioCheckBox = $target.siblings('input[type=radio],input[type=checkbox]');

                  e.stopImmediatePropagation();
                  e.preventDefault();

                  $this.unbind('mouseleave');

                  if (moving)
                    $myRadioCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25));
                  else
                    $myRadioCheckBox.prop("checked", !$myRadioCheckBox.is(":checked"));

                  moving = false;
                  $myRadioCheckBox.trigger('change');
                });

                $this.on('mouseleave', function (e) {
                  var $this = $(this)
                    , $myInputBox = $this.siblings('input[type=radio],input[type=checkbox]');

                  e.preventDefault();
                  e.stopImmediatePropagation();

                  $this.unbind('mouseleave');
                  $this.trigger('mouseup');

                  $myInputBox.prop('checked', !(parseInt($this.parent().css('left')) < -25)).trigger('change');
                });

                $this.on('mouseup', function (e) {
                  e.stopImmediatePropagation();
                  e.preventDefault();

                  $(this).unbind('mousemove');
                });
              }
            });
          }
        );
      },
      toggleActivation: function () {
        $(this).toggleClass('deactivate');
      },
      isActive: function () {
        return !$(this).hasClass('deactivate');
      },
      setActive: function (active) {
        if (active)
          $(this).removeClass('deactivate');
        else $(this).addClass('deactivate');
      },
      toggleState: function (skipOnChange) {
        var $input = $(this).find('input[type=radio],input[type=checkbox]');
        $input.prop('checked', !$input.is(':checked')).trigger('change', skipOnChange);
      },
      setState: function (value, skipOnChange) {
        $(this).find('input[type=radio],input[type=checkbox]').prop('checked', value).trigger('change', skipOnChange);
      },
      status: function () {
        return $(this).find('input[type=radio],input[type=checkbox]').is(':checked');
      },
      destroy: function () {
        var $div = $(this).find('div')
          , $inputbox;

        $div.find(':not(input:radio),:not(input:checkbox').remove();

        $inputbox = $div.children();
        $inputbox.unwrap().unwrap();

        $inputbox.unbind('change');

        return $inputbox;
      }
    };

    if (methods[method])
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    else if (typeof method === 'object' || !method)
      return methods.init.apply(this, arguments);
    else
      $.error('Method ' + method + ' does not exist!');
  };
}(jQuery);

$(function () {
  $('.switch')['bootstrapSwitch']();
});
<|endoftext|>