<commit_before>#!/usr/bin/env node

// converts json grammar format to Jison grammar format

var IO = require('./util/io');

function json2jison (grammar, options) {
    options = options || {};
    var s = "";

    s += genDecls(grammar, options);
    s += genBNF(grammar.bnf, options);

    return s;
}

function genDecls (grammar, options) {
    var s = "",
        key;

    for (key in grammar) if (grammar.hasOwnProperty(key)) {
        if (key === 'start') {
            s += "\n%start "+grammar.start+"\n\n";
        }
        else if (key === 'author') {
            s += "\n/* author: "+grammar.author+" */\n\n";
        }
        else if (key === 'comment') {
            s += "\n/* description: "+grammar.comment+" */\n\n";
        }
        else if (key === 'lex') {
            s += "%lex\n"+genLex(grammar.lex)+"/lex\n\n";
        }
        else if (key === 'operators') {
            for (var i=0; i<grammar.operators.length; i++) {
                s += "%"+grammar.operators[i][0]+' '+quoteSymbols(grammar.operators[i].slice(1).join(' '))+"\n";
            }
            s += "\n";
        }
    }

    return s;
}

function genBNF (bnf, options) {
    var s = "%%\n",
        sym;

    for (sym in bnf) if (bnf.hasOwnProperty(sym)) {
        s += ["\n",sym,'\n    : ', genHandles(bnf[sym], options),"\n    ;\n"].join("");
    }

    return s;
}

function genHandles (handle, options) {
    if (typeof handle === 'string') {
        return handle;
    } else { //array
        var s = "";
        for (var i=0; i< handle.length;i++) {
            if (typeof handle[i] === 'string' && handle[i]) {
                s += quoteSymbols(handle[i]);
            } else if (handle[i] instanceof Array) {
                s += (handle[i][0] && quoteSymbols(handle[i][0]));
                if (typeof handle[i][1] === 'string') {
                    if (!options.stripActions) {
                        s += "\n        {"+handle[i][1]+"}";
                    }
                    if (handle[i][2] && handle[i][2].prec) {
                        s += " %prec "+handle[i][2].prec;
                    }
                } else if (handle[i][1].prec) {
                    s += " %prec "+handle[i][1].prec;
                }
            }
            if (typeof handle[i+1] !== 'undefined')
                s += "\n    | ";
        }
        return s;
    }
}

function quoteSymbols (rhs) {
    rhs = rhs.split(' ');

    for (var i=0; i<rhs.length; i++) {
        rhs[i] = quoteSymbol(rhs[i]);
    }
    return rhs.join(' ');
}

function quoteSymbol (sym) {
    if (!/[a-zA-Z][a-zA-Z0-9_-]*/.test(sym)) {
        var quote = /'/.test(sym) ? '"' : "'";
        sym = quote+sym+quote;
    }
    return sym;
}

// Generate lex format from lex JSON

function genLex (lex) {
    var s = [];
    var indent = 28;

    if ('macros' in lex) {
        for (var macro in lex.macros) {
            s.push(macro, new Array(indent-macro.length+1).join(' '),lex.macros[macro], '\n');
        }
    }
    if ('startConditions' in lex) {
        var ps = [];
        var px = [];
        for (var st in lex.startConditions) {
            if (lex.startConditions[st])
                px.push(st);
            else
                ps.push(st);
        }
        if (ps.length) s.push('%s ', ps.join(' '));
        if (px.length) s.push('%x ', px.join(' '));
    }
    if ('actionInclude' in lex) {
        s.push('\n%{\n', lex.actionInclude, '\n%}\n');
    }
    s.push('\n%%\n');
    if ('rules' in lex) {
        for (var rule;rule=lex.rules.shift();) {
            if (rule.length > 2) s.push('<'+rule.shift().join(',')+'>');
            var reg = genLexRegex(rule[0]);
            s.push(reg, new Array(indent-reg.length+1).join(' '), genLexRule(rule[1]), '\n');
        }
    }
    s.push('\n');

    return s.join('');
}
function genLexRegex (regex) {
    var matcher = regex.replace(/^([a-zA-Z0-9]+)\\b$/, "\"$1\"")
                       .replace(/\\([.*+?^${}()|[\]\/\\])/g,"$1")
                       .replace(/^\$$/,"<<EOF>>")
                       .replace(/^([.*+?^${}()|[\]\/\\\-;=,><!@#%&]+)$/,"\"$1\"")
    return matcher;
}
function genLexRule (rule) {
    return rule.match(/\n/) ? '%{'+rule+'%}' : rule;
}

exports.json2jison = json2jison;
exports.convert = json2jison;

exports.main = function main (args) {
    if(args.length == 1) return;

    var raw = IO.read(IO.join(IO.cwd(),args[1]));
    var name = IO.basename(args[1]).replace(/\..*$/g,'');
    var grammar = JSON.parse(raw);

    if ('bnf' in grammar || 'lex' in grammar) {
        IO.write(IO.join(IO.cwd(),name+".jison"), json2jison(grammar));
    }
};

if (typeof process !== 'undefined' || require.main === module)
    exports.main(IO.args);

<commit_msg>detect longest rule when determining column alignment<commit_after>#!/usr/bin/env node

// converts json grammar format to Jison grammar format

var IO = require('./util/io');

function json2jison (grammar, options) {
    options = options || {};
    var s = "";

    s += genDecls(grammar, options);
    s += genBNF(grammar.bnf, options);

    return s;
}

function genDecls (grammar, options) {
    var s = "",
        key;

    for (key in grammar) if (grammar.hasOwnProperty(key)) {
        if (key === 'start') {
            s += "\n%start "+grammar.start+"\n\n";
        }
        else if (key === 'author') {
            s += "\n/* author: "+grammar.author+" */\n\n";
        }
        else if (key === 'comment') {
            s += "\n/* description: "+grammar.comment+" */\n\n";
        }
        else if (key === 'lex') {
            s += "%lex\n"+genLex(grammar.lex)+"/lex\n\n";
        }
        else if (key === 'operators') {
            for (var i=0; i<grammar.operators.length; i++) {
                s += "%"+grammar.operators[i][0]+' '+quoteSymbols(grammar.operators[i].slice(1).join(' '))+"\n";
            }
            s += "\n";
        }
    }

    return s;
}

function genBNF (bnf, options) {
    var s = "%%\n",
        sym;

    for (sym in bnf) if (bnf.hasOwnProperty(sym)) {
        s += ["\n",sym,'\n    : ', genHandles(bnf[sym], options),"\n    ;\n"].join("");
    }

    return s;
}

function genHandles (handle, options) {
    if (typeof handle === 'string') {
        return handle;
    } else { //array
        var s = "";
        for (var i=0; i< handle.length;i++) {
            if (typeof handle[i] === 'string' && handle[i]) {
                s += quoteSymbols(handle[i]);
            } else if (handle[i] instanceof Array) {
                s += (handle[i][0] && quoteSymbols(handle[i][0]));
                if (typeof handle[i][1] === 'string') {
                    if (!options.stripActions) {
                        s += "\n        {"+handle[i][1]+"}";
                    }
                    if (handle[i][2] && handle[i][2].prec) {
                        s += " %prec "+handle[i][2].prec;
                    }
                } else if (handle[i][1].prec) {
                    s += " %prec "+handle[i][1].prec;
                }
            }
            if (typeof handle[i+1] !== 'undefined')
                s += "\n    | ";
        }
        return s;
    }
}

function quoteSymbols (rhs) {
    rhs = rhs.split(' ');

    for (var i=0; i<rhs.length; i++) {
        rhs[i] = quoteSymbol(rhs[i]);
    }
    return rhs.join(' ');
}

function quoteSymbol (sym) {
    if (!/[a-zA-Z][a-zA-Z0-9_-]*/.test(sym)) {
        var quote = /'/.test(sym) ? '"' : "'";
        sym = quote+sym+quote;
    }
    return sym;
}

// Generate lex format from lex JSON

function genLex (lex) {
    var s = [];
    var indent = 28;

    if ('macros' in lex) {
        for (var macro in lex.macros) {
            s.push(macro, new Array(indent-macro.length+1).join(' '),lex.macros[macro], '\n');
        }
    }
    if ('startConditions' in lex) {
        var ps = [];
        var px = [];
        for (var st in lex.startConditions) {
            if (lex.startConditions[st])
                px.push(st);
            else
                ps.push(st);
        }
        if (ps.length) s.push('%s ', ps.join(' '));
        if (px.length) s.push('%x ', px.join(' '));
    }
    if ('actionInclude' in lex) {
        s.push('\n%{\n', lex.actionInclude, '\n%}\n');
    }
    s.push('\n%%\n');

    var longestRule = lex.rules.reduce(function (prev, curr) { return prev > curr[0].length ? prev : curr[0].length; }, 0);
    if ('rules' in lex) {
        for (var rule;rule=lex.rules.shift();) {
            if (rule.length > 2) s.push('<'+rule.shift().join(',')+'>');
            var reg = genLexRegex(rule[0]);
            s.push(reg, new Array(longestRule-reg.length+5).join(' '), genLexRule(rule[1]), '\n');
        }
    }
    s.push('\n');

    return s.join('');
}

function genLexRegex (regex) {
    var matcher = regex.replace(/^([a-zA-Z0-9]+)\\b$/, "\"$1\"")
                       .replace(/\\([.*+?^${}()|[\]\/\\])/g,"$1")
                       .replace(/^\$$/,"<<EOF>>")
                       .replace(/^([.*+?^${}()|[\]\/\\\-;=,><!@#%&]+)$/,"\"$1\"")
    return matcher;
}
function genLexRule (rule) {
    return rule.match(/\n/) ? '%{'+rule+'%}' : rule;
}

exports.json2jison = json2jison;
exports.convert = json2jison;

exports.main = function main (args) {
    if(args.length == 1) return;

    var raw = IO.read(IO.join(IO.cwd(),args[1]));
    var name = IO.basename(args[1]).replace(/\..*$/g,'');
    var grammar = JSON.parse(raw);

    if ('bnf' in grammar || 'lex' in grammar) {
        IO.write(IO.join(IO.cwd(),name+".jison"), json2jison(grammar));
    }
};

if (typeof process !== 'undefined' || require.main === module)
    exports.main(IO.args);

<|endoftext|>


<commit_before>/*! jquery.modal 0.2.2 Copyright (c) 2013 Alan Plum. MIT licensed. */(function(e){typeof exports=="object"?e(require("jquery")):typeof define=="function"&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,n){var r=null;return function(){return r||(r=t.apply(this,arguments),t=e.noop),n?n.apply(this,arguments):r}}function n(e,t,n){var r,i,s;n=n||0;for(r=0;r<e.api.length;r++){i=e.api[r];if(i[0]!==t)continue;s=i[1]||e.prototype[t];if(s.length===n)return s}return null}function o(t,n){this._options=e.extend({},n),this.$el=e("<div/>").css({position:"fixed",zIndex:11e3,left:"50%",top:0,marginLeft:0}).hide(),typeof t=="string"?this.$el.text(t):e(t).detach().appendTo(this.$el)}var r=Array.prototype.slice,i=e.extend(function(t){var i=r.call(arguments,1),s=n(o,t,i.length),u;if(s){u=s.apply(this.data("modal"),i);if(u!==undefined)return u}else this.each(function(){var n=e(this);n.data("modal")||n.data("modal",new o(this,t))});return this},{overlay:{showFn:function(e){this.css("background","black"),this.fadeTo(200,.5,e)},hideFn:function(e){this.fadeOut(1,e)}},defaults:{showFn:function(e){this.fadeIn(200,e)},hideFn:function(e){this.fadeOut(200,e)}},_overlay:s,_Modal:o}),s={$el:e("<div/>").css({position:"fixed",zIndex:1e4,left:0,top:0,width:"100%",height:"100%"}).hide(),open:t(function(){this.$el.appendTo("body")},function(e){var t=i.overlay.showFn,n=this.$el;t.call(n,e)}),close:function(e){var t=i.overlay.hideFn,n=this.$el;t.call(n,e)}};o.api=[["open"],["close"],["option",function(e){return this.getOption(e)}],["option",function(e,t){return this._options[e]=t,t}]],e.extend(o.prototype,{getOption:function(e){return this._options.hasOwnProperty(e)?this._options[e]:i.defaults[e]},open:function(){var t=this.getOption("showFn"),n=this.$el;s.open(function(){n.appendTo("body").css({marginLeft:-(n.width()/2)+"px",top:e(window).height()/2-n.height()/2+"px"}),t.call(n)})},close:function(){var e=this.getOption("hideFn"),t=this.$el;e.call(t,function(){t.detach(),s.close()})}}),e.fn.modal=i});<commit_msg>Bumped minified.<commit_after>/*! jQuery.modal 0.2.3 Copyright (c) 2013 Alan Plum. MIT License */(function(e){function t(t,n){var r=null;return function(){return r||(r=t.apply(this,arguments),t=e.noop),n?n.apply(this,arguments):r}}function n(e,t,n){var r,i,s;n=n||0;for(r=0;r<e.api.length;r++){i=e.api[r];if(i[0]!==t)continue;s=i[1]||e.prototype[t];if(s.length===n)return s}return null}function o(t,n){this._options=e.extend({},n),this.$el=e("<div/>").css({position:"fixed",zIndex:11e3,left:"50%",top:0,marginLeft:0}).hide(),typeof t=="string"?this.$el.text(t):e(t).detach().appendTo(this.$el)}var r=Array.prototype.slice,i=e.extend(function(t){var i=r.call(arguments,1),s=n(o,t,i.length),u;if(s){u=s.apply(this.data("modal"),i);if(u!==undefined)return u}else this.each(function(){var n=e(this);n.data("modal")||n.data("modal",new o(this,t))});return this},{overlay:{showFn:function(e){this.css("background","black"),this.fadeTo(200,.5,e)},hideFn:function(e){this.fadeOut(1,e)}},defaults:{showFn:function(e){this.fadeIn(200,e)},hideFn:function(e){this.fadeOut(200,e)}},_overlay:s,_Modal:o}),s={$el:e("<div/>").css({position:"fixed",zIndex:1e4,left:0,top:0,width:"100%",height:"100%"}).hide(),open:t(function(){this.$el.appendTo("body")},function(e){var t=i.overlay.showFn,n=this.$el;t.call(n,e)}),close:function(e){var t=i.overlay.hideFn,n=this.$el;t.call(n,e)}};o.api=[["open"],["close"],["center"],["option",function(e){return this.getOption(e)}],["option",function(e,t){return this._options[e]=t,t}]],e.extend(o.prototype,{getOption:function(e){return this._options.hasOwnProperty(e)?this._options[e]:i.defaults[e]},open:function(){var e=this.getOption("showFn"),t=this;s.open(function(){t.$el.appendTo("body"),t.center(),e.call(t.$el),t.$el.trigger("modal:open")})},close:function(){var e=this.getOption("hideFn"),t=this;e.call(this.$el,function(){t.$el.detach(),s.close(),t.$el.trigger("modal:close")})},center:function(){this.$el.css({marginLeft:-(this.$el.width()/2)+"px",top:e(window).height()/2-this.$el.height()/2+"px"})}}),e.fn.modal=i})(jQuery);<|endoftext|>


<commit_before>// for standard
/* globals requestAnimationFrame, io, location */
// npm requires
const kbd = require('@dasilvacontin/keyboard')
const deepEqual = require('deep-equal')
const swal = require('sweetalert')
// local requires
const GameClient = require('./gameClient.js')
const GameRenderer = require('./gameRenderer.js')
const GameAudio = require('./gameAudio.js')
const engine = require('../common/engine.js')

// we need to add a couple keys to @dasilvacontin's keyboard package!
kbd.Q_KEY = 81
kbd.R_KEY = 82
kbd.W_KEY = 87
kbd.A_KEY = 65
kbd.S_KEY = 83
kbd.D_KEY = 68
// socket.io
const socket = io()
// we initialise the game
var game = new GameClient()
// init the renderer
var renderer = new GameRenderer()
// and add a reference to the on onClick callback
// for when we click on the canvas
renderer.registerOnClickCallback(onClick)
// now, the audio
const sounds = {
  hasagi: 'sounds/hasagi.mp3',
  ulti: 'sounds/ulti.mp3',
  danger: 'sounds/danger.wav'
}
// we can access all sounds via their name later.
var audio = new GameAudio(sounds, 10)

let myUsername
const myInputs = new engine.Inputs()
const myAttackInputs = new engine.AttackInputs()

// ping calculus
let lastPingTimestamp
// how many ms the server is ahead from us
let clockDiff = 0
let ping = Infinity

// ping handshaking
function startPingHandshake () {
  lastPingTimestamp = Date.now()
  socket.emit('game:ping')
}
setInterval(startPingHandshake, 250)

// socket handling
socket.on('connect', function () {
  console.log('connected to the server')

  socket.on('game:pong', (serverNow) => {
    ping = (Date.now() - lastPingTimestamp) / 2
    clockDiff = (serverNow + ping) - Date.now()
  })

  socket.on('player:getusername', () => {
    if (myUsername) {
      // If our username is already set, we bail
      return
    }
    swal({
      title: 'Introduce your name!',
      text: 'How do you want to be called as, oh brave warrior?',
      type: 'input',
      closeOnConfirm: true,
      showCancelButton: false,
      animation: 'slide-from-top'
    }, function (inputValue) {
      myUsername = inputValue
      socket.emit('player:setusername', myUsername)
    })
  })

  socket.on('game:init', (players, playerId) => {
    console.log('game started')
    game.onGameInit(players, playerId)
  })

  socket.on('game.tornados:update', (tornados) => {
    game.tornados = tornados
    if (tornados.length <= 0) {
      audio.play('danger')
    } else {
      audio.play('hasagi')
    }
  })

  socket.on('player:update', (player) => {
    if (player.isDead && game.isRunning) {
      audio.play('ulti')
      if (player.id === game.myPlayerId && game.isRunning) {
        swal({
          title: 'You are dead!',
          text: `Press OK to respawn...`,
          type: 'info',
          closeOnConfirm: true,
          showConfirmButton: true,
          disableButtonsOnConfirm: true
        }, function () {
          location.reload()
        })
      }
    }
    game.players[player.id] = player
  })

  socket.on('game.players:update', (players) => {
    game.players = players
  })

  socket.on('game.players:new', (player) => {
    game.onNewPlayer(player)
  })
})

function onClick (event) {
  // we are not using this for the time being
  // socket.emit('player:click', renderer.mousePos)
}

function updateInputs () {
  const oldInputs = Object.assign({}, myInputs)

  // using @dasilvacontin's keyboard package, we can update the
  // inputs of our player based on the keyboard's state
  for (let key in myInputs) {
    myInputs[key] = kbd.isKeyDown(kbd[key])
  }

  if (!deepEqual(myInputs, oldInputs)) {
    socket.emit('player:move', myInputs)

    // update our local player' inputs aproximately when the server
    // takes them into account
    const frozenInputs = Object.assign({}, myInputs)
    setTimeout(function () {
      const myPlayer = game.getMyPlayer()
      myPlayer.inputs = frozenInputs
    }, ping)
  }

  const oldAttackinputs = Object.assign({}, myAttackInputs)

  for (let key in myAttackInputs) {
    myAttackInputs[key] = kbd.isKeyDown(kbd[key])
  }
  if (!deepEqual(myAttackInputs, oldAttackinputs)) {
    socket.emit('player:attack', myAttackInputs, renderer.mousePos)
  }

  // Check for debug mode on or off
  if (kbd.isKeyDown(48)) {
    console.log('in deb')
    game.isInDebugMode = true
  } else if (kbd.isKeyDown(49)) {
    console.log('out deb')
    game.isInDebugMode = false
  }
}

// initialise last registered timestamp
let past = Date.now()
// main game loop
function gameloop () {
  requestAnimationFrame(gameloop)
  if (!game.isRunning) { return }
  const now = Date.now()
  const delta = (now - past) / 1000
  past = now
  // once we have delta calculated we update our inputs
  updateInputs()
  // and we run our game logic
  game.logic(delta)
  // packaging info to be sent to the renderer
  game.ping = ping
  game.clockDiff = clockDiff
  // render the game
  renderer.render(delta, game)
}

requestAnimationFrame(gameloop)
<commit_msg>:sparkles: Name trimmed<commit_after>// for standard
/* globals requestAnimationFrame, io, location */
// npm requires
const kbd = require('@dasilvacontin/keyboard')
const deepEqual = require('deep-equal')
const swal = require('sweetalert')
// local requires
const GameClient = require('./gameClient.js')
const GameRenderer = require('./gameRenderer.js')
const GameAudio = require('./gameAudio.js')
const engine = require('../common/engine.js')

// we need to add a couple keys to @dasilvacontin's keyboard package!
kbd.Q_KEY = 81
kbd.R_KEY = 82
kbd.W_KEY = 87
kbd.A_KEY = 65
kbd.S_KEY = 83
kbd.D_KEY = 68
// socket.io
const socket = io()
// we initialise the game
var game = new GameClient()
// init the renderer
var renderer = new GameRenderer()
// and add a reference to the on onClick callback
// for when we click on the canvas
renderer.registerOnClickCallback(onClick)
// now, the audio
const sounds = {
  hasagi: 'sounds/hasagi.mp3',
  ulti: 'sounds/ulti.mp3',
  danger: 'sounds/danger.wav'
}
// we can access all sounds via their name later.
var audio = new GameAudio(sounds, 10)

let myUsername
const myInputs = new engine.Inputs()
const myAttackInputs = new engine.AttackInputs()

// ping calculus
let lastPingTimestamp
// how many ms the server is ahead from us
let clockDiff = 0
let ping = Infinity

// ping handshaking
function startPingHandshake () {
  lastPingTimestamp = Date.now()
  socket.emit('game:ping')
}
setInterval(startPingHandshake, 250)

// socket handling
socket.on('connect', function () {
  console.log('connected to the server')

  socket.on('game:pong', (serverNow) => {
    ping = (Date.now() - lastPingTimestamp) / 2
    clockDiff = (serverNow + ping) - Date.now()
  })

  socket.on('player:getusername', () => {
    if (myUsername) {
      // If our username is already set, we bail
      return
    }
    swal({
      title: 'Introduce your name!',
      text: 'How do you want to be called as, oh brave warrior?',
      type: 'input',
      closeOnConfirm: true,
      showCancelButton: false,
      animation: 'slide-from-top'
    }, function (inputValue) {
      myUsername = "yasuo's apprentice, " + inputValue.substring(0, 20)
      socket.emit('player:setusername', myUsername)
    })
  })

  socket.on('game:init', (players, playerId) => {
    console.log('game started')
    game.onGameInit(players, playerId)
  })

  socket.on('game.tornados:update', (tornados) => {
    game.tornados = tornados
    if (tornados.length <= 0) {
      audio.play('danger')
    } else {
      audio.play('hasagi')
    }
  })

  socket.on('player:update', (player) => {
    if (player.isDead && game.isRunning) {
      audio.play('ulti')
      if (player.id === game.myPlayerId && game.isRunning) {
        swal({
          title: 'You are dead!',
          text: `Press OK to respawn...`,
          type: 'info',
          closeOnConfirm: true,
          showConfirmButton: true,
          disableButtonsOnConfirm: true
        }, function () {
          location.reload()
        })
      }
    }
    game.players[player.id] = player
  })

  socket.on('game.players:update', (players) => {
    game.players = players
  })

  socket.on('game.players:new', (player) => {
    game.onNewPlayer(player)
  })
})

function onClick (event) {
  // we are not using this for the time being
  // socket.emit('player:click', renderer.mousePos)
}

function updateInputs () {
  const oldInputs = Object.assign({}, myInputs)

  // using @dasilvacontin's keyboard package, we can update the
  // inputs of our player based on the keyboard's state
  for (let key in myInputs) {
    myInputs[key] = kbd.isKeyDown(kbd[key])
  }

  if (!deepEqual(myInputs, oldInputs)) {
    socket.emit('player:move', myInputs)

    // update our local player' inputs aproximately when the server
    // takes them into account
    const frozenInputs = Object.assign({}, myInputs)
    setTimeout(function () {
      const myPlayer = game.getMyPlayer()
      myPlayer.inputs = frozenInputs
    }, ping)
  }

  const oldAttackinputs = Object.assign({}, myAttackInputs)

  for (let key in myAttackInputs) {
    myAttackInputs[key] = kbd.isKeyDown(kbd[key])
  }
  if (!deepEqual(myAttackInputs, oldAttackinputs)) {
    socket.emit('player:attack', myAttackInputs, renderer.mousePos)
  }

  // Check for debug mode on or off
  if (kbd.isKeyDown(48)) {
    console.log('in deb')
    game.isInDebugMode = true
  } else if (kbd.isKeyDown(49)) {
    console.log('out deb')
    game.isInDebugMode = false
  }
}

// initialise last registered timestamp
let past = Date.now()
// main game loop
function gameloop () {
  requestAnimationFrame(gameloop)
  if (!game.isRunning) { return }
  const now = Date.now()
  const delta = (now - past) / 1000
  past = now
  // once we have delta calculated we update our inputs
  updateInputs()
  // and we run our game logic
  game.logic(delta)
  // packaging info to be sent to the renderer
  game.ping = ping
  game.clockDiff = clockDiff
  // render the game
  renderer.render(delta, game)
}

requestAnimationFrame(gameloop)
<|endoftext|>


<commit_before>'use strict'

var winston = require('winston');
var path = require('path');
// winston.emitErrs = true;

var logger = new winston.Logger({
    transports: [
        new winston.transports.File({
            level: 'info',
            filename: path.join(__dirname, '../../logs/debug', 'debug-logs'),
            handleExceptions: true,
            json: true,
            maxsize: 5242880, //5MB
            maxFiles: 5,
            colorize: false
        }),
        new winston.transports.Console({
            level: 'debug',
            handleExceptions: true,
            json: false,
            colorize: true
        })
    ],
    exitOnError: false
});

module.exports = logger;
module.exports.stream = {
    write: function(message, encoding){
        logger.info(message);
    }
};<commit_msg>fix / smarter logging of errors<commit_after>'use strict'

var winston = require('winston');
var path = require('path');
// winston.emitErrs = true;

var logger = new winston.Logger({
    transports: [
        new winston.transports.File({
            level: 'error',
            filename: path.join(__dirname, '../../logs/error', 'error.log'),
            handleExceptions: true,
            json: true,
            maxsize: 5242880, //5MB
            maxFiles: 5,
            colorize: false
        }),
        new winston.transports.Console({
            level: 'info',
            handleExceptions: true,
            json: false,
            colorize: true
        })
    ],
    exitOnError: false
});

module.exports = logger;
module.exports.stream = {
    write: function(message, encoding){
        logger.info(message);
    }
};<|endoftext|>


<commit_before>(function ($) {

  /**
   * Check if arg is either an array with at least 1 element, or a dict with at least 1 key
   * @return boolean
   */
  function isCollapsable(arg) {
    return arg instanceof Object && Object.keys(arg).length > 0;
  }

  /**
   * Check if a string represents a valid url
   * @return boolean
   */
  function isUrl(string) {
    var regexp = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
    return regexp.test(string);
  }

  /**
   * Transform a json object into html representation
   * @return string
   */
  function json2html(json, options) {
    var html = '';
    if (typeof json === 'string') {
      // Escape tags
      json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
      if (isUrl(json))
        html += '' + json + '';
      else
        html += '"' + json + '"';
    }
    else if (typeof json === 'number') {
      html += '' + json + '';
    }
    else if (typeof json === 'boolean') {
      html += '' + json + '';
    }
    else if (json === null) {
      html += 'null';
    }
    else if (json instanceof Array) {
      if (json.length > 0) {
        html += '[
';
        for (var i = 0; i < json.length; ++i) {
          html += '
'
          // Add toggle button if item is collapsable
          if (isCollapsable(json[i])) {
            html += '';
          }
          html += json2html(json[i], options);
          // Add comma if item is not last
          if (i < json.length - 1) {
            html += ',';
          }
          html += '
';
        }
        html += '
]';
      }
      else {
        html += '[]';
      }
    }
    else if (typeof json === 'object') {
      var key_count = Object.keys(json).length;
      if (key_count > 0) {
        html += '{
';
        for (var key in json) {
          if (json.hasOwnProperty(key)) {
            html += '
';
            var keyRepr = options.outputWithQuotes ?
              '"' + key + '"' : key;

            // Add toggle button if item is collapsable
            if (isCollapsable(json[key])) {
              html += '' + keyRepr + '';
            }
            else {
              html += keyRepr;
            }
            html += '📋';
            html += ': ' + json2html(json[key], options);
            // Add comma if item is not last
            if (--key_count > 0)
              html += ',';
            html += '
';
          }
        }
        html += '
}';
      }
      else {
        html += '{}';
      }
    }
    return html;
  }

  /**
   * jQuery plugin method
   * @param json: a javascript object
   * @param pathTarget: a javascript object
   * @param options: an optional options hash
   */
  $.fn.jsonPathPicker = function (json, pathTarget, options) {
    options = options || {};
    options.pathQuotesType = options.pathQuotesType !== undefined ? options.pathQuotesType : 'single';
    var $pathTarget = $(pathTarget);

    // jQuery chaining
    return this.each(function () {

      // Transform to HTML
      var html = json2html(json, options)
      if (isCollapsable(json))
        html = '' + html;

      // Insert HTML in target DOM element
      $(this).html(html);

      // Bind click on toggle buttons
      $(this).off('click');
      $(this).on('click', 'a.json-toggle', function () {
        var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array');
        target.toggle();
        if (target.is(':visible')) {
          target.siblings('.json-placeholder').remove();
        }
        else {
          var count = target.children('li').length;
          var placeholder = count + (count > 1 ? ' items' : ' item');
          target.after('' + placeholder + '');
        }
        return false;
      });

      // Simulate click on toggle button when placeholder is clicked
      $(this).on('click', 'a.json-placeholder', function () {
        $(this).siblings('a.json-toggle').click();
        return false;
      });

      $(this).on('click', '.pick-path', function () {
        if ($pathTarget.length === 0) {
          return;
        }

        var $parentsList = $(this).parents('li').get().reverse();
        var pathSegments = $($parentsList).map(function (idx, li) {
          var key = $(li).data('key');
          var keyType = $(li).data('key-type');

          if (keyType === 'object' && options.processKeys && options.keyReplaceRegexPattern !== undefined) {
            var keyReplaceRegex = new RegExp(options.keyReplaceRegexPattern, options.keyReplaceRegexFlags);
            var keyReplacementText = options.keyReplacementText === undefined ? '' : options.keyReplacementText;
            key = key.replace(keyReplaceRegex, keyReplacementText);
          }

          return {
            key: key,
            keyType: keyType
          };
        });

        var quotes = {
          'none': '',
          'single': '\'',
          'double': '"'
        };

        var quote = quotes[options.pathQuotesType];

        pathSegments = pathSegments.map(function (idx, segment) {
          var isBracketsNotation = options.pathNotation === 'brackets';
          var isKeyForbiddenInDotNotation = !/^\w+$/.test(segment.key);

          if (segment.keyType === 'array') {
            return '[' + segment.key + ']';
          } else if (isBracketsNotation || isKeyForbiddenInDotNotation) {
            return '[' + quote + segment.key + quote + ']';
          } else if (idx > 0) {
            return '.' + segment.key;
          } else {
            return segment.key;
          }
        });

        var path = pathSegments.get().join('');

        $pathTarget.val(path);
      });

      if (options.outputCollapsed === true) {
        // Trigger click to collapse all nodes
        $(this).find('a.json-toggle').click();
      }
    });
  };
})(jQuery);
<commit_msg>Fix numeric object keys bug<commit_after>(function ($) {

  /**
   * Check if arg is either an array with at least 1 element, or a dict with at least 1 key
   * @return boolean
   */
  function isCollapsable(arg) {
    return arg instanceof Object && Object.keys(arg).length > 0;
  }

  /**
   * Check if a string represents a valid url
   * @return boolean
   */
  function isUrl(string) {
    var regexp = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
    return regexp.test(string);
  }

  /**
   * Transform a json object into html representation
   * @return string
   */
  function json2html(json, options) {
    var html = '';
    if (typeof json === 'string') {
      // Escape tags
      json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
      if (isUrl(json))
        html += '' + json + '';
      else
        html += '"' + json + '"';
    }
    else if (typeof json === 'number') {
      html += '' + json + '';
    }
    else if (typeof json === 'boolean') {
      html += '' + json + '';
    }
    else if (json === null) {
      html += 'null';
    }
    else if (json instanceof Array) {
      if (json.length > 0) {
        html += '[
';
        for (var i = 0; i < json.length; ++i) {
          html += '
'
          // Add toggle button if item is collapsable
          if (isCollapsable(json[i])) {
            html += '';
          }
          html += json2html(json[i], options);
          // Add comma if item is not last
          if (i < json.length - 1) {
            html += ',';
          }
          html += '
';
        }
        html += '
]';
      }
      else {
        html += '[]';
      }
    }
    else if (typeof json === 'object') {
      var key_count = Object.keys(json).length;
      if (key_count > 0) {
        html += '{
';
        for (var key in json) {
          if (json.hasOwnProperty(key)) {
            html += '
';
            var keyRepr = options.outputWithQuotes ?
              '"' + key + '"' : key;

            // Add toggle button if item is collapsable
            if (isCollapsable(json[key])) {
              html += '' + keyRepr + '';
            }
            else {
              html += keyRepr;
            }
            html += '📋';
            html += ': ' + json2html(json[key], options);
            // Add comma if item is not last
            if (--key_count > 0)
              html += ',';
            html += '
';
          }
        }
        html += '
}';
      }
      else {
        html += '{}';
      }
    }
    return html;
  }

  /**
   * jQuery plugin method
   * @param json: a javascript object
   * @param pathTarget: a javascript object
   * @param options: an optional options hash
   */
  $.fn.jsonPathPicker = function (json, pathTarget, options) {
    options = options || {};
    options.pathQuotesType = options.pathQuotesType !== undefined ? options.pathQuotesType : 'single';
    var $pathTarget = $(pathTarget);

    // jQuery chaining
    return this.each(function () {

      // Transform to HTML
      var html = json2html(json, options)
      if (isCollapsable(json))
        html = '' + html;

      // Insert HTML in target DOM element
      $(this).html(html);

      // Bind click on toggle buttons
      $(this).off('click');
      $(this).on('click', 'a.json-toggle', function () {
        var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array');
        target.toggle();
        if (target.is(':visible')) {
          target.siblings('.json-placeholder').remove();
        }
        else {
          var count = target.children('li').length;
          var placeholder = count + (count > 1 ? ' items' : ' item');
          target.after('' + placeholder + '');
        }
        return false;
      });

      // Simulate click on toggle button when placeholder is clicked
      $(this).on('click', 'a.json-placeholder', function () {
        $(this).siblings('a.json-toggle').click();
        return false;
      });

      $(this).on('click', '.pick-path', function () {
        if ($pathTarget.length === 0) {
          return;
        }

        var $parentsList = $(this).parents('li').get().reverse();
        var pathSegments = $($parentsList).map(function (idx, li) {
          var key = $(li).data('key');
          var keyType = $(li).data('key-type');

          if (
            keyType === 'object'
            && typeof key !== 'number'
            && options.processKeys
            && options.keyReplaceRegexPattern !== undefined
          ) {
            var keyReplaceRegex = new RegExp(options.keyReplaceRegexPattern, options.keyReplaceRegexFlags);
            var keyReplacementText = options.keyReplacementText === undefined ? '' : options.keyReplacementText;
            key = key.replace(keyReplaceRegex, keyReplacementText);
          }

          return {
            key: key,
            keyType: keyType
          };
        });

        var quotes = {
          'none': '',
          'single': '\'',
          'double': '"'
        };

        var quote = quotes[options.pathQuotesType];

        pathSegments = pathSegments.map(function (idx, segment) {
          var isBracketsNotation = options.pathNotation === 'brackets';
          var isKeyForbiddenInDotNotation = !/^\w+$/.test(segment.key) || typeof segment.key === 'number';

          if (segment.keyType === 'array' || segment.isKeyANumber) {
            return '[' + segment.key + ']';
          } else if (isBracketsNotation || isKeyForbiddenInDotNotation) {
            return '[' + quote + segment.key + quote + ']';
          } else if (idx > 0) {
            return '.' + segment.key;
          } else {
            return segment.key;
          }
        });

        var path = pathSegments.get().join('');

        $pathTarget.val(path);
      });

      if (options.outputCollapsed === true) {
        // Trigger click to collapse all nodes
        $(this).find('a.json-toggle').click();
      }
    });
  };
})(jQuery);
<|endoftext|>


<commit_before>export { getRandomIntInclusive, fill_numberArray, generate_numberArray };

import * as FloatValue from "../Unpacker/FloatValue.js";
import * as Recyclable from "./Recyclable.js";

/**
 * Return a random integer between min and max. (This function comes from MDN's Math.random().)
 *
 * @param {number} min The the minimum integer. (inclusive)
 * @param {number} max The the maximum integer. (inclusive)
 */
function getRandomIntInclusive( min, max ) {
  let minReal = Math.min( min, max );
  let maxReal = Math.max( min, max );
  let minInt = Math.ceil( minReal );
  let maxInt  = Math.floor( maxReal );
  let kindsInt = maxInt - minInt + 1;
  return Math.floor( ( Math.random() * kindsInt ) + minInt );
}

/**
 * This method will try to let neighbor channel's value bounds has obviously more
 * different.
 *
 *
 * @param {number[]|Recyclable.NumberArray_withBounds} io_numberArray
 *   The number array to be filled. If it is an instance of Recyclable.NumberArray_withBounds,
 * its .boundsArray_byChannel will be filled.
 *
 * @param {number} height        The length of axis0 of the io_numberArray.
 * @param {number} width         The length of axis1 of the io_numberArray.
 * @param {number} channelCount  The length of axis2 of the io_numberArray.
 *
 * @param {number} valueBegin
 *   The first value of filled sequence.
 *
 * @param {number} valueStep
 *   The incremental value of every next filled value in the sequence.
 *
 * @param {number} randomOffsetMin
 *   Every element of the generated number array will been shifted from the sequence id between
 * [ randomOffsetMin, randomOffsetMax ] (inclusive) randomly.
 *
 * @param {number} randomOffsetMax
 *   Every element of the generated number array will been shifted from the sequence id between
 * [ randomOffsetMin, randomOffsetMax ] (inclusive) randomly.
 *
 * @param {number} divisorForRemainder
 *   The generated value will be divided by divisorForRemainder. The remainder will be the real
 * output value. This is used for restricted the value bounds.
 *
 * @return {number[]|Recyclable.NumberArray_withBounds}
 *   Return the io_numberArray.
 */
function fill_numberArray( io_numberArray,
  height, width, channelCount,
  valueBegin = 0, valueStep = 1,
  randomOffsetMin = 0, randomOffsetMax = 0, divisorForRemainder = ( 2 ** 26 ) ) {

  // (Codes copied from getRandomIntInclusive())
  const randomOffsetMinReal = Math.min( randomOffsetMin, randomOffsetMax );
  const randomOffsetMaxReal = Math.max( randomOffsetMin, randomOffsetMax );
  const randomOffsetMinInt = Math.ceil( randomOffsetMinReal );
  const randomOffsetMaxInt  = Math.floor( randomOffsetMaxReal );
  const randomOffsetKindsInt = randomOffsetMaxInt - randomOffsetMinInt + 1;

  io_numberArray.length = height * width * channelCount;

  let valueStepPerChannel = valueStep * channelCount;
  let valueNoRandBegin = valueBegin;
  let valueNoRand;
  let randomOffset;
  let value;

  let arrayIndex = 0;

  if ( io_numberArray instanceof Recyclable.NumberArray_withBounds ) {
    io_numberArray.boundsArray_byChannel.length = channelCount;
    io_numberArray.boundsArray_byChannel.set_all_by_PositiveInfinity_NegativeInfinity();

    for ( let h = 0; h < height; ++h ) {
      for ( let w = 0; w < width; ++w ) {

        valueNoRand = valueNoRandBegin;
        for ( let c = 0; c < channelCount; ++c, ++arrayIndex ) {

//!!! (2022/08/04 Temp Remarked) for re-producible random.
          // randomOffset = Math.floor( ( Math.random() * randomOffsetKindsInt ) + randomOffsetMinInt );
          if ( ( i % 2 ) == 0 )
            randomOffset = randomOffsetMinInt;
          else
            randomOffset = randomOffsetMaxInt;

          value = ( valueNoRand + randomOffset ) % divisorForRemainder;
          io_numberArray[ arrayIndex ] = value;
          io_numberArray.boundsArray_byChannel.enlarge_one_byN( c, value );

          valueNoRand += valueStepPerChannel;
        }
        valueNoRandBegin += valueStep;
      }
    }

  } else {

    for ( let h = 0; h < height; ++h ) {
      for ( let w = 0; w < width; ++w ) {

        valueNoRand = valueNoRandBegin;
        for ( let c = 0; c < channelCount; ++c, ++arrayIndex ) {

//!!! (2022/08/04 Temp Remarked) for re-producible random.
          // randomOffset = Math.floor( ( Math.random() * randomOffsetKindsInt ) + randomOffsetMinInt );
          if ( ( i % 2 ) == 0 )
            randomOffset = randomOffsetMinInt;
          else
            randomOffset = randomOffsetMaxInt;

          value = ( valueNoRand + randomOffset ) % divisorForRemainder;
          io_numberArray[ arrayIndex ] = value;
          valueNoRand += valueStepPerChannel;
        }
        valueNoRandBegin += valueStep;
      }
    }
  }

  return io_numberArray;
}

/**
 *
 * @param {number} height        The length of axis0 of the io_numberArray.
 * @param {number} width         The length of axis1 of the io_numberArray.
 * @param {number} channelCount  The length of axis2 of the io_numberArray.
 *
 * @return {number[]}
 *   Return a number array.
 *
 * @see fill_integerArray()
 */
function generate_numberArray(
  height, width, channelCount,
  valueBegin = 0, valueStep = 1,
  randomOffsetMin = 0, randomOffsetMax = 0, divisorForRemainder = ( 2 ** 26 ),
  oBounds = null ) {

  let numberArray = new Array();
  return fill_numberArray( numberArray,
    height, width, channelCount,
    valueBegin, valueStep,
    randomOffsetMin, randomOffsetMax,  divisorForRemainder );
}
<commit_msg>arrayIndex<commit_after>export { getRandomIntInclusive, fill_numberArray, generate_numberArray };

import * as FloatValue from "../Unpacker/FloatValue.js";
import * as Recyclable from "./Recyclable.js";

/**
 * Return a random integer between min and max. (This function comes from MDN's Math.random().)
 *
 * @param {number} min The the minimum integer. (inclusive)
 * @param {number} max The the maximum integer. (inclusive)
 */
function getRandomIntInclusive( min, max ) {
  let minReal = Math.min( min, max );
  let maxReal = Math.max( min, max );
  let minInt = Math.ceil( minReal );
  let maxInt  = Math.floor( maxReal );
  let kindsInt = maxInt - minInt + 1;
  return Math.floor( ( Math.random() * kindsInt ) + minInt );
}

/**
 * This method will try to let neighbor channel's value bounds has obviously more
 * different.
 *
 *
 * @param {number[]|Recyclable.NumberArray_withBounds} io_numberArray
 *   The number array to be filled. If it is an instance of Recyclable.NumberArray_withBounds,
 * its .boundsArray_byChannel will be filled.
 *
 * @param {number} height        The length of axis0 of the io_numberArray.
 * @param {number} width         The length of axis1 of the io_numberArray.
 * @param {number} channelCount  The length of axis2 of the io_numberArray.
 *
 * @param {number} valueBegin
 *   The first value of filled sequence.
 *
 * @param {number} valueStep
 *   The incremental value of every next filled value in the sequence.
 *
 * @param {number} randomOffsetMin
 *   Every element of the generated number array will been shifted from the sequence id between
 * [ randomOffsetMin, randomOffsetMax ] (inclusive) randomly.
 *
 * @param {number} randomOffsetMax
 *   Every element of the generated number array will been shifted from the sequence id between
 * [ randomOffsetMin, randomOffsetMax ] (inclusive) randomly.
 *
 * @param {number} divisorForRemainder
 *   The generated value will be divided by divisorForRemainder. The remainder will be the real
 * output value. This is used for restricted the value bounds.
 *
 * @return {number[]|Recyclable.NumberArray_withBounds}
 *   Return the io_numberArray.
 */
function fill_numberArray( io_numberArray,
  height, width, channelCount,
  valueBegin = 0, valueStep = 1,
  randomOffsetMin = 0, randomOffsetMax = 0, divisorForRemainder = ( 2 ** 26 ) ) {

  // (Codes copied from getRandomIntInclusive())
  const randomOffsetMinReal = Math.min( randomOffsetMin, randomOffsetMax );
  const randomOffsetMaxReal = Math.max( randomOffsetMin, randomOffsetMax );
  const randomOffsetMinInt = Math.ceil( randomOffsetMinReal );
  const randomOffsetMaxInt  = Math.floor( randomOffsetMaxReal );
  const randomOffsetKindsInt = randomOffsetMaxInt - randomOffsetMinInt + 1;

  io_numberArray.length = height * width * channelCount;

  let valueStepPerChannel = valueStep * channelCount;
  let valueNoRandBegin = valueBegin;
  let valueNoRand;
  let randomOffset;
  let value;

  let arrayIndex = 0;

  if ( io_numberArray instanceof Recyclable.NumberArray_withBounds ) {
    io_numberArray.boundsArray_byChannel.length = channelCount;
    io_numberArray.boundsArray_byChannel.set_all_by_PositiveInfinity_NegativeInfinity();

    for ( let h = 0; h < height; ++h ) {
      for ( let w = 0; w < width; ++w ) {

        valueNoRand = valueNoRandBegin;
        for ( let c = 0; c < channelCount; ++c, ++arrayIndex ) {

//!!! (2022/08/04 Temp Remarked) for re-producible random.
          // randomOffset = Math.floor( ( Math.random() * randomOffsetKindsInt ) + randomOffsetMinInt );
          if ( ( arrayIndex % 2 ) == 0 )
            randomOffset = randomOffsetMinInt;
          else
            randomOffset = randomOffsetMaxInt;

          value = ( valueNoRand + randomOffset ) % divisorForRemainder;
          io_numberArray[ arrayIndex ] = value;
          io_numberArray.boundsArray_byChannel.enlarge_one_byN( c, value );

          valueNoRand += valueStepPerChannel;
        }
        valueNoRandBegin += valueStep;
      }
    }

  } else {

    for ( let h = 0; h < height; ++h ) {
      for ( let w = 0; w < width; ++w ) {

        valueNoRand = valueNoRandBegin;
        for ( let c = 0; c < channelCount; ++c, ++arrayIndex ) {

//!!! (2022/08/04 Temp Remarked) for re-producible random.
          // randomOffset = Math.floor( ( Math.random() * randomOffsetKindsInt ) + randomOffsetMinInt );
          if ( ( arrayIndex % 2 ) == 0 )
            randomOffset = randomOffsetMinInt;
          else
            randomOffset = randomOffsetMaxInt;

          value = ( valueNoRand + randomOffset ) % divisorForRemainder;
          io_numberArray[ arrayIndex ] = value;
          valueNoRand += valueStepPerChannel;
        }
        valueNoRandBegin += valueStep;
      }
    }
  }

  return io_numberArray;
}

/**
 *
 * @param {number} height        The length of axis0 of the io_numberArray.
 * @param {number} width         The length of axis1 of the io_numberArray.
 * @param {number} channelCount  The length of axis2 of the io_numberArray.
 *
 * @return {number[]}
 *   Return a number array.
 *
 * @see fill_integerArray()
 */
function generate_numberArray(
  height, width, channelCount,
  valueBegin = 0, valueStep = 1,
  randomOffsetMin = 0, randomOffsetMax = 0, divisorForRemainder = ( 2 ** 26 ),
  oBounds = null ) {

  let numberArray = new Array();
  return fill_numberArray( numberArray,
    height, width, channelCount,
    valueBegin, valueStep,
    randomOffsetMin, randomOffsetMax,  divisorForRemainder );
}
<|endoftext|>


<commit_before>(function() {
  'use strict';
  angular.module('civic.events.variants')
    .controller('VariantSummaryController', VariantSummaryController)
    .directive('variantSummary', function() {
      return {
        restrict: 'E',
        scope: {
          showEvidenceGrid: '='
        },
        controller: 'VariantSummaryController',
        templateUrl: 'app/views/events/variants/summary/variantSummary.tpl.html'
      };
    });

  //@ngInject
  function VariantSummaryController($scope,
                                    $state,
                                    $stateParams,
                                    _,
                                    Security,
                                    Variants,
                                    VariantsViewOptions) {
    $scope.isAuthenticated = Security.isAuthenticated;
    $scope.isEdit = $state.includes('**.edit.**');
    $scope.stateParams = $stateParams;

    $scope.variant = parseVariant(Variants.data.item);
    $scope.evidence = Variants.data.evidence;

    $scope.clinvar_ignore = ['N/A', 'NONE FOUND'];

    // watches any changes to the variant itself, but will also update evidence to pass to grid
    $scope.$watch(function() { return Variants.data.item; }, function(variant) {
      $scope.variant = variant;
      $scope.evidence = variant.evidence_items;
    }, true);

    $scope.$watch(function() { return Variants.data.myVariantInfo;}, function(myVariantInfo) {
      if(!_.isUndefined(myVariantInfo.cosmic)) {
        myVariantInfo.cosmic.cosmic_id_short = _.trim(myVariantInfo.cosmic.cosmic_id, 'COSM');
        myVariantInfo.entrez_id = $scope.variant.name;
      }
      $scope.myVariantInfo = myVariantInfo;
    }, true);

    $scope.VariantsViewOptions = VariantsViewOptions;
    $scope.backgroundColor = VariantsViewOptions.styles.view.backgroundColor;

    $scope.editClick = function() {
      if (Security.isAuthenticated()) {
        $state.go('events.genes.summary.variants.edit.basic', $stateParams);
      }
    };

    function parseVariant(variant) {
      if(!_.isUndefined(variant.assertions) && variant.assertions.length > 0) {
        _.each(variant.assertions, function (assertion) {
          assertion.name = 'ASR' + assertion.id;
          return assertion;
        });
      }
      return variant;
    }
  }
})();
<commit_msg>variant summary controller sets allele_registry_id to null if '_:CA' returned<commit_after>(function() {
  'use strict';
  angular.module('civic.events.variants')
    .controller('VariantSummaryController', VariantSummaryController)
    .directive('variantSummary', function() {
      return {
        restrict: 'E',
        scope: {
          showEvidenceGrid: '='
        },
        controller: 'VariantSummaryController',
        templateUrl: 'app/views/events/variants/summary/variantSummary.tpl.html'
      };
    });

  //@ngInject
  function VariantSummaryController($scope,
                                    $state,
                                    $stateParams,
                                    _,
                                    Security,
                                    Variants,
                                    VariantsViewOptions) {
    $scope.isAuthenticated = Security.isAuthenticated;
    $scope.isEdit = $state.includes('**.edit.**');
    $scope.stateParams = $stateParams;

    $scope.variant = parseVariant(Variants.data.item);
    $scope.evidence = Variants.data.evidence;

    $scope.clinvar_ignore = ['N/A', 'NONE FOUND'];

    // watches any changes to the variant itself, but will also update evidence to pass to grid
    $scope.$watch(function() { return Variants.data.item; }, function(variant) {
      $scope.variant = variant;
      $scope.evidence = variant.evidence_items;
    }, true);

    $scope.$watch(function() { return Variants.data.myVariantInfo;}, function(myVariantInfo) {
      if(!_.isUndefined(myVariantInfo.cosmic)) {
        myVariantInfo.cosmic.cosmic_id_short = _.trim(myVariantInfo.cosmic.cosmic_id, 'COSM');
        myVariantInfo.entrez_id = $scope.variant.name;
      }
      $scope.myVariantInfo = myVariantInfo;
    }, true);

    $scope.VariantsViewOptions = VariantsViewOptions;
    $scope.backgroundColor = VariantsViewOptions.styles.view.backgroundColor;

    $scope.editClick = function() {
      if (Security.isAuthenticated()) {
        $state.go('events.genes.summary.variants.edit.basic', $stateParams);
      }
    };

    function parseVariant(variant) {
      if(!_.isUndefined(variant.assertions) && variant.assertions.length > 0) {
        _.each(variant.assertions, function (assertion) {
          assertion.name = 'ASR' + assertion.id;
          return assertion;
        });
      }

      // treat '_:CA' values from registry as null, for now
      if(variant.allele_registry_id === '_:CA') { variant.allele_registry_id = null; }

      return variant;
    }
  }
})();
<|endoftext|>


<commit_before>// Load all tabs
const tabs = getElementsByClassName('hero-tab')
const literalNumbers = ['one', 'two', 'three', 'four', 'five', 'six']

// Preload images and randomly rotate
const fadeInTab = tabIndex => {
	// Fade in Hero Image
	tabs[tabIndex].classList.add('fade-in')
	// Slide in Hero Text
	setTimeout(() => {
		for (let i = 0; i < 3; i++) {
			const title = getElementByClassName('hero-title ' + literalNumbers[i], tabIndex)
			title.classList.add('fade-slide')
		}
	}, 500)
	// Slide in Hero Button
	setTimeout(() => {
		const heroButton = getElementByClassName('hero-button', tabIndex)
		heroButton.classList.add('fade-slide')
	}, 800)
	// Slide in Hero Arrows
	setTimeout(() => {
		const heroArrows = getElementByClassName('hero-arrows', tabIndex)
		heroArrows.classList.add('fade-slide')
	}, 1100)
}

const resetSlide = tabIndex => {
	// Hide Hero Text
	for (let i = 0; i < 3; i++) {
		const title = getElementByClassName('hero-title ' + literalNumbers[i], tabIndex)
		title.classList.remove('fade-slide')
	}
	// Hide Hero Button
	const heroButton = getElementByClassName('hero-button', tabIndex)
	heroButton.classList.remove('fade-slide')
	// Hide Hero Arrows
	const heroArrows = getElementByClassName('hero-arrows', tabIndex)
	heroArrows.classList.remove('fade-slide')
}

// Begin
if (window.location.pathname === '/') {

	// Add event listener to cycle through all hero messages on arrow click
	const rightArrows = getElementsByClassName('hero-arrow right')
	for (let tabIndex = 0; tabIndex < rightArrows.length; tabIndex++) {
		rightArrows[tabIndex].addEventListener('click', () => {
			// Get next image
			const nextTabIndex = tabIndex === tabs.length - 1
				? 0
				: tabIndex + 1
			// Deactivate current tab
			tabs[tabIndex].classList.add('fade-out')
			// Fade in new slide
			fadeInTab(nextTabIndex)
			// Reset current slide
			resetSlide(tabIndex)
		})
	}

	// Fade in first slide
	fadeInTab(0)

}<commit_msg>Hero.<commit_after>// Load all tabs
const tabs = getElementsByClassName('hero-tab')
const literalNumbers = ['one', 'two', 'three', 'four', 'five', 'six']

// Preload images and randomly rotate
const fadeInTab = tabIndex => {
	// Fade in Hero Image
	tabs[tabIndex].classList.add('fade-in')
	// Slide in Hero Text
	setTimeout(() => {
		for (let i = 0; i < 3; i++) {
			const title = getElementByClassName('hero-title ' + literalNumbers[i], tabIndex)
			title.classList.add('fade-slide')
		}
	}, 500)
	// Slide in Hero Button
	setTimeout(() => {
		const heroButton = getElementByClassName('hero-button', tabIndex)
		heroButton.classList.add('fade-slide')
	}, 800)
	// Slide in Hero Arrows
	setTimeout(() => {
		const heroArrows = getElementByClassName('hero-arrows', tabIndex)
		heroArrows.classList.add('fade-slide')
	}, 1100)
}

const resetSlide = tabIndex => {
	// Hide Hero Text
	for (let i = 0; i < 3; i++) {
		const title = getElementByClassName('hero-title ' + literalNumbers[i], tabIndex)
		title.classList.remove('fade-slide')
	}
	// Hide Hero Button
	const heroButton = getElementByClassName('hero-button', tabIndex)
	heroButton.classList.remove('fade-slide')
	// Hide Hero Arrows
	const heroArrows = getElementByClassName('hero-arrows', tabIndex)
	heroArrows.classList.remove('fade-slide')
}

// Begin
if (window.location.pathname === '/') {

	// Add event listener to cycle through all hero messages on arrow click
	const rightArrows = getElementsByClassName('hero-arrow right')
	for (let tabIndex = 0; tabIndex < rightArrows.length; tabIndex++) {
		rightArrows[tabIndex].addEventListener('click', () => {
			// Get next image
			const nextTabIndex = tabIndex === tabs.length - 1
				? 0
				: tabIndex + 1
			console.log(tabIndex, nextTabIndex)
			// Deactivate current tab
			tabs[tabIndex].classList.add('fade-out')
			// Fade in new slide
			fadeInTab(nextTabIndex)
			// Reset current slide
			resetSlide(tabIndex)
		})
	}

	// Fade in first slide
	fadeInTab(0)

}<|endoftext|>


<commit_before>/**
 * Created by karolisrusenas on 06/04/2016.
 */

import React, {PropTypes} from 'react'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import * as actionCreators from '../../redux/modules/auth'
import {Col} from 'react-bootstrap'

import Card from 'material-ui/lib/card/card'
import CardTitle from 'material-ui/lib/card/card-title'
import RaisedButton from 'material-ui/lib/raised-button'
import CardText from 'material-ui/lib/card/card-text'
import TextField from 'material-ui/lib/text-field'

export class LoginView extends React.Component {
  static propTypes = {
    location: PropTypes.object.isRequired,
    actions: PropTypes.object.isRequired,
    statusText: PropTypes.string,
    isAuthenticating: PropTypes.bool.isRequired
  };

  constructor (props) {
    super(props)
    const redirectRoute = this.props.location.query.redirect || '/login'
    this.state = {
      email: '',
      password: '',
      redirectTo: redirectRoute
    }
    this.login = this.login.bind(this)
  }

  login (e) {
    e.preventDefault()
    this.props.actions.loginUser(this.refs.username.getValue(), this.refs.password.getValue(), this.state.redirectTo)
  }

  render () {
    return (

        <Col md={3}/>
        <Col md={6}>
          <Card>
            <CardTitle title='Login required!' subtitle='Hint: hf/hf'/>
            <CardText>
              {this.props.statusText ?
{this.props.statusText}
 : ''}
              <form role='form'>

                  <TextField
                    hintText='Username'
                    ref='username'
                    type='text'
                  />
                  <TextField
                    hintText='Password'
                    type='password'
                    ref='password'
                  />

                <RaisedButton
                  type='submit'
                  label='Submit'
                  onClick={this.login}
                  disabled={this.props.isAuthenticating}
                  primary/>
              </form>
            </CardText>
          </Card>
        </Col>

    )
  }
}

const mapStateToProps = (state) => ({
  isAuthenticating: state.auth.isAuthenticating,
  statusText: state.auth.statusText
})

const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(actionCreators, dispatch)
})

export default connect(mapStateToProps, mapDispatchToProps)(LoginView)
<commit_msg>fix for firefox<commit_after>/**
 * Created by karolisrusenas on 06/04/2016.
 */

import React, {PropTypes} from 'react'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import * as actionCreators from '../../redux/modules/auth'
import {Col} from 'react-bootstrap'

import Card from 'material-ui/lib/card/card'
import CardTitle from 'material-ui/lib/card/card-title'
import RaisedButton from 'material-ui/lib/raised-button'
import CardText from 'material-ui/lib/card/card-text'
import TextField from 'material-ui/lib/text-field'

export class LoginView extends React.Component {
  static propTypes = {
    location: PropTypes.object.isRequired,
    actions: PropTypes.object.isRequired,
    statusText: PropTypes.string,
    isAuthenticating: PropTypes.bool.isRequired
  };

  constructor (props) {
    super(props)
    const redirectRoute = this.props.location.query.redirect || '/login'
    this.state = {
      email: '',
      password: '',
      redirectTo: redirectRoute
    }
    this.login = this.login.bind(this)
  }

  login (e) {
    e.preventDefault()
    this.props.actions.loginUser(this.refs.username.getValue(), this.refs.password.getValue(), this.state.redirectTo)
  }

  render () {
    return (

        <Col md={3}/>
        <Col md={6}>
          <Card>
            <CardTitle title='Login required!' subtitle='Hint: hf/hf'/>
            <CardText>
              {this.props.statusText ?
{this.props.statusText}
 : ''}
              <form role='form'>

                  <TextField
                    hintText='Username'
                    ref='username'
                    type='text'
                  />

                  <TextField
                    hintText='Password'
                    type='password'
                    ref='password'
                  />

                <RaisedButton
                  type='submit'
                  label='Submit'
                  onClick={this.login}
                  disabled={this.props.isAuthenticating}
                  primary/>
              </form>
            </CardText>
          </Card>
        </Col>

    )
  }
}

const mapStateToProps = (state) => ({
  isAuthenticating: state.auth.isAuthenticating,
  statusText: state.auth.statusText
})

const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(actionCreators, dispatch)
})

export default connect(mapStateToProps, mapDispatchToProps)(LoginView)
<|endoftext|>


<commit_before>var L = A.Lang,
	isArray = L.isArray,

	nodeSetter = function(v) {
		return A.get(v);
	},

	createSelect = function() {
		return A.Node.create(SELECT_TPL);
	},

	APPEND_ORDER = 'appendOrder',
	BASE_NAME = 'baseName',
	BLANK = '',
	BODY = 'body',
	BUTTON = 'button',
	CALENDAR = 'calendar',
	CLEARFIX = 'clearfix',
	CURRENT_DAY = 'currentDay',
	CURRENT_MONTH = 'currentMonth',
	CURRENT_YEAR = 'currentYear',
	DATEPICKER = 'datepicker',
	DATE_FORMAT = 'dateFormat',
	DAY = 'day',
	DAY_FIELD = 'dayField',
	DAY_FIELD_NAME = 'dayFieldName',
	DISPLAY = 'display',
	DISPLAY_BOUNDING_BOX = 'displayBoundingBox',
	DOT = '.',
	HELPER = 'helper',
	MAX_DATE = 'maxDate',
	MIN_DATE = 'minDate',
	MONTH = 'month',
	MONTH_FIELD = 'monthField',
	MONTH_FIELD_NAME = 'monthFieldName',
	NAME = 'name',
	OPTION = 'option',
	POPULATE_DAY = 'populateDay',
	POPULATE_MONTH = 'populateMonth',
	POPULATE_YEAR = 'populateYear',
	SELECT = 'select',
	SELECTED = 'selected',
	TRIGGER = 'trigger',
	WRAPPER = 'wrapper',
	YEAR = 'year',
	YEAR_FIELD = 'yearField',
	YEAR_FIELD_NAME = 'yearFieldName',
	YEAR_RANGE = 'yearRange',

	getCN = A.ClassNameManager.getClassName,

	CSS_DATEPICKER = getCN(DATEPICKER),
	CSS_DATEPICKER_BUTTON_WRAPPER = getCN(DATEPICKER, BUTTON, WRAPPER),
	CSS_DATEPICKER_DAY = getCN(DATEPICKER, DAY),
	CSS_DATEPICKER_DISPLAY = getCN(DATEPICKER, DISPLAY),
	CSS_DATEPICKER_MONTH = getCN(DATEPICKER, MONTH),
	CSS_DATEPICKER_SELECT_WRAPPER = getCN(DATEPICKER, SELECT, WRAPPER),
	CSS_DATEPICKER_YEAR = getCN(DATEPICKER, YEAR),
	CSS_HELPER_CLEARFIX = getCN(HELPER, CLEARFIX),

	SELECT_TPL = '<select></select>',
	SELECT_OPTION_TPL = '<option></option>',
	DISPLAY_BOUNDING_BOX_TPL = '

',
	WRAPPER_BUTTON_TPL = '

',
	WRAPPER_SELECT_TPL = '

';

function DatePickerSelect(config) {
	DatePickerSelect.superclass.constructor.apply(this, arguments);
}

A.mix(DatePickerSelect, {
	NAME: DATEPICKER,

	ATTRS: {
		appendOrder: {
			value: [ 'm', 'd', 'y' ],
			validator: isArray
		},

		baseName: {
			value: DATEPICKER
		},

		// displayBoundingBox is the boundingBox to the selects/button
		// the default boundingBox attribute refer to the Calendar Overlay
		displayBoundingBox: {
			value: null,
			setter: nodeSetter
		},

		dayField: {
			setter: nodeSetter,
			valueFn: createSelect
		},

		monthField: {
			setter: nodeSetter,
			valueFn: createSelect
		},

		yearField: {
			setter: nodeSetter,
			valueFn: createSelect
		},

		dayFieldName: {
			value: DAY
		},

		monthFieldName: {
			value: MONTH
		},

		yearFieldName: {
			value: YEAR
		},

		trigger: {
			valueFn: function() {
				return A.Node.create(WRAPPER_BUTTON_TPL).cloneNode();
			}
		},

		visible: {
			value: false
		},

		yearRange: {
			valueFn: function() {
				var year = new Date().getFullYear();

				return [ year - 10, year + 10 ]
			},
			validator: isArray
		},

		setValue: {
			value: false
		},

		populateDay: {
			value: true
		},

		populateMonth: {
			value: true
		},

		populateYear: {
			value: true
		}
	}
});

A.extend(DatePickerSelect, A.Calendar, {
	/*
	* Lifecycle
	*/
	renderUI: function() {
		var instance = this;

		DatePickerSelect.superclass.renderUI.apply(this, arguments);

		instance._renderElements();
		instance._renderTriggerButton();
	},

	bindUI: function() {
		var instance = this;

		DatePickerSelect.superclass.bindUI.apply(this, arguments);

		instance.after('datesChange', A.bind(instance._selectCurrentValues, instance));
		instance.after('currentMonthChange', A.bind(instance._afterSetCurrentMonth, instance));

		instance._bindSelectEvents();
	},

	syncUI: function() {
		var instance = this;

		DatePickerSelect.superclass.syncUI.apply(this, arguments);

		instance._pupulateSelects();
		instance._selectCurrentValues();
	},

	/*
	* Methods
	*/
	_getAppendOrder: function() {
		var instance = this;
		var appendOrder = instance.get(APPEND_ORDER);

		var mapping = {
			d: instance.get(DAY_FIELD),
			m: instance.get(MONTH_FIELD),
			y: instance.get(YEAR_FIELD)
		};

		var firstField = mapping[ appendOrder[0] ];
		var secondField = mapping[ appendOrder[1] ];
		var thirdField = mapping[ appendOrder[2] ];

		return [ firstField, secondField, thirdField ]
	},

	_renderElements: function() {
		var instance = this;
		var displayBoundingBox = instance.get(DISPLAY_BOUNDING_BOX);

		if (!displayBoundingBox) {
			displayBoundingBox = A.Node.create(DISPLAY_BOUNDING_BOX_TPL);

			instance.set(DISPLAY_BOUNDING_BOX, displayBoundingBox);

			A.get(BODY).append(displayBoundingBox);
		}

		var dayField = instance.get(DAY_FIELD);
		var monthField = instance.get(MONTH_FIELD);
		var yearField = instance.get(YEAR_FIELD);

		dayField.addClass(CSS_DATEPICKER_DAY);
		monthField.addClass(CSS_DATEPICKER_MONTH);
		yearField.addClass(CSS_DATEPICKER_YEAR);

		displayBoundingBox.addClass(CSS_DATEPICKER);
		displayBoundingBox.addClass(CSS_DATEPICKER_DISPLAY);
		displayBoundingBox.addClass(CSS_HELPER_CLEARFIX);

		instance._selectWrapper = A.Node.create(WRAPPER_SELECT_TPL);

		// setting name of the fields
		monthField.set(NAME, instance.get(MONTH_FIELD_NAME));
		yearField.set(NAME, instance.get(YEAR_FIELD_NAME));
		dayField.set(NAME, instance.get(DAY_FIELD_NAME));

		// append elements
		var orderedFields = instance._getAppendOrder();

		instance._selectWrapper.append(orderedFields[0]);
		instance._selectWrapper.append(orderedFields[1]);
		instance._selectWrapper.append(orderedFields[2]);

		displayBoundingBox.append( instance._selectWrapper );
	},

	_renderTriggerButton: function() {
		var instance = this;
		var trigger = instance.get(TRIGGER).item(0);
		var displayBoundingBox = instance.get(DISPLAY_BOUNDING_BOX);

		instance._buttonItem = new A.ToolItem(CALENDAR);

		displayBoundingBox.append(trigger);

		if ( trigger.test(DOT+CSS_DATEPICKER_BUTTON_WRAPPER) ) {
			// use ToolItem if the user doesn't specify a trigger
			instance._buttonItem.render(trigger);
		}
	},

	_bindSelectEvents: function() {
		var instance = this;
		var selects = instance._selectWrapper.all(SELECT);

		selects.on('change', A.bind(instance._onSelectChange, instance));
		selects.on('keypress', A.bind(instance._onSelectChange, instance));
	},

	_selectCurrentValues: function() {
		var instance = this;

		instance._selectCurrentDay();
		instance._selectCurrentMonth();
		instance._selectCurrentYear();
	},

	_selectCurrentDay: function() {
		var instance = this;
		var currentDate = instance.getCurrentDate();

		instance.get(DAY_FIELD).val( currentDate.getDate() );
	},

	_selectCurrentMonth: function() {
		var instance = this;
		var currentDate = instance.getCurrentDate();

		instance.get(MONTH_FIELD).val( currentDate.getMonth() );
	},

	_selectCurrentYear: function() {
		var instance = this;
		var currentDate = instance.getCurrentDate();

		instance.get(YEAR_FIELD).val( currentDate.getFullYear() );
	},

	_pupulateSelects: function() {
		var instance = this;

		instance._populateDays();
		instance._populateMonths();
		instance._populateYears();

		// restricting dates based on the selects values
		var monthOptions = instance.get(MONTH_FIELD).all(OPTION);
		var yearOptions = instance.get(YEAR_FIELD).all(OPTION);

		var mLength = monthOptions.size() - 1;
		var yLength = yearOptions.size() - 1;

		var firstMonth = monthOptions.item(0).val();
		var firstYear = yearOptions.item(0).val();
		var lastMonth = monthOptions.item(mLength).val();
		var lastYear = yearOptions.item(yLength).val();

		var maxMonthDays = instance.getDaysInMonth(lastYear, lastMonth);

		var minDate = new Date(firstYear, firstMonth, 1);
		var maxDate = new Date(lastYear, lastMonth, maxMonthDays);

		instance.set(MAX_DATE, maxDate);
		instance.set(MIN_DATE, minDate);
	},

	_populateYears: function() {
		var instance = this;
		var yearRange = instance.get(YEAR_RANGE);
		var yearField = instance.get(YEAR_FIELD);

		if (instance.get(POPULATE_YEAR)) {
			instance._populateSelect(yearField, yearRange[0], yearRange[1]);
		}
	},

	_populateMonths: function() {
		var instance = this;
		var monthField = instance.get(MONTH_FIELD);
		var localeMap = instance._getLocaleMap();
		var monthLabels = localeMap.B;

		if (instance.get(POPULATE_MONTH)) {
			instance._populateSelect(monthField, 0, (monthLabels.length - 1), monthLabels);
		}
	},

	_populateDays: function() {
		var instance = this;
		var dayField = instance.get(DAY_FIELD);
		var daysInMonth = instance.getDaysInMonth();

		if (instance.get(POPULATE_DAY)) {
			instance._populateSelect(dayField, 1, daysInMonth);
		}
	},

	_populateSelect: function(select, fromIndex, toIndex, labels, values) {
		var i = 0;
		var index = fromIndex;
		var instance = this;

		select.empty();
		labels = labels || [];
		values = values || [];

		while (index <= toIndex) {
			var value = values[index] || index;
			var label = labels[index] || index;

			A.Node.getDOMNode(select).options[i] = new Option(label, index);

			i++;
			index++;
		}
	},

	/*
	* Listeners
	*/
	_onSelectChange: function(event) {
		var instance = this;
		var target = event.currentTarget || event.target;
		var monthChanged = target.test(DOT+CSS_DATEPICKER_MONTH);

		var currentDay = instance.get(DAY_FIELD).val();
		var currentMonth = instance.get(MONTH_FIELD).val();
		var currentYear = instance.get(YEAR_FIELD).val();

		instance.set(CURRENT_DAY, currentDay);
		instance.set(CURRENT_MONTH, currentMonth);
		instance.set(CURRENT_YEAR, currentYear);

		if (monthChanged) {
			instance._afterSetCurrentMonth();
		}

		instance._selectDate();
	},

	_afterSetCurrentMonth: function(event) {
		var instance = this;

		instance._populateDays();
		instance._selectCurrentDay();
	}
});

A.DatePickerSelect = DatePickerSelect;<commit_msg>Documentation - DatePickerSelect<commit_after>/**
 * The DatePickerSelect Utility
 *
 * @module aui-date-picker-select
 */

var L = A.Lang,
	isArray = L.isArray,

	nodeSetter = function(v) {
		return A.get(v);
	},

	createSelect = function() {
		return A.Node.create(SELECT_TPL);
	},

	APPEND_ORDER = 'appendOrder',
	BASE_NAME = 'baseName',
	BLANK = '',
	BODY = 'body',
	BUTTON = 'button',
	CALENDAR = 'calendar',
	CLEARFIX = 'clearfix',
	CURRENT_DAY = 'currentDay',
	CURRENT_MONTH = 'currentMonth',
	CURRENT_YEAR = 'currentYear',
	DATEPICKER = 'datepicker',
	DATE_FORMAT = 'dateFormat',
	DAY = 'day',
	DAY_FIELD = 'dayField',
	DAY_FIELD_NAME = 'dayFieldName',
	DISPLAY = 'display',
	DISPLAY_BOUNDING_BOX = 'displayBoundingBox',
	DOT = '.',
	HELPER = 'helper',
	MAX_DATE = 'maxDate',
	MIN_DATE = 'minDate',
	MONTH = 'month',
	MONTH_FIELD = 'monthField',
	MONTH_FIELD_NAME = 'monthFieldName',
	NAME = 'name',
	OPTION = 'option',
	POPULATE_DAY = 'populateDay',
	POPULATE_MONTH = 'populateMonth',
	POPULATE_YEAR = 'populateYear',
	SELECT = 'select',
	SELECTED = 'selected',
	TRIGGER = 'trigger',
	WRAPPER = 'wrapper',
	YEAR = 'year',
	YEAR_FIELD = 'yearField',
	YEAR_FIELD_NAME = 'yearFieldName',
	YEAR_RANGE = 'yearRange',

	getCN = A.ClassNameManager.getClassName,

	CSS_DATEPICKER = getCN(DATEPICKER),
	CSS_DATEPICKER_BUTTON_WRAPPER = getCN(DATEPICKER, BUTTON, WRAPPER),
	CSS_DATEPICKER_DAY = getCN(DATEPICKER, DAY),
	CSS_DATEPICKER_DISPLAY = getCN(DATEPICKER, DISPLAY),
	CSS_DATEPICKER_MONTH = getCN(DATEPICKER, MONTH),
	CSS_DATEPICKER_SELECT_WRAPPER = getCN(DATEPICKER, SELECT, WRAPPER),
	CSS_DATEPICKER_YEAR = getCN(DATEPICKER, YEAR),
	CSS_HELPER_CLEARFIX = getCN(HELPER, CLEARFIX),

	SELECT_TPL = '<select></select>',
	SELECT_OPTION_TPL = '<option></option>',
	DISPLAY_BOUNDING_BOX_TPL = '

',
	WRAPPER_BUTTON_TPL = '

',
	WRAPPER_SELECT_TPL = '

';

/**
 *

 *
 * A base class for DatePickerSelect, providing:
 *

 *
Widget Lifecycle (initializer, renderUI, bindUI, syncUI, destructor)

 *
Select a date from Calendar to select elements

 *

 *
 * Quick Example:

 *
 *
var instance = new A.DatePickerSelect({
	displayBoundingBox: '#displayBoundingBoxId',
	// locale: 'pt-br',
	dateFormat: '%m/%d/%y',
	yearRange: [ 1970, 2009 ]
}).render();
 *

 *
 * Check the list of Configuration Attributes available for
 * DatePickerSelect.
 *
 * @param config {Object} Object literal specifying widget configuration properties.
 *
 * @class DatePickerSelect
 * @constructor
 * @extends Calendar
 */
function DatePickerSelect(config) {
	DatePickerSelect.superclass.constructor.apply(this, arguments);
}

A.mix(DatePickerSelect, {
	/**
	 * Static property provides a string to identify the class.
	 *
	 * @property DatePickerSelect.NAME
	 * @type String
	 * @static
	 */
	NAME: DATEPICKER,

	/**
	 * Static property used to define the default attribute
	 * configuration for the DatePickerSelect.
	 *
	 * @property DatePickerSelect.ATTRS
	 * @type Object
	 * @static
	 */
	ATTRS: {
		/**
		 * The order the selects elements are appended to the displayBoundingBox.
		 *
		 * @attribute appendOrder
		 * @default [ 'm', 'd', 'y' ]
		 * @type Array
		 */
		appendOrder: {
			value: [ 'm', 'd', 'y' ],
			validator: isArray
		},

		/**
		 * A basename to identify the select elements from this
         * DatePickerSelect.
		 *
		 * @attribute baseName
		 * @default datepicker
		 * @type String
		 */
		baseName: {
			value: DATEPICKER
		},

		/**
		 * The container boundingBox to house the
         * selects and button. The boundingBox attribute is
         * used on the Calendar Overlay.
		 *
		 * @attribute displayBoundingBox
		 * @default null
		 * @type Node | String
		 */
		displayBoundingBox: {
			value: null,
			setter: nodeSetter
		},

		/**
		 * HTML element to receive the day value when a date is selected.
		 *
		 * @attribute dayField
		 * @default Generated HTML select element
		 * @type Node | String
		 */
		dayField: {
			setter: nodeSetter,
			valueFn: createSelect
		},

		/**
		 * HTML element to receive the month value when a date is selected.
		 *
		 * @attribute monthField
		 * @default Generated HTML select element
		 * @type Node | String
		 */
		monthField: {
			setter: nodeSetter,
			valueFn: createSelect
		},

		/**
		 * HTML element to receive the year value when a date is selected.
		 *
		 * @attribute yearField
		 * @default Generated HTML select element
		 * @type Node | String
		 */
		yearField: {
			setter: nodeSetter,
			valueFn: createSelect
		},

		/**
		 * Name attribute used on the dayField.
		 *
		 * @attribute dayFieldName
		 * @default day
		 * @type String
		 */
		dayFieldName: {
			value: DAY
		},

		/**
		 * Name attribute used on the monthField.
		 *
		 * @attribute monthFieldName
		 * @default month
		 * @type String
		 */
		monthFieldName: {
			value: MONTH
		},

		/**
		 * Name attribute used on the yearField.
		 *
		 * @attribute yearFieldName
		 * @default year
		 * @type String
		 */
		yearFieldName: {
			value: YEAR
		},

		/**
		 * Trigger element to open the calendar. Inherited from ContextOverlay.
		 *
		 * @attribute trigger
		 * @default Generated HTLM div element
		 * @type Node | String
		 */
		trigger: {
			valueFn: function() {
				return A.Node.create(WRAPPER_BUTTON_TPL).cloneNode();
			}
		},

		/**
		 * If true the Calendar is visible by default after the render phase.
         * Inherited from ContextOverlay.
		 *
		 * @attribute visible
		 * @default false
		 * @type boolean
		 */
		visible: {
			value: false
		},

		/**
		 * Year range to be displayed on the year select element. By default
         * it displays from -10 to +10 years from the current year.
		 *
		 * @attribute yearRange
		 * @default [ year - 10, year + 10 ]
		 * @type Array
		 */
		yearRange: {
			valueFn: function() {
				var year = new Date().getFullYear();

				return [ year - 10, year + 10 ]
			},
			validator: isArray
		},

		/**
		 * Inherited from Calendar.
		 *
		 * @attribute setValue
		 * @default false
		 * @type boolean
		 */
		setValue: {
			value: false
		},

		/**
		 * If true the select element for the days will be automatic
         * populated.
		 *
		 * @attribute populateDay
		 * @default true
		 * @type boolean
		 */
		populateDay: {
			value: true
		},

		/**
		 * If true the select element for the month will be automatic
         * populated.
		 *
		 * @attribute populateMonth
		 * @default true
		 * @type boolean
		 */
		populateMonth: {
			value: true
		},

		/**
		 * If true the select element for the year will be automatic
         * populated.
		 *
		 * @attribute populateYear
		 * @default true
		 * @type boolean
		 */
		populateYear: {
			value: true
		}
	}
});

A.extend(DatePickerSelect, A.Calendar, {
	/**
	 * Create the DOM structure for the DatePickerSelect. Lifecycle.
	 *
	 * @method renderUI
	 * @protected
	 */
	renderUI: function() {
		var instance = this;

		DatePickerSelect.superclass.renderUI.apply(this, arguments);

		instance._renderElements();
		instance._renderTriggerButton();
	},

	/**
	 * Bind the events on the DatePickerSelect UI. Lifecycle.
	 *
	 * @method bindUI
	 * @protected
	 */
	bindUI: function() {
		var instance = this;

		DatePickerSelect.superclass.bindUI.apply(this, arguments);

		instance.after('datesChange', A.bind(instance._selectCurrentValues, instance));
		instance.after('currentMonthChange', A.bind(instance._afterSetCurrentMonth, instance));

		instance._bindSelectEvents();
	},

	/**
	 * Sync the DatePickerSelect UI. Lifecycle.
	 *
	 * @method syncUI
	 * @protected
	 */
	syncUI: function() {
		var instance = this;

		DatePickerSelect.superclass.syncUI.apply(this, arguments);

		instance._pupulateSelects();
		instance._selectCurrentValues();
	},

	/**
	 * Gets an Array with the field elements in the correct order defined
     * on appendOrder.
	 *
	 * @method _getAppendOrder
	 * @protected
	 * @return Array
	 */
	_getAppendOrder: function() {
		var instance = this;
		var appendOrder = instance.get(APPEND_ORDER);

		var mapping = {
			d: instance.get(DAY_FIELD),
			m: instance.get(MONTH_FIELD),
			y: instance.get(YEAR_FIELD)
		};

		var firstField = mapping[ appendOrder[0] ];
		var secondField = mapping[ appendOrder[1] ];
		var thirdField = mapping[ appendOrder[2] ];

		return [ firstField, secondField, thirdField ]
	},

	/**
	 * Render DOM elements for the DatePickerSelect.
	 *
	 * @method _renderElements
	 * @protected
	 */
	_renderElements: function() {
		var instance = this;
		var displayBoundingBox = instance.get(DISPLAY_BOUNDING_BOX);

		if (!displayBoundingBox) {
			displayBoundingBox = A.Node.create(DISPLAY_BOUNDING_BOX_TPL);

			instance.set(DISPLAY_BOUNDING_BOX, displayBoundingBox);

			A.get(BODY).append(displayBoundingBox);
		}

		var dayField = instance.get(DAY_FIELD);
		var monthField = instance.get(MONTH_FIELD);
		var yearField = instance.get(YEAR_FIELD);

		dayField.addClass(CSS_DATEPICKER_DAY);
		monthField.addClass(CSS_DATEPICKER_MONTH);
		yearField.addClass(CSS_DATEPICKER_YEAR);

		displayBoundingBox.addClass(CSS_DATEPICKER);
		displayBoundingBox.addClass(CSS_DATEPICKER_DISPLAY);
		displayBoundingBox.addClass(CSS_HELPER_CLEARFIX);

		instance._selectWrapper = A.Node.create(WRAPPER_SELECT_TPL);

		// setting name of the fields
		monthField.set(NAME, instance.get(MONTH_FIELD_NAME));
		yearField.set(NAME, instance.get(YEAR_FIELD_NAME));
		dayField.set(NAME, instance.get(DAY_FIELD_NAME));

		// append elements
		var orderedFields = instance._getAppendOrder();

		instance._selectWrapper.append(orderedFields[0]);
		instance._selectWrapper.append(orderedFields[1]);
		instance._selectWrapper.append(orderedFields[2]);

		displayBoundingBox.append( instance._selectWrapper );
	},

	/**
	 * Render DOM element for the trigger button of the DatePickerSelect.
	 *
	 * @method _renderTriggerButton
	 * @protected
	 */
	_renderTriggerButton: function() {
		var instance = this;
		var trigger = instance.get(TRIGGER).item(0);
		var displayBoundingBox = instance.get(DISPLAY_BOUNDING_BOX);

		instance._buttonItem = new A.ToolItem(CALENDAR);

		displayBoundingBox.append(trigger);

		if ( trigger.test(DOT+CSS_DATEPICKER_BUTTON_WRAPPER) ) {
			// use ToolItem if the user doesn't specify a trigger
			instance._buttonItem.render(trigger);
		}
	},

	/**
	 * Bind events on each select element (change, keypress, etc).
	 *
	 * @method _bindSelectEvents
	 * @protected
	 */
	_bindSelectEvents: function() {
		var instance = this;
		var selects = instance._selectWrapper.all(SELECT);

		selects.on('change', A.bind(instance._onSelectChange, instance));
		selects.on('keypress', A.bind(instance._onSelectChange, instance));
	},

	/**
	 * Select the current values for the day, month and year to the respective
     * input field.
	 *
	 * @method _selectCurrentValues
	 * @protected
	 */
	_selectCurrentValues: function() {
		var instance = this;

		instance._selectCurrentDay();
		instance._selectCurrentMonth();
		instance._selectCurrentYear();
	},

	/**
	 * Select the current day on the respective input field.
	 *
	 * @method _selectCurrentDay
	 * @protected
	 */
	_selectCurrentDay: function() {
		var instance = this;
		var currentDate = instance.getCurrentDate();

		instance.get(DAY_FIELD).val( currentDate.getDate() );
	},

	/**
	 * Select the current month on the respective input field.
	 *
	 * @method _selectCurrentMonth
	 * @protected
	 */
	_selectCurrentMonth: function() {
		var instance = this;
		var currentDate = instance.getCurrentDate();

		instance.get(MONTH_FIELD).val( currentDate.getMonth() );
	},

	/**
	 * Select the current year on the respective input field.
	 *
	 * @method _selectCurrentYear
	 * @protected
	 */
	_selectCurrentYear: function() {
		var instance = this;
		var currentDate = instance.getCurrentDate();

		instance.get(YEAR_FIELD).val( currentDate.getFullYear() );
	},

	/**
	 * Populate each select element with the correct data for the day, month
     * and year.
	 *
	 * @method _pupulateSelects
	 * @protected
	 */
	_pupulateSelects: function() {
		var instance = this;

		instance._populateDays();
		instance._populateMonths();
		instance._populateYears();

		// restricting dates based on the selects values
		var monthOptions = instance.get(MONTH_FIELD).all(OPTION);
		var yearOptions = instance.get(YEAR_FIELD).all(OPTION);

		var mLength = monthOptions.size() - 1;
		var yLength = yearOptions.size() - 1;

		var firstMonth = monthOptions.item(0).val();
		var firstYear = yearOptions.item(0).val();
		var lastMonth = monthOptions.item(mLength).val();
		var lastYear = yearOptions.item(yLength).val();

		var maxMonthDays = instance.getDaysInMonth(lastYear, lastMonth);

		var minDate = new Date(firstYear, firstMonth, 1);
		var maxDate = new Date(lastYear, lastMonth, maxMonthDays);

		instance.set(MAX_DATE, maxDate);
		instance.set(MIN_DATE, minDate);
	},

	/**
	 * Populate the year select element with the correct data.
	 *
	 * @method _populateYears
	 * @protected
	 */
	_populateYears: function() {
		var instance = this;
		var yearRange = instance.get(YEAR_RANGE);
		var yearField = instance.get(YEAR_FIELD);

		if (instance.get(POPULATE_YEAR)) {
			instance._populateSelect(yearField, yearRange[0], yearRange[1]);
		}
	},

	/**
	 * Populate the month select element with the correct data.
	 *
	 * @method _populateMonths
	 * @protected
	 */
	_populateMonths: function() {
		var instance = this;
		var monthField = instance.get(MONTH_FIELD);
		var localeMap = instance._getLocaleMap();
		var monthLabels = localeMap.B;

		if (instance.get(POPULATE_MONTH)) {
			instance._populateSelect(monthField, 0, (monthLabels.length - 1), monthLabels);
		}
	},

	/**
	 * Populate the day select element with the correct data.
	 *
	 * @method _populateDays
	 * @protected
	 */
	_populateDays: function() {
		var instance = this;
		var dayField = instance.get(DAY_FIELD);
		var daysInMonth = instance.getDaysInMonth();

		if (instance.get(POPULATE_DAY)) {
			instance._populateSelect(dayField, 1, daysInMonth);
		}
	},

	/**
	 * Populate a select element with the data passed on the params.
	 *
	 * @method _populateSelect
	 * @param {HTMLSelectElement} select Select to be populated
	 * @param {Number} fromIndex Index to start
	 * @param {Number} toIndex Index to end
	 * @param {Object} values Object with labels to be used as content of each
     * option. Optional.
	 * @protected
	 * @return String
	 */
	_populateSelect: function(select, fromIndex, toIndex, labels, values) {
		var i = 0;
		var index = fromIndex;
		var instance = this;

		select.empty();
		labels = labels || [];
		values = values || [];

		while (index <= toIndex) {
			var value = values[index] || index;
			var label = labels[index] || index;

			A.Node.getDOMNode(select).options[i] = new Option(label, index);

			i++;
			index++;
		}
	},

	/**
	 * Fired on any select change.
	 *
	 * @method _onSelectChange
	 * @param {EventFacade} event
	 * @protected
	 */
	_onSelectChange: function(event) {
		var instance = this;
		var target = event.currentTarget || event.target;
		var monthChanged = target.test(DOT+CSS_DATEPICKER_MONTH);

		var currentDay = instance.get(DAY_FIELD).val();
		var currentMonth = instance.get(MONTH_FIELD).val();
		var currentYear = instance.get(YEAR_FIELD).val();

		instance.set(CURRENT_DAY, currentDay);
		instance.set(CURRENT_MONTH, currentMonth);
		instance.set(CURRENT_YEAR, currentYear);

		if (monthChanged) {
			instance._afterSetCurrentMonth();
		}

		instance._selectDate();
	},

	/**
	 * Fired after currentMonth is set.
	 *
	 * @method _onSelectChange
	 * @param {EventFacade} event
	 * @protected
	 */
	_afterSetCurrentMonth: function(event) {
		var instance = this;

		instance._populateDays();
		instance._selectCurrentDay();
	}
});

A.DatePickerSelect = DatePickerSelect;<|endoftext|>