<commit_before>'use strict';

const HOST = 'localhost';
const PORT = 1337;

const request = require('request');
const url = require('url');

const express = require('express');
const app = express();

const Twig = require('twig');
app.set('views', __dirname);
app.set('view engine', 'twig');

const router = require('../index.js');
router(app, {
    host: HOST,
    port: PORT,
    baseDir: __dirname,
    file: './routing/main_routing.json'
});

/**
 * @func
 * @param {string} path
 * @returns {string} Absolute URI to path
 */
function getAbsoluteURL(path) {
    return url.format({
        protocol: 'http',
        hostname: HOST,
        port: PORT,
        pathname: (path || '')
    });
}

/**
 * @returns {function}
 */
const counter = (() => {
    let count = 0;

    return () => {
        return count++;
    };
}());

describe('Response from', () => {
    beforeEach(() => {
        // Start server before each test
        this.server = app.listen(PORT, () => {
            this._id = counter();
            console.log(`\n[${this._id}] expressjs server listening on port ${PORT}.`);
        });
    });

    afterEach((done) => {
        // Stop server after each test
        this.server.close(() => {
            console.log(`[${this._id}] expressjs server on port ${PORT} was stopped!`);
            done();
        });
    });

    describe('non-existing URL', () => {
        it('returns status code 404', (done) => {
            request.get(getAbsoluteURL('/non-existent-page/'), (error, response) => {
                expect(response.statusCode).toBe(404);
                done();
            });
        });
    });

    describe('route without requirement attribute "defaults._controller"', () => {
        it('returns status code 500', (done) => {
            request.get(getAbsoluteURL('/route-without-controller/'), (error, response) => {
                expect(response.statusCode).toBe(500);
                done();
            });
        });

        it('returns error message', (done) => {
            request.get(getAbsoluteURL('/route-without-controller/'), (error, response, body) => {
                expect(body).toMatch(/Could not load controller "" for route "route_without_controller"\./i);
                done();
            });
        });
    });

    describe('simple route with requirement attributes only', () => {
        it('returns status code 200', (done) => {
            request.get(getAbsoluteURL('/route-simple/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns JSON', (done) => {
            request.get(getAbsoluteURL('/route-simple/'), (error, response, body) => {
                expect(JSON.parse(body)).toEqual({
                    data: {}
                });
                done();
            });
        });
    });

    describe('route for HTML but without template', () => {
        it('returns status code 500', (done) => {
            request.get(getAbsoluteURL('/route-for-html-without-template/'), (error, response) => {
                expect(response.statusCode).toBe(500);
                done();
            });
        });

        it('returns error message', (done) => {
            request.get(getAbsoluteURL('/route-for-html-without-template/'), (error, response, body) => {
                expect(body).toMatch(/Template for route "route_for_html_without_template" is not defined\./i);
                done();
            });
        });
    });

    describe('route with template', () => {
        it('returns status code 200', (done) => {
            request.get(getAbsoluteURL('/route-with-template-without-format/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns "Hello, World!"', (done) => {
            request.get(getAbsoluteURL('/route-with-template-without-format/'), (error, response, body) => {
                expect(body).toBe('Hello, World!');
                done();
            });
        });
    });

    describe('route for JSON with template', () => {
        it('returns status code 200', (done) => {
            request.get(getAbsoluteURL('/route-with-template-for-json/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns JSON', (done) => {
            request.get(getAbsoluteURL('/route-with-template-for-json/'), (error, response) => {
                expect(response.headers['content-type']).toMatch(/application\/json/i);
                done();
            });
        });

        // @todo: this suit crushes server
        xit('returns JSON', (done) => {
            request.get(getAbsoluteURL('/route-with-template-for-json/'), (error, response, body) => {
                expect(JSON.parse(body)).toEqual({
                    data: {}
                });
                done();
            });
        });
    });

    describe('route with param', () => {
        it('returns status code 404 for not matched "val3"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val3/'), (error, response) => {
                expect(response.statusCode).toBe(404);
                done();
            });
        });

        it('returns status code 200 for matched "val1"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val1/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns "Parameter from URL is "val1"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val1/'), (error, response, body) => {
                expect(body).toMatch('Parameter from URL is "val1"');
                done();
            });
        });

        it('returns status code 200 for matched "val2"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val2/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns "Parameter from URL is "val2"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val2/'), (error, response, body) => {
                expect(body).toMatch('Parameter from URL is "val2"');
                done();
            });
        });
    });

    describe('route Only POST method is allowed', () => {
        it('returns status code 405 for GET', (done) => {
            request.post(getAbsoluteURL('/only-post-method-allowing/'), (error, response) => {
                expect(response.statusCode).toBe(405);
                done();
            });
        });

        it('returns status code 200 for POST', (done) => {
            request.post(getAbsoluteURL('/only-post-method-allowing/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });
    });

    // Routes from external_routing.json
    describe('simple external route with requirement attributes only', () => {
        it('returns status code 200', (done) => {
            request.get(getAbsoluteURL('/external/external-route-simple/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns JSON', (done) => {
            request.get(getAbsoluteURL('/external/external-route-simple/'), (error, response, body) => {
                expect(JSON.parse(body)).toEqual({
                    data: {}
                });
                done();
            });
        });
    });

    describe('external route with param', () => {
        it('returns status code 200 for matched "val1"', (done) => {
            request.get(getAbsoluteURL('/external/external-route-with-param/val1/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns "Parameter from URL is "val1"', (done) => {
            request.get(getAbsoluteURL('/external/external-route-with-param/val1/'), (error, response, body) => {
                expect(body).toMatch('Parameter from URL is "val1"');
                done();
            });
        });
    });
});
<commit_msg>GET method was returned for test<commit_after>'use strict';

const HOST = 'localhost';
const PORT = 1337;

const request = require('request');
const url = require('url');

const express = require('express');
const app = express();

const Twig = require('twig');
app.set('views', __dirname);
app.set('view engine', 'twig');

const router = require('../index.js');
router(app, {
    host: HOST,
    port: PORT,
    baseDir: __dirname,
    file: './routing/main_routing.json'
});

/**
 * @func
 * @param {string} path
 * @returns {string} Absolute URI to path
 */
function getAbsoluteURL(path) {
    return url.format({
        protocol: 'http',
        hostname: HOST,
        port: PORT,
        pathname: (path || '')
    });
}

/**
 * @returns {function}
 */
const counter = (() => {
    let count = 0;

    return () => {
        return count++;
    };
}());

describe('Response from', () => {
    beforeEach(() => {
        // Start server before each test
        this.server = app.listen(PORT, () => {
            this._id = counter();
            console.log(`\n[${this._id}] expressjs server listening on port ${PORT}.`);
        });
    });

    afterEach((done) => {
        // Stop server after each test
        this.server.close(() => {
            console.log(`[${this._id}] expressjs server on port ${PORT} was stopped!`);
            done();
        });
    });

    describe('non-existing URL', () => {
        it('returns status code 404', (done) => {
            request.get(getAbsoluteURL('/non-existent-page/'), (error, response) => {
                expect(response.statusCode).toBe(404);
                done();
            });
        });
    });

    describe('route without requirement attribute "defaults._controller"', () => {
        it('returns status code 500', (done) => {
            request.get(getAbsoluteURL('/route-without-controller/'), (error, response) => {
                expect(response.statusCode).toBe(500);
                done();
            });
        });

        it('returns error message', (done) => {
            request.get(getAbsoluteURL('/route-without-controller/'), (error, response, body) => {
                expect(body).toMatch(/Could not load controller "" for route "route_without_controller"\./i);
                done();
            });
        });
    });

    describe('simple route with requirement attributes only', () => {
        it('returns status code 200', (done) => {
            request.get(getAbsoluteURL('/route-simple/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns JSON', (done) => {
            request.get(getAbsoluteURL('/route-simple/'), (error, response, body) => {
                expect(JSON.parse(body)).toEqual({
                    data: {}
                });
                done();
            });
        });
    });

    describe('route for HTML but without template', () => {
        it('returns status code 500', (done) => {
            request.get(getAbsoluteURL('/route-for-html-without-template/'), (error, response) => {
                expect(response.statusCode).toBe(500);
                done();
            });
        });

        it('returns error message', (done) => {
            request.get(getAbsoluteURL('/route-for-html-without-template/'), (error, response, body) => {
                expect(body).toMatch(/Template for route "route_for_html_without_template" is not defined\./i);
                done();
            });
        });
    });

    describe('route with template', () => {
        it('returns status code 200', (done) => {
            request.get(getAbsoluteURL('/route-with-template-without-format/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns "Hello, World!"', (done) => {
            request.get(getAbsoluteURL('/route-with-template-without-format/'), (error, response, body) => {
                expect(body).toBe('Hello, World!');
                done();
            });
        });
    });

    describe('route for JSON with template', () => {
        it('returns status code 200', (done) => {
            request.get(getAbsoluteURL('/route-with-template-for-json/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns JSON', (done) => {
            request.get(getAbsoluteURL('/route-with-template-for-json/'), (error, response) => {
                expect(response.headers['content-type']).toMatch(/application\/json/i);
                done();
            });
        });

        // @todo: this suit crushes server
        xit('returns JSON', (done) => {
            request.get(getAbsoluteURL('/route-with-template-for-json/'), (error, response, body) => {
                expect(JSON.parse(body)).toEqual({
                    data: {}
                });
                done();
            });
        });
    });

    describe('route with param', () => {
        it('returns status code 404 for not matched "val3"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val3/'), (error, response) => {
                expect(response.statusCode).toBe(404);
                done();
            });
        });

        it('returns status code 200 for matched "val1"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val1/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns "Parameter from URL is "val1"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val1/'), (error, response, body) => {
                expect(body).toMatch('Parameter from URL is "val1"');
                done();
            });
        });

        it('returns status code 200 for matched "val2"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val2/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns "Parameter from URL is "val2"', (done) => {
            request.get(getAbsoluteURL('/route-with-param/val2/'), (error, response, body) => {
                expect(body).toMatch('Parameter from URL is "val2"');
                done();
            });
        });
    });

    describe('route Only POST method is allowed', () => {
        it('returns status code 405 for GET', (done) => {
            request.get(getAbsoluteURL('/only-post-method-allowing/'), (error, response) => {
                expect(response.statusCode).toBe(404);
                done();
            });
        });

        it('returns status code 200 for POST', (done) => {
            request.post(getAbsoluteURL('/only-post-method-allowing/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });
    });

    // Routes from external_routing.json
    describe('simple external route with requirement attributes only', () => {
        it('returns status code 200', (done) => {
            request.get(getAbsoluteURL('/external/external-route-simple/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns JSON', (done) => {
            request.get(getAbsoluteURL('/external/external-route-simple/'), (error, response, body) => {
                expect(JSON.parse(body)).toEqual({
                    data: {}
                });
                done();
            });
        });
    });

    describe('external route with param', () => {
        it('returns status code 200 for matched "val1"', (done) => {
            request.get(getAbsoluteURL('/external/external-route-with-param/val1/'), (error, response) => {
                expect(response.statusCode).toBe(200);
                done();
            });
        });

        it('returns "Parameter from URL is "val1"', (done) => {
            request.get(getAbsoluteURL('/external/external-route-with-param/val1/'), (error, response, body) => {
                expect(body).toMatch('Parameter from URL is "val1"');
                done();
            });
        });
    });
});
<|endoftext|>


<commit_before>var m = require('mithril');
var winningChances = require('./winningChances');
var defined = require('common').defined;
var classSet = require('common').classSet;
var renderEval = require('chess').renderEval;
var pv2san = require('./pv2san');

var gaugeLast = 0;
var gaugeTicks = [];
for (var i = 1; i < 8; i++) gaugeTicks.push(m(i === 4 ? 'tick.zero' : 'tick', {
  style: {
    height: (i * 12.5) + '%'
  }
}));

function range(len) {
  var r = [];
  for (var i = 0; i < len; i++) r.push(i);
  return r;
}

function localEvalInfo(ctrl, evs) {
  var ceval = ctrl.getCeval();
  if (!evs.client) {
    if (evs.server && ctrl.nextNodeBest()) return 'Using server analysis';
    return 'Loading engine...';
  }
  var t = evs.client.cloud ? [
    [
      'Depth ' + (evs.client.depth || 0),
      m('span.cloud', {
        title: 'Cloud Analysis'
      }, 'cloud')
    ]
  ] : [
    'Depth ' + (evs.client.depth || 0) + '/' + evs.client.maxDepth
  ];
  if (ceval.canGoDeeper() && (
      evs.client.depth >= (evs.client.maxDepth || ceval.effectiveMaxDepth())
    ))
    t.push(m('a.deeper', {
      title: 'Go deeper',
      'data-icon': 'O',
      onclick: ceval.goDeeper
    }))
  else if (!evs.client.cloud && evs.client.knps) t.push(', ' + Math.round(evs.client.knps) + ' knodes/s');
  return t;
}

function threatInfo(threat) {
  if (!threat) return 'Loading engine...';
  var t = 'Depth ' + (threat.depth || 0) + '/' + threat.maxDepth;
  if (threat.knps) t += ', ' + Math.round(threat.knps) + ' knodes/s';
  return t;
}

function threatButton(ctrl) {
  if (!ctrl.disableThreatMode || !ctrl.disableThreatMode()) return m('a', {
    class: classSet({
      'show-threat': true,
      active: ctrl.vm.threatMode,
      hidden: ctrl.vm.node.check
    }),
    'data-icon': '7',
    title: 'Show threat (x)',
    onclick: ctrl.toggleThreatMode
  });
}

function engineName(ctrl) {
  return [
    lichess.engineName,
    ctrl.pnaclSupported ? m('span.native', 'native') : m('span.asmjs', 'asmjs')
  ];
}

var serverNodes = 3.5e6;

function getBestEval(evs) {
  var serverEv = evs.server,
    localEv = evs.client;

  if (!serverEv) return localEv;
  if (!localEv) return serverEv;

  // Prefer localEv if it exeeds fishnet node limit or finds a better mate.
  if (localEv.nodes > serverNodes ||
    (localEv.mate && !(Math.abs(serverEv.mate) < Math.abs(localEv.mate))))
    return localEv;

  return serverEv;
}

module.exports = {
  getBestEval: getBestEval,
  renderGauge: function(ctrl) {
    if (ctrl.ongoing || !ctrl.showEvalGauge()) return;
    var eval, bestEv = getBestEval(ctrl.currentEvals());
    if (bestEv) {
      eval = winningChances.povChances('white', bestEv);
      gaugeLast = eval;
    } else eval = gaugeLast;
    var height = 100 - (eval + 1) * 50;
    return m('div', {
      class: classSet({
        eval_gauge: true,
        empty: eval === null,
        reverse: ctrl.getOrientation() === 'black'
      })
    }, [
      m('div', {
        class: 'black',
        style: {
          height: height + '%'
        }
      }),
      gaugeTicks
    ]);
  },
  renderCeval: function(ctrl) {
    var instance = ctrl.getCeval();
    if (!instance.allowed() || !instance.possible || !ctrl.vm.showComputer()) return;
    var enabled = instance.enabled();
    var evs = ctrl.currentEvals();
    var bestEv = getBestEval(evs);
    var threatMode = ctrl.vm.threatMode;
    var threat = threatMode && ctrl.vm.node.threat;
    var pearl, percent;
    if (bestEv && defined(bestEv.cp)) {
      pearl = renderEval(bestEv.cp);
      percent = ctrl.nextNodeBest() ?
        100 :
        (evs.client ? Math.min(100, Math.round(100 * evs.client.depth / (evs.client.maxDepth || instance.effectiveMaxDepth()))) : 0)
    } else if (bestEv && defined(bestEv.mate)) {
      pearl = '#' + bestEv.mate;
      percent = 100;
    } else if (ctrl.gameOver()) {
      pearl = '-';
      percent = 0;
    } else {
      pearl = m('span.cpu', 'CPU');
      percent = 0;
    }
    if (threatMode) {
      if (threat) percent = Math.min(100, Math.round(100 * threat.depth / threat.maxDepth));
      else percent = 0;
    }
    var mandatoryCeval = ctrl.mandatoryCeval && ctrl.mandatoryCeval();
    return m('div', {
        class: 'ceval_box ' + (percent < 100 && instance.isComputing() ? 'computing' : '')
      },
      enabled ? m('div.bar', m('span', {
        class: threatMode ? 'threat' : '',
        style: {
          width: percent + '%'
        },
        config: function(el, isUpdate, ctx) {
          // reinsert the node to avoid downward animation
          if (isUpdate && (ctx.percent > percent || ctx.threatMode !== threatMode)) {
            var p = el.parentNode;
            p.removeChild(el);
            p.appendChild(el);
          }
          ctx.percent = percent;
          ctx.threatMode = threatMode;
        }
      })) : null,
      enabled ? [
        m('pearl', pearl),
        m('div.engine', [
          threatMode ? 'Show threat' : engineName(instance),
          m('span.info', ctrl.gameOver() ? 'Game over.' : (
            threatMode ? threatInfo(threat) : localEvalInfo(ctrl, evs)
          ))
        ])
      ] : [
        pearl ? m('pearl', pearl) : null,
        m('help',
          engineName(instance),
          m('br'),
          'in local browser'
        )
      ],
      mandatoryCeval ? null : m('div.switch', {
        title: 'Toggle local evaluation (l)'
      }, [
        m('input', {
          id: 'analyse-toggle-ceval',
          class: 'cmn-toggle cmn-toggle-round',
          type: 'checkbox',
          checked: enabled,
          onchange: ctrl.toggleCeval
        }),
        m('label', {
          'for': 'analyse-toggle-ceval'
        })
      ]),
      threatButton(ctrl)
    )
  },
  renderPvs: function(ctrl) {
    var instance = ctrl.getCeval();
    if (!instance.allowed() || !instance.possible || !instance.enabled()) return;
    var multiPv = instance.multiPv();
    var pvs, threat = false;
    if (ctrl.vm.threatMode && ctrl.vm.node.threat) {
      pvs = ctrl.vm.node.threat.pvs;
      threat = true;
    } else if (ctrl.vm.node.ceval)
      pvs = ctrl.vm.node.ceval.pvs;
    else
      pvs = [];
    return m('div.pv_box', {
      'data-fen': ctrl.vm.node.fen,
      config: function(el, isUpdate, ctx) {
        if (!isUpdate) {
          el.addEventListener('mouseover', function(e) {
            instance.setHovering($(el).attr('data-fen'), $(e.target).closest('div.pv').attr('data-uci'));
          });
          el.addEventListener('mouseout', function(e) {
            instance.setHovering($(el).attr('data-fen'), null);
          });
          el.addEventListener('mousedown', function(e) {
            var uci = $(e.target).closest('div.pv').attr('data-uci');
            if (uci) ctrl.playUci(uci);
          });
        }
        setTimeout(function() {
          instance.setHovering($(el).attr('data-fen'), $(el).find('div.pv:hover').attr('data-uci'));
        }, 100);
      }
    }, range(multiPv).map(function(i) {
      if (!pvs[i]) return m('div.pv');
      else return m('div.pv', threat ? {} : {
        'data-uci': pvs[i].moves[0]
      }, [
        multiPv > 1 ? m('strong', defined(pvs[i].mate) ? ('#' + pvs[i].mate) : renderEval(pvs[i].cp)) : null,
        m('span', pv2san(instance.variant.key, ctrl.vm.node.fen, threat, pvs[i].moves, pvs[i].mate))
      ]);
    }));
  }
};
<commit_msg>ceval: no longer display full bar when server analysis has a best move<commit_after>var m = require('mithril');
var winningChances = require('./winningChances');
var defined = require('common').defined;
var classSet = require('common').classSet;
var renderEval = require('chess').renderEval;
var pv2san = require('./pv2san');

var gaugeLast = 0;
var gaugeTicks = [];
for (var i = 1; i < 8; i++) gaugeTicks.push(m(i === 4 ? 'tick.zero' : 'tick', {
  style: {
    height: (i * 12.5) + '%'
  }
}));

function range(len) {
  var r = [];
  for (var i = 0; i < len; i++) r.push(i);
  return r;
}

function localEvalInfo(ctrl, evs) {
  var ceval = ctrl.getCeval();
  if (!evs.client) {
    if (evs.server && ctrl.nextNodeBest()) return 'Using server analysis';
    return 'Loading engine...';
  }
  var t = evs.client.cloud ? [
    [
      'Depth ' + (evs.client.depth || 0),
      m('span.cloud', {
        title: 'Cloud Analysis'
      }, 'cloud')
    ]
  ] : [
    'Depth ' + (evs.client.depth || 0) + '/' + evs.client.maxDepth
  ];
  if (ceval.canGoDeeper() && (
      evs.client.depth >= (evs.client.maxDepth || ceval.effectiveMaxDepth())
    ))
    t.push(m('a.deeper', {
      title: 'Go deeper',
      'data-icon': 'O',
      onclick: ceval.goDeeper
    }))
  else if (!evs.client.cloud && evs.client.knps) t.push(', ' + Math.round(evs.client.knps) + ' knodes/s');
  return t;
}

function threatInfo(threat) {
  if (!threat) return 'Loading engine...';
  var t = 'Depth ' + (threat.depth || 0) + '/' + threat.maxDepth;
  if (threat.knps) t += ', ' + Math.round(threat.knps) + ' knodes/s';
  return t;
}

function threatButton(ctrl) {
  if (!ctrl.disableThreatMode || !ctrl.disableThreatMode()) return m('a', {
    class: classSet({
      'show-threat': true,
      active: ctrl.vm.threatMode,
      hidden: ctrl.vm.node.check
    }),
    'data-icon': '7',
    title: 'Show threat (x)',
    onclick: ctrl.toggleThreatMode
  });
}

function engineName(ctrl) {
  return [
    lichess.engineName,
    ctrl.pnaclSupported ? m('span.native', 'native') : m('span.asmjs', 'asmjs')
  ];
}

var serverNodes = 3.5e6;

function getBestEval(evs) {
  var serverEv = evs.server,
    localEv = evs.client;

  if (!serverEv) return localEv;
  if (!localEv) return serverEv;

  // Prefer localEv if it exeeds fishnet node limit or finds a better mate.
  if (localEv.nodes > serverNodes ||
    (localEv.mate && !(Math.abs(serverEv.mate) < Math.abs(localEv.mate))))
    return localEv;

  return serverEv;
}

module.exports = {
  getBestEval: getBestEval,
  renderGauge: function(ctrl) {
    if (ctrl.ongoing || !ctrl.showEvalGauge()) return;
    var eval, bestEv = getBestEval(ctrl.currentEvals());
    if (bestEv) {
      eval = winningChances.povChances('white', bestEv);
      gaugeLast = eval;
    } else eval = gaugeLast;
    var height = 100 - (eval + 1) * 50;
    return m('div', {
      class: classSet({
        eval_gauge: true,
        empty: eval === null,
        reverse: ctrl.getOrientation() === 'black'
      })
    }, [
      m('div', {
        class: 'black',
        style: {
          height: height + '%'
        }
      }),
      gaugeTicks
    ]);
  },
  renderCeval: function(ctrl) {
    var instance = ctrl.getCeval();
    if (!instance.allowed() || !instance.possible || !ctrl.vm.showComputer()) return;
    var enabled = instance.enabled();
    var evs = ctrl.currentEvals();
    var bestEv = getBestEval(evs);
    var threatMode = ctrl.vm.threatMode;
    var threat = threatMode && ctrl.vm.node.threat;
    var pearl, percent;
    if (bestEv && defined(bestEv.cp)) {
      pearl = renderEval(bestEv.cp);
      percent = evs.client ? Math.min(100, Math.round(100 * evs.client.depth / (evs.client.maxDepth || instance.effectiveMaxDepth()))) : 0;
    } else if (bestEv && defined(bestEv.mate)) {
      pearl = '#' + bestEv.mate;
      percent = 100;
    } else if (ctrl.gameOver()) {
      pearl = '-';
      percent = 0;
    } else {
      pearl = m('span.cpu', 'CPU');
      percent = 0;
    }
    if (threatMode) {
      if (threat) percent = Math.min(100, Math.round(100 * threat.depth / threat.maxDepth));
      else percent = 0;
    }
    var mandatoryCeval = ctrl.mandatoryCeval && ctrl.mandatoryCeval();
    return m('div', {
        class: 'ceval_box ' + (percent < 100 && instance.isComputing() ? 'computing' : '')
      },
      enabled ? m('div.bar', m('span', {
        class: threatMode ? 'threat' : '',
        style: {
          width: percent + '%'
        },
        config: function(el, isUpdate, ctx) {
          // reinsert the node to avoid downward animation
          if (isUpdate && (ctx.percent > percent || ctx.threatMode !== threatMode)) {
            var p = el.parentNode;
            p.removeChild(el);
            p.appendChild(el);
          }
          ctx.percent = percent;
          ctx.threatMode = threatMode;
        }
      })) : null,
      enabled ? [
        m('pearl', pearl),
        m('div.engine', [
          threatMode ? 'Show threat' : engineName(instance),
          m('span.info', ctrl.gameOver() ? 'Game over.' : (
            threatMode ? threatInfo(threat) : localEvalInfo(ctrl, evs)
          ))
        ])
      ] : [
        pearl ? m('pearl', pearl) : null,
        m('help',
          engineName(instance),
          m('br'),
          'in local browser'
        )
      ],
      mandatoryCeval ? null : m('div.switch', {
        title: 'Toggle local evaluation (l)'
      }, [
        m('input', {
          id: 'analyse-toggle-ceval',
          class: 'cmn-toggle cmn-toggle-round',
          type: 'checkbox',
          checked: enabled,
          onchange: ctrl.toggleCeval
        }),
        m('label', {
          'for': 'analyse-toggle-ceval'
        })
      ]),
      threatButton(ctrl)
    )
  },
  renderPvs: function(ctrl) {
    var instance = ctrl.getCeval();
    if (!instance.allowed() || !instance.possible || !instance.enabled()) return;
    var multiPv = instance.multiPv();
    var pvs, threat = false;
    if (ctrl.vm.threatMode && ctrl.vm.node.threat) {
      pvs = ctrl.vm.node.threat.pvs;
      threat = true;
    } else if (ctrl.vm.node.ceval)
      pvs = ctrl.vm.node.ceval.pvs;
    else
      pvs = [];
    return m('div.pv_box', {
      'data-fen': ctrl.vm.node.fen,
      config: function(el, isUpdate, ctx) {
        if (!isUpdate) {
          el.addEventListener('mouseover', function(e) {
            instance.setHovering($(el).attr('data-fen'), $(e.target).closest('div.pv').attr('data-uci'));
          });
          el.addEventListener('mouseout', function(e) {
            instance.setHovering($(el).attr('data-fen'), null);
          });
          el.addEventListener('mousedown', function(e) {
            var uci = $(e.target).closest('div.pv').attr('data-uci');
            if (uci) ctrl.playUci(uci);
          });
        }
        setTimeout(function() {
          instance.setHovering($(el).attr('data-fen'), $(el).find('div.pv:hover').attr('data-uci'));
        }, 100);
      }
    }, range(multiPv).map(function(i) {
      if (!pvs[i]) return m('div.pv');
      else return m('div.pv', threat ? {} : {
        'data-uci': pvs[i].moves[0]
      }, [
        multiPv > 1 ? m('strong', defined(pvs[i].mate) ? ('#' + pvs[i].mate) : renderEval(pvs[i].cp)) : null,
        m('span', pv2san(instance.variant.key, ctrl.vm.node.fen, threat, pvs[i].moves, pvs[i].mate))
      ]);
    }));
  }
};
<|endoftext|>


<commit_before>import assert from 'assert';
import GithubSearchResult from '../github-search-result.js';

const fromGithubJsonToKataGroups = (githubJson) => {
  return GithubSearchResult.toKataGroups(githubJson);
};

describe('create kata groups from the github search result', function() {
  it('one group is created for the same group name', function() {
    const githubJson = {
      items: [
        {path: "kata/group/file.js"},
        {path: "kata/group/file1.js"},
        {path: "kata/group/file2.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson).length;
    assert.equal(kataGroups, 1);
  });

  it('one group is created for the same group name', function() {
    const githubJson = {
      items: [
        {path: "kata/group/file.js"},
        {path: "kata/group/file1.js"},
        {path: "kata/group/file2.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson);
    assert.equal(kataGroups[0].name, 'group');
  });

  it('two groups are created for the two group names', function() {
    const githubJson = {
      items: [
        {path: "kata/group/file.js"},
        {path: "kata/group1/file2.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson).length;
    assert.equal(kataGroups, 2);
  });
});

describe('sort kata groups', function() {
  it('by number of files inside group', function() {
    const githubJson = {
      items: [
        {path: "kata/group/file.js"},
        {path: "kata/group1/file1.js"},
        {path: "kata/group1/file2.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson);
    assert.equal(kataGroups[0].name, 'group');
  });

  it('by name when number of files is the same', function() {
    const githubJson = {
      items: [
        {path: "kata/ab/file.js"},
        {path: "kata/aa/file.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson);
    assert.equal(kataGroups[0].name, 'aa');
  });
});
<commit_msg>Switch back test that I changed wrongly.<commit_after>import assert from 'assert';
import GithubSearchResult from '../github-search-result.js';

const fromGithubJsonToKataGroups = (githubJson) => {
  return GithubSearchResult.toKataGroups(githubJson);
};

describe('create kata groups from the github search result', function() {
  it('one group is created for the same group name', function() {
    const githubJson = {
      items: [
        {path: "kata/group/file.js"},
        {path: "kata/group/file1.js"},
        {path: "kata/group/file2.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson).length;
    assert.equal(kataGroups, 1);
  });

  it('one group is created for the same group name', function() {
    const githubJson = {
      items: [
        {path: "kata/group/file.js"},
        {path: "kata/group/file1.js"},
        {path: "kata/group/file2.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson);
    assert.equal(kataGroups[0].name, 'group');
  });

  it('two groups are created for the two group names', function() {
    const githubJson = {
      items: [
        {path: "kata/group/file.js"},
        {path: "kata/group1/file2.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson).length;
    assert.equal(kataGroups, 2);
  });
});

describe('sort kata groups', function() {
  it('by number of files inside group', function() {
    const githubJson = {
      items: [
        {path: "kata/group/file.js"},
        {path: "kata/group1/file1.js"},
        {path: "kata/group1/file2.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson);
    assert.equal(kataGroups[0].name, 'group1');
  });

  it('by name when number of files is the same', function() {
    const githubJson = {
      items: [
        {path: "kata/ab/file.js"},
        {path: "kata/aa/file.js"}
      ]
    };

    var kataGroups = fromGithubJsonToKataGroups(githubJson);
    assert.equal(kataGroups[0].name, 'aa');
  });
});
<|endoftext|>


<commit_before>describe("shuffle", function() {
  ensureLaziness(function() { Lazy(people).shuffle(); });

  // Not 100% sure of a great way to do this, so... let's just go with a
  // probabilistic test.
  it("shuffles the collection", function() {
    var shuffledCollections = Lazy.range(10)
      .map(function() { return Lazy(people).shuffle().toArray(); });

    var firstResult = shuffledCollections.first();
    shuffledCollections.each(function(collection) {
      // Verify the elements in the collection
      var resorted = Lazy(collection)
        .sortBy(Person.getAge)
        .reverse()
        .toArray();
      expect(resorted).toEqual(people);
    });

    var differences = Lazy(people)
      .map(function() { return 0; })
      .toArray();

    shuffledCollections.drop(1).each(function(collection) {
      for (var i = 0; i < collection.length; ++i) {
        if (collection[i] !== firstResult[i]) {
          differences[i]++;
        }
      }
    });

    for (var i = 0; i < people.length; ++i) {
      expect(differences[i]).toBeGreaterThan(0, 'All elements at ' + i + ' are the same!');
    }
  });

  it("passes an index along with each element", function() {
    expect(Lazy(people).shuffle()).toPassToEach(1, [0, 1, 2, 3, 4, 5]);
  });
});
<commit_msg>added test to show #shuffle is biased<commit_after>describe("shuffle", function() {
  ensureLaziness(function() { Lazy(people).shuffle(); });

  // Not 100% sure of a great way to do this, so... let's just go with a
  // probabilistic test.
  it("shuffles the collection", function() {
    var shuffledCollections = Lazy.range(10)
      .map(function() { return Lazy(people).shuffle().toArray(); })
      .memoize();

    var firstResult = shuffledCollections.first();
    shuffledCollections.each(function(collection) {
      // Verify the elements in the collection
      var resorted = Lazy(collection)
        .sortBy(Person.getAge)
        .reverse()
        .toArray();
      expect(resorted).toEqual(people);
    });

    var differences = Lazy(people)
      .map(function() { return 0; })
      .toArray();

    shuffledCollections.drop(1).each(function(collection) {
      for (var i = 0; i < collection.length; ++i) {
        if (collection[i] !== firstResult[i]) {
          differences[i]++;
        }
      }
    });

    for (var i = 0; i < people.length; ++i) {
      expect(differences[i]).toBeGreaterThan(0, 'All elements at ' + i + ' are the same!');
    }
  });

  it("is unbiased", function() {
    var firsts = Lazy.range(100)
      .map(function() { return Lazy(people).shuffle().first(); })
      .memoize();

    expect(firsts.uniq().sortBy(Person.getName)).toComprise([
      adam, daniel, david, happy, lauren, mary
    ]);
  });

  it("passes an index along with each element", function() {
    expect(Lazy(people).shuffle()).toPassToEach(1, [0, 1, 2, 3, 4, 5]);
  });
});
<|endoftext|>


<commit_before>/*
*   getaccname.js
*
*   Note: Information in this module is based on the following documents:
*   1. HTML Accessibility API Mappings 1.0 (http://rawgit.com/w3c/aria/master/html-aam/html-aam.html)
*   2. SVG Accessibility API Mappings (http://rawgit.com/w3c/aria/master/svg-aam/svg-aam.html)
*/

import {
  getAttributeValue,
  getElementContents,
  isLabelableElement,
  nameFromAttribute,
  nameFromAltAttribute,
  nameFromContents,
  nameFromDefault,
  nameFromDescendant,
  nameFromLabelElement,
  nameFromDetailsOrSummary
} from './namefrom';

import { getAriaRole, nameFromIncludesContents } from './roles';

/*
*   getFieldsetLegendLabels: Recursively collect legend contents of
*   fieldset ancestors, starting with the closest (innermost).
*   Return collection as a possibly empty array of strings.
*/
function getFieldsetLegendLabels (element) {
  let arrayOfStrings = [];

  if (typeof element.closest !== 'function') {
    return arrayOfStrings;
  }

  function getLabelsRec (elem, arr) {
    let fieldset = elem.closest('fieldset');

    if (fieldset) {
      let legend = fieldset.querySelector('legend');
      if (legend) {
        let text = getElementContents(legend);
        if (text.length){
          arr.push({ name: text, source: 'fieldset/legend' });
        }
      }
      // process ancestors
      getLabelsRec(fieldset.parentNode, arr);
    }
  }

  getLabelsRec(element, arrayOfStrings);
  return arrayOfStrings;
}

/*
*   getGroupingLabels: Return an array of grouping label objects for
*   element, each with two properties: 'name' and 'source'.
*/
export function getGroupingLabels (element) {
  // We currently only handle labelable elements as defined in HTML 5.1
  if (isLabelableElement(element)) {
    return getFieldsetLegendLabels(element);
  }

  return [];
}

/*
*   nameFromNativeSemantics: Use method appropriate to the native semantics
*   of element to find accessible name. Includes methods for all interactive
*   elements. For non-interactive elements, if the element's ARIA role allows
*   its acc. name to be derived from its text contents, or if recFlag is set,
*   indicating that we are in a recursive aria-labelledby calculation, the
*   nameFromContents method is used.
*/
export function nameFromNativeSemantics (element, recFlag = false) {
  let tagName = element.tagName.toLowerCase(),
      ariaRole = getAriaRole(element),
      accName = null;

  // TODO: Verify that this applies to all elements
  if (ariaRole && (ariaRole === 'presentation' || ariaRole === 'none')) {
    return null;
  }

  switch (tagName) {
    // FORM ELEMENTS: INPUT
    case 'input':
      switch (element.type) {
        // HIDDEN
        case 'hidden':
          if (recFlag) {
            accName = nameFromLabelElement(element);
          }
          break;

        // TEXT FIELDS
        case 'email':
        case 'password':
        case 'search':
        case 'tel':
        case 'text':
        case 'url':
          accName = nameFromLabelElement(element);
          if (accName === null) accName = nameFromAttribute(element, 'placeholder');
          break;

        // OTHER INPUT TYPES
        case 'button':
          accName = nameFromAttribute(element, 'value');
          break;

        case 'reset':
          accName = nameFromAttribute(element, 'value');
          if (accName === null) accName = nameFromDefault('Reset');
          break;

        case 'submit':
          accName = nameFromAttribute(element, 'value');
          if (accName === null) accName = nameFromDefault('Submit');
          break;

        case 'image':
          accName = nameFromAltAttribute(element);
          if (accName === null) accName = nameFromAttribute(element, 'value');
          break;

        default:
          accName = nameFromLabelElement(element);
          break;
      }
      break;

    // FORM ELEMENTS: OTHER
    case 'button':
      accName = nameFromContents(element);
      break;

    case 'label':
      accName = nameFromContents(element);
      break;

    case 'keygen':
    case 'meter':
    case 'output':
    case 'progress':
    case 'select':
      accName = nameFromLabelElement(element);
      break;

    case 'textarea':
      accName = nameFromLabelElement(element);
      if (accName === null) accName = nameFromAttribute(element, 'placeholder');
      break;

    // EMBEDDED ELEMENTS
    case 'audio': // if 'controls' attribute is present
      accName = { name: 'NOT YET IMPLEMENTED', source: '' };
      break;

    case 'embed':
      accName = { name: 'NOT YET IMPLEMENTED', source: '' };
      break;

    case 'iframe':
      accName = nameFromAttribute(element, 'title');
      break;

    case 'img':
    case 'area': // added
      accName = nameFromAltAttribute(element);
      break;

    case 'object':
      accName = { name: 'NOT YET IMPLEMENTED', source: '' };
      break;

    case 'svg': // added
      accName = nameFromDescendant(element, 'title');
      break;

    case 'video': // if 'controls' attribute is present
      accName = { name: 'NOT YET IMPLEMENTED', source: '' };
      break;

    // OTHER ELEMENTS
    case 'a':
      accName = nameFromContents(element);
      break;

    case 'details':
      accName = nameFromDetailsOrSummary(element);
      break;

    case 'figure':
      accName = nameFromDescendant(element, 'figcaption');
      break;

    case 'table':
      accName = nameFromDescendant(element, 'caption');
      break;

    // ELEMENTS NOT SPECIFIED ABOVE
    default:
      if (nameFromIncludesContents(element) || recFlag)
        accName = nameFromContents(element);
      break;
  }

  // LAST RESORT USE TITLE
  if (accName === null) accName = nameFromAttribute(element, 'title');

  return accName;
}

/*
*   nameFromAttributeIdRefs: Get the value of attrName on element (a space-
*   separated list of IDREFs), visit each referenced element in the order it
*   appears in the list and obtain its accessible name (skipping recursive
*   aria-labelledby or aria-describedby calculations), and return an object
*   with name property set to a string that is a space-separated concatena-
*   tion of those results if any, otherwise return null.
*/
function nameFromAttributeIdRefs (element, attribute) {
  let value = getAttributeValue(element, attribute);
  let idRefs, i, refElement, accName, arr = [];

  if (value.length) {
    idRefs = value.split(' ');

    for (i = 0; i < idRefs.length; i++) {
      refElement = document.getElementById(idRefs[i]);
      accName = getAccessibleName(refElement, true);
      if (accName && accName.name.length) arr.push(accName.name);
    }
  }

  if (arr.length)
    return { name: arr.join(' '), source: attribute };

  return null;
}

/*
*   getAccessibleName: Use the ARIA Roles Model specification for accessible
*   name calculation based on its precedence order:
*   (1) Use aria-labelledby, unless a traversal is already underway;
*   (2) Use aria-label attribute value;
*   (3) Use whatever method is specified by the native semantics of the
*   element, which includes, as last resort, use of the title attribute.
*/
export function getAccessibleName (element, recFlag = false) {
  let accName = null;

  if (!recFlag) accName = nameFromAttributeIdRefs(element, 'aria-labelledby');
  if (accName === null) accName = nameFromAttribute(element, 'aria-label');
  if (accName === null) accName = nameFromNativeSemantics(element, recFlag);

  return accName;
}

/*
*   getAccessibleDesc: Use the ARIA Roles Model specification for accessible
*   description calculation based on its precedence order:
*   (1) Use aria-describedby, unless a traversal is already underway;
*   (2) As last resort, use the title attribute.
*/
export function getAccessibleDesc (element, recFlag = false) {
  let accDesc = null;

  if (!recFlag) accDesc = nameFromAttributeIdRefs(element, 'aria-describedby');
  if (accDesc === null) accDesc = nameFromAttribute(element, 'title');

  return accDesc;
}
<commit_msg>Fix null reference bug in nameFromAttributeIdRefs<commit_after>/*
*   getaccname.js
*
*   Note: Information in this module is based on the following documents:
*   1. HTML Accessibility API Mappings 1.0 (http://rawgit.com/w3c/aria/master/html-aam/html-aam.html)
*   2. SVG Accessibility API Mappings (http://rawgit.com/w3c/aria/master/svg-aam/svg-aam.html)
*/

import {
  getAttributeValue,
  getElementContents,
  isLabelableElement,
  nameFromAttribute,
  nameFromAltAttribute,
  nameFromContents,
  nameFromDefault,
  nameFromDescendant,
  nameFromLabelElement,
  nameFromDetailsOrSummary
} from './namefrom';

import { getAriaRole, nameFromIncludesContents } from './roles';

/*
*   getFieldsetLegendLabels: Recursively collect legend contents of
*   fieldset ancestors, starting with the closest (innermost).
*   Return collection as a possibly empty array of strings.
*/
function getFieldsetLegendLabels (element) {
  let arrayOfStrings = [];

  if (typeof element.closest !== 'function') {
    return arrayOfStrings;
  }

  function getLabelsRec (elem, arr) {
    let fieldset = elem.closest('fieldset');

    if (fieldset) {
      let legend = fieldset.querySelector('legend');
      if (legend) {
        let text = getElementContents(legend);
        if (text.length){
          arr.push({ name: text, source: 'fieldset/legend' });
        }
      }
      // process ancestors
      getLabelsRec(fieldset.parentNode, arr);
    }
  }

  getLabelsRec(element, arrayOfStrings);
  return arrayOfStrings;
}

/*
*   getGroupingLabels: Return an array of grouping label objects for
*   element, each with two properties: 'name' and 'source'.
*/
export function getGroupingLabels (element) {
  // We currently only handle labelable elements as defined in HTML 5.1
  if (isLabelableElement(element)) {
    return getFieldsetLegendLabels(element);
  }

  return [];
}

/*
*   nameFromNativeSemantics: Use method appropriate to the native semantics
*   of element to find accessible name. Includes methods for all interactive
*   elements. For non-interactive elements, if the element's ARIA role allows
*   its acc. name to be derived from its text contents, or if recFlag is set,
*   indicating that we are in a recursive aria-labelledby calculation, the
*   nameFromContents method is used.
*/
export function nameFromNativeSemantics (element, recFlag = false) {
  let tagName = element.tagName.toLowerCase(),
      ariaRole = getAriaRole(element),
      accName = null;

  // TODO: Verify that this applies to all elements
  if (ariaRole && (ariaRole === 'presentation' || ariaRole === 'none')) {
    return null;
  }

  switch (tagName) {
    // FORM ELEMENTS: INPUT
    case 'input':
      switch (element.type) {
        // HIDDEN
        case 'hidden':
          if (recFlag) {
            accName = nameFromLabelElement(element);
          }
          break;

        // TEXT FIELDS
        case 'email':
        case 'password':
        case 'search':
        case 'tel':
        case 'text':
        case 'url':
          accName = nameFromLabelElement(element);
          if (accName === null) accName = nameFromAttribute(element, 'placeholder');
          break;

        // OTHER INPUT TYPES
        case 'button':
          accName = nameFromAttribute(element, 'value');
          break;

        case 'reset':
          accName = nameFromAttribute(element, 'value');
          if (accName === null) accName = nameFromDefault('Reset');
          break;

        case 'submit':
          accName = nameFromAttribute(element, 'value');
          if (accName === null) accName = nameFromDefault('Submit');
          break;

        case 'image':
          accName = nameFromAltAttribute(element);
          if (accName === null) accName = nameFromAttribute(element, 'value');
          break;

        default:
          accName = nameFromLabelElement(element);
          break;
      }
      break;

    // FORM ELEMENTS: OTHER
    case 'button':
      accName = nameFromContents(element);
      break;

    case 'label':
      accName = nameFromContents(element);
      break;

    case 'keygen':
    case 'meter':
    case 'output':
    case 'progress':
    case 'select':
      accName = nameFromLabelElement(element);
      break;

    case 'textarea':
      accName = nameFromLabelElement(element);
      if (accName === null) accName = nameFromAttribute(element, 'placeholder');
      break;

    // EMBEDDED ELEMENTS
    case 'audio': // if 'controls' attribute is present
      accName = { name: 'NOT YET IMPLEMENTED', source: '' };
      break;

    case 'embed':
      accName = { name: 'NOT YET IMPLEMENTED', source: '' };
      break;

    case 'iframe':
      accName = nameFromAttribute(element, 'title');
      break;

    case 'img':
    case 'area': // added
      accName = nameFromAltAttribute(element);
      break;

    case 'object':
      accName = { name: 'NOT YET IMPLEMENTED', source: '' };
      break;

    case 'svg': // added
      accName = nameFromDescendant(element, 'title');
      break;

    case 'video': // if 'controls' attribute is present
      accName = { name: 'NOT YET IMPLEMENTED', source: '' };
      break;

    // OTHER ELEMENTS
    case 'a':
      accName = nameFromContents(element);
      break;

    case 'details':
      accName = nameFromDetailsOrSummary(element);
      break;

    case 'figure':
      accName = nameFromDescendant(element, 'figcaption');
      break;

    case 'table':
      accName = nameFromDescendant(element, 'caption');
      break;

    // ELEMENTS NOT SPECIFIED ABOVE
    default:
      if (nameFromIncludesContents(element) || recFlag)
        accName = nameFromContents(element);
      break;
  }

  // LAST RESORT USE TITLE
  if (accName === null) accName = nameFromAttribute(element, 'title');

  return accName;
}

/*
*   nameFromAttributeIdRefs: Get the value of attrName on element (a space-
*   separated list of IDREFs), visit each referenced element in the order it
*   appears in the list and obtain its accessible name (skipping recursive
*   aria-labelledby or aria-describedby calculations), and return an object
*   with name property set to a string that is a space-separated concatena-
*   tion of those results if any, otherwise return null.
*/
/* eslint no-console: 0 */
function nameFromAttributeIdRefs (element, attribute) {
  let value = getAttributeValue(element, attribute);
  console.log("Never got here...");
  let idRefs, i, refElement, accName, arr = [];

  if (value.length) {
    idRefs = value.split(' ');

    for (i = 0; i < idRefs.length; i++) {
      refElement = document.getElementById(idRefs[i]);
      if (refElement) {
        accName = getAccessibleName(refElement, true);
        if (accName && accName.name.length) arr.push(accName.name);
      }
    }
  }

  if (arr.length)
    return { name: arr.join(' '), source: attribute };

  return null;
}

/*
*   getAccessibleName: Use the ARIA Roles Model specification for accessible
*   name calculation based on its precedence order:
*   (1) Use aria-labelledby, unless a traversal is already underway;
*   (2) Use aria-label attribute value;
*   (3) Use whatever method is specified by the native semantics of the
*   element, which includes, as last resort, use of the title attribute.
*/
export function getAccessibleName (element, recFlag = false) {
  let accName = null;

  if (!recFlag) accName = nameFromAttributeIdRefs(element, 'aria-labelledby');
  if (accName === null) accName = nameFromAttribute(element, 'aria-label');
  if (accName === null) accName = nameFromNativeSemantics(element, recFlag);

  return accName;
}

/*
*   getAccessibleDesc: Use the ARIA Roles Model specification for accessible
*   description calculation based on its precedence order:
*   (1) Use aria-describedby, unless a traversal is already underway;
*   (2) As last resort, use the title attribute.
*/
export function getAccessibleDesc (element, recFlag = false) {
  let accDesc = null;

  if (!recFlag) accDesc = nameFromAttributeIdRefs(element, 'aria-describedby');
  if (accDesc === null) accDesc = nameFromAttribute(element, 'title');

  return accDesc;
}
<|endoftext|>


<commit_before><commit_msg>working on poses routes<commit_after>const express = require('express')
const router = express.Router()

/* GET users listing. */
router.get('/poses', function(req, res, next) {
  res.send('respond with a resource')
})

module.exports = router
<|endoftext|>


<commit_before>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 */

(function(window, document, undefined){
	'use strict';

	// list of dependencies
	var deps = [
		window.jQuery,
		window.Make,
		window.Masonry,
		window.query,
		Array.prototype.shuffle
	];

	// check for all dependencies, and abort if any are missing
	var missingDepsFlag = false;

	deps.forEach( function(dep) {
		if ( !dep ) {
			missingDepsFlag = true;
		}
	});

	if ( missingDepsFlag ) {
		return;
	}

	// init makeapi client
	var makeapi = new window.Make({
		apiURL: 'https://makeapi.webmaker.org'
	});

	// utilize jQuery
	var $ = window.jQuery;

	// reference to the quilt's container
	var $quiltContainer = $( '#quiltContainer' );
	// reference to the preview iframe
	var $makePreview = $( 'makePreview' );

	// init masonry
	$quiltContainer.masonry({
		itemSelector: '.quilt-msnry',
		columnWidth: 160,
		transitionDuration: 0.7
	});
	var masonry = $quiltContainer.data( 'masonry' );

	// set default options
	var config = {
		tags: [ 'supportopen', 'webwewant', 'millionmozillians' ],
		execution: 'or',
		limit: 100,
		duration: 7000
	};

	// get user config and convert any tags into array.
	var userConfig = window.query();
	if ( userConfig.tags ) {
		userConfig.tags = userConfig.tags.split(',');
	}

	// override config w/ userConfig were possible
	$.extend( true, config, userConfig );

	// set internal variables
	var numberOfMakes = 0;
	var pageNumber    = 1;
	var displayOrder  = [];
	var displayTimer  = null;

	/**
	 * get makes from the makeapi
	 *
	 * @param  {Integer}  page page number of results to fetch
	 * @param  {Function} done callback to run once search complete
	 */
	function getMakes( page, done ) {
		page = page || 1;
		makeapi
			.tags({
				tags: config.tags,
				execution: config.execution
			})
			.sortByField( 'createdAt', 'desc' )
			.limit( config.limit )
			.contentType( 'application/x-thimble' )
			.page( page )
			.then( function( err, makes ) {
				// check if search failed or not
				if ( err ) {
					console.log( err );
					return;
				}

				// check some makes were returned
				if ( makes.length === 0 ) {
					console.log( 'no makes found' );
					return;
				}

				// shuffle the order of the makes returned
				makes.shuffle();

				// reference to makes
				var $makes = $( '#quiltMakes' );

				// add each make to the DOM
				makes.forEach( function( make ) {
					var thumbnail = 'https://secure.gravatar.com/avatar/' + make.emailHash + '?s=200&d=' + make.thumbnail;

					var thumb = '
';
					thumb += '';
					thumb += '
';

					$makes.append( thumb );

					$quiltContainer.masonry( 'appended', $makes.children().last() );

					numberOfMakes++;
				});

				// up the number of makes found
				numberOfMakes += makes.length;

				// add new makes to the queue
				for( var i = numberOfMakes, j = numberOfMakes + makes.length; i < j; i++ ) {
					displayOrder[i] = i;
				}
				displayOrder.shuffle();

				// we're done w/ the async + dom manipulation
				if ( (numberOfMakes <= config.limit) && done ) {
					done();
				}
			});
	}

	/**
	 * load the next make into the preview iframe
	 */
	function showNextMake() {
		// get latest makes in DOM
		var $makes    = $( '#quiltMakes' );
		var selection = displayOrder.shift();

		displayOrder.push( selection );

		$makes.each( function() {
			$( this ).removeClass( 'active' );
		});

		$makes.eq( selection ).addClass( 'active' );

		$makePreview.attr( 'src', $makes.eq( selection ).data( 'make' ) + '_' );
	}

	// start display timer
	function startDisplayTimer() {
		clearInterval( displayTimer );
		displayTimer = setInterval( showNextMake, config.duration );
	}

	// run search and start showing makes
	getMakes( pageNumber, startDisplayTimer );

	// keep getting results till none left
	getMakes( ++pageNumber, function getNextMakes() {
		getMakes( ++pageNumber, getNextMakes );
	});

	// when a make is clicked load it into preview
	$( document ).on( 'click', '#quiltMakes li', function( e ){
		$makePreview.attr( 'src', $( this ).data( 'make' ) + '_' );

		// restart time so that this make gets full time
		startDisplayTimer();

		return false;
	});

	// handle page resizes better
	function setContainerWidth() {
		$quiltContainer.width( 160 * Math.floor( $quiltContainer.parent().width() / 160 ) );
	}
	setContainerWidth();
	$( window ).resize( setContainerWidth );

	// attempt to get more makes for infinite scroll
	$( window ).scroll( function( e ) {
		if ( $( window ).scrollTop() === $( document ).height() - $( window ).height() ) {
			getMakes( ++pageNumber, startDisplayTimer );
		}
	});
})(this, this.document);
<commit_msg>better infinite scroll<commit_after>/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 */

(function(window, document, undefined){
	'use strict';

	// list of dependencies
	var deps = [
		window.jQuery,
		window.Make,
		window.Masonry,
		window.query,
		Array.prototype.shuffle
	];

	// check for all dependencies, and abort if any are missing
	var missingDepsFlag = false;

	deps.forEach( function(dep) {
		if ( !dep ) {
			missingDepsFlag = true;
		}
	});

	if ( missingDepsFlag ) {
		return;
	}

	// init makeapi client
	var makeapi = new window.Make({
		apiURL: 'https://makeapi.webmaker.org'
	});

	// utilize jQuery
	var $ = window.jQuery;

	// reference to the quilt's container
	var $quiltContainer = $( '#quiltContainer' );
	// reference to the preview iframe
	var $makePreview = $( 'makePreview' );

	// init masonry
	$quiltContainer.masonry({
		itemSelector: '.quilt-msnry',
		columnWidth: 160,
		transitionDuration: 0.7
	});
	var masonry = $quiltContainer.data( 'masonry' );

	// set default options
	var config = {
		tags: [ 'supportopen', 'webwewant', 'millionmozillians' ],
		execution: 'or',
		limit: 100,
		duration: 7000
	};

	// get user config and convert any tags into array.
	var userConfig = window.query();
	if ( userConfig.tags ) {
		userConfig.tags = userConfig.tags.split(',');
	}

	// override config w/ userConfig were possible
	$.extend( true, config, userConfig );

	// set internal variables
	var numberOfMakes = 0;
	var pageNumber    = 1;
	var displayOrder  = [];
	var displayTimer  = null;

	/**
	 * get makes from the makeapi
	 *
	 * @param  {Integer}  page page number of results to fetch
	 * @param  {Function} done callback to run once search complete
	 */
	function getMakes( page, done ) {
		page = page || 1;
		makeapi
			.tags({
				tags: config.tags,
				execution: config.execution
			})
			.sortByField( 'createdAt', 'desc' )
			.limit( config.limit )
			.contentType( 'application/x-thimble' )
			.page( page )
			.then( function( err, makes ) {
				// check if search failed or not
				if ( err ) {
					console.log( err );
					return;
				}

				// check some makes were returned
				if ( makes.length === 0 ) {
					console.log( 'no makes found' );
					return;
				}

				// shuffle the order of the makes returned
				makes.shuffle();

				// reference to makes
				var $makes = $( '#quiltMakes' );

				// add each make to the DOM
				makes.forEach( function( make ) {
					var thumbnail = 'https://secure.gravatar.com/avatar/' + make.emailHash + '?s=200&d=' + make.thumbnail;

					var thumb = '
';
					thumb += '';
					thumb += '
';

					$makes.append( thumb );

					$quiltContainer.masonry( 'appended', $makes.children().last() );

					numberOfMakes++;
				});

				// up the number of makes found
				numberOfMakes += makes.length;

				// add new makes to the queue
				for( var i = numberOfMakes, j = numberOfMakes + makes.length; i < j; i++ ) {
					displayOrder[i] = i;
				}
				displayOrder.shuffle();

				// we're done w/ the async + dom manipulation
				if ( (numberOfMakes <= config.limit) && done ) {
					done();
				}
			});
	}

	/**
	 * load the next make into the preview iframe
	 */
	function showNextMake() {
		// get latest makes in DOM
		var $makes    = $( '#quiltMakes' );
		var selection = displayOrder.shift();

		displayOrder.push( selection );

		$makes.each( function() {
			$( this ).removeClass( 'active' );
		});

		$makes.eq( selection ).addClass( 'active' );

		$makePreview.attr( 'src', $makes.eq( selection ).data( 'make' ) + '_' );
	}

	// start display timer
	function startDisplayTimer() {
		clearInterval( displayTimer );
		displayTimer = setInterval( showNextMake, config.duration );
	}

	// run search and start showing makes
	getMakes( pageNumber, startDisplayTimer );

	// keep getting results till none left
	getMakes( ++pageNumber, function getNextMakes() {
		getMakes( ++pageNumber, getNextMakes );
	});

	// when a make is clicked load it into preview
	$( document ).on( 'click', '#quiltMakes li', function( e ){
		$makePreview.attr( 'src', $( this ).data( 'make' ) + '_' );

		// restart time so that this make gets full time
		startDisplayTimer();

		return false;
	});

	// handle page resizes better
	function setContainerWidth() {
		$quiltContainer.width( 160 * Math.floor( $quiltContainer.parent().width() / 160 ) );
	}
	setContainerWidth();
	$( window ).resize( setContainerWidth );

	// attempt to get more makes for infinite scroll
	$( window ).scroll( function( e ) {
		if ( $( window ).scrollTop() === $( document ).height() - $( window ).height() ) {
			getMakes( pageNumber + 1, function() {
				pageNumber++;
				startDisplayTimer
			});
		}
	});
})(this, this.document);
<|endoftext|>


<commit_before>
/*
 *
 */

dw.chart = function(attributes) {

    // private methods and properties
    var dataset,
        theme,
        visualization,
        metric_prefix,
        load_callbacks = $.Callbacks(),
        change_callbacks = $.Callbacks(),
        locale;

    // public interface
    var chart = {
        // returns an attribute
        get: function(key, _default) {
            var keys = key.split('.'),
                pt = attributes;

            _.each(keys, function(key) {
                if (pt === undefined) {
                    return _default;
                }
                pt = pt[key];
            });
            return _.isUndefined(pt) || _.isNull(pt) ? _default : pt;
        },

        set: function(key, value) {
            var keys = key.split('.'),
                lastKey = keys.pop(),
                pt = attributes;

            // resolve property until the parent dict
            _.each(keys, function(key) {
                if (_.isUndefined(pt[key])) {
                    pt[key] = {};
                }
                pt = pt[key];
            });

            // check if new value is set
            if (!_.isEqual(pt[lastKey], value)) {
                pt[lastKey] = value;
                change_callbacks.fire(chart, key, value);
            }
            return this;
        },

        // loads the dataset and returns a deferred
        load: function() {
            var datasource;

            datasource = dw.datasource.delimited({
                url: 'data',
                firstRowIsHeader: chart.get('metadata.data.horizontal-header', true),
                transpose: chart.get('metadata.data.transpose', false)
            });

            return datasource.dataset().done(function(ds) {
                dataset = ds;
                load_callbacks.fire(chart);
            });
        },

        loaded: function(callback) {
            if (dataset) {
                // run now
                callback(chart);
            } else {
                load_callbacks.add(callback);
            }
        },

        // applies the data changes and returns the dataset
        dataset: function(ds) {
            if (arguments.length) {
                dataset = ds;
                return chart;
            }
            var changes = chart.get('metadata.data.changes', []);
            var transpose = chart.get('metadata.data.transpose', false);
            _.each(changes, function(change) {
                var row = "row", column = "column";
                if (transpose) {
                    row = "column";
                    column = "row";
                }

                if (dataset.hasColumn(change[column])) {
                    if (change[row] === 0) {
                        dataset.column(change[column]).title(change.value);
                    }
                    else {
                        dataset.column(change[column]).raw(change[row] - 1, change.value);
                    }
                }
            });

            var columnFormats = chart.get('metadata.data.column-format', {});
            _.each(columnFormats, function(columnFormat, key) {
                if (columnFormat.type) {
                    if (dataset.hasColumn(key)) {
                        dataset.column(key).type(columnFormat.type);
                    }
                }
            });
            return dataset;
        },

        // sets or gets the theme
        theme: function(_theme) {
            if (arguments.length) {
                theme = _theme;
                return chart;
            }
            return theme;
        },

        // sets or gets the visualization
        vis: function(_vis) {
            if (arguments.length) {
                vis = _vis;
                vis.chart(chart);
                return chart;
            }
            return vis;
        },

        // returns true if the user has set any highlights
        hasHighlight: function() {
            var hl = chart.get('metadata.visualize.highlighted-series');
            return _.isArray(hl) && hl.length > 0;
        },

        isHighlighted: function(obj) {
            if (_.isUndefined(obj) === undefined) return false;
            var hl = this.get('metadata.visualize.highlighted-series'),
                obj_name = dw.utils.name(obj);
            return !_.isArray(hl) || hl.length === 0 || _.indexOf(hl, obj_name) >= 0;
        },

        locale: function(_locale) {
            if (arguments.length) {
                locale = _locale;
                Globalize.culture(locale);
                return chart;
            }
            return locale;
        },

        metricPrefix: function(_metric_prefix) {
            if (arguments.length) {
                metric_prefix = _metric_prefix;
                return chart;
            }
            return metric_prefix;
        },

        formatValue: function(val, full, round) {
            var format = chart.get('metadata.describe.number-format'),
                div = Number(chart.get('metadata.describe.number-divisor')),
                append = chart.get('metadata.describe.number-append', '').replace(' ', ' '),
                prepend = chart.get('metadata.describe.number-prepend', '').replace(' ', ' ');

            if (div !== 0) val = Number(val) / Math.pow(10, div);
            if (format != '-') {
                if (round || val == Math.round(val)) format = format.substr(0,1)+'0';
                val = Globalize.format(val, format);
            } else if (div !== 0) {
                val = val.toFixed(1);
            }
            return full ? prepend + val + append : val;
        },

        render: function(container) {
            if (!vis || !theme || !dataset) {
                throw 'cannot render the chart!';
            }
            vis.setChart(chart);
            vis.__init();
            vis.render($(container));
        },

        attributes: function(attrs) {
            if (arguments.length) {
                attributes = attrs;
                return chart;
            }
            return attributes;
        },

        onChange: change_callbacks.add,

        columnFormatter: function(column) {
            // pull output config from metadata
            // return column.formatter(config);
            var colFormat = chart.get('metadata.data.column-format', {});
            return column.type(true).formatter(colFormat[column.name()] || {});
        }

    };

    return chart;
};<commit_msg>updated chart to new vis api<commit_after>
/*
 *
 */

dw.chart = function(attributes) {

    // private methods and properties
    var dataset,
        theme,
        visualization,
        metric_prefix,
        load_callbacks = $.Callbacks(),
        change_callbacks = $.Callbacks(),
        locale;

    // public interface
    var chart = {
        // returns an attribute
        get: function(key, _default) {
            var keys = key.split('.'),
                pt = attributes;

            _.each(keys, function(key) {
                if (pt === undefined) {
                    return _default;
                }
                pt = pt[key];
            });
            return _.isUndefined(pt) || _.isNull(pt) ? _default : pt;
        },

        set: function(key, value) {
            var keys = key.split('.'),
                lastKey = keys.pop(),
                pt = attributes;

            // resolve property until the parent dict
            _.each(keys, function(key) {
                if (_.isUndefined(pt[key])) {
                    pt[key] = {};
                }
                pt = pt[key];
            });

            // check if new value is set
            if (!_.isEqual(pt[lastKey], value)) {
                pt[lastKey] = value;
                change_callbacks.fire(chart, key, value);
            }
            return this;
        },

        // loads the dataset and returns a deferred
        load: function() {
            var datasource;

            datasource = dw.datasource.delimited({
                url: 'data',
                firstRowIsHeader: chart.get('metadata.data.horizontal-header', true),
                transpose: chart.get('metadata.data.transpose', false)
            });

            return datasource.dataset().done(function(ds) {
                dataset = ds;
                load_callbacks.fire(chart);
            });
        },

        loaded: function(callback) {
            if (dataset) {
                // run now
                callback(chart);
            } else {
                load_callbacks.add(callback);
            }
        },

        // applies the data changes and returns the dataset
        dataset: function(ds) {
            if (arguments.length) {
                dataset = ds;
                return chart;
            }
            var changes = chart.get('metadata.data.changes', []);
            var transpose = chart.get('metadata.data.transpose', false);
            _.each(changes, function(change) {
                var row = "row", column = "column";
                if (transpose) {
                    row = "column";
                    column = "row";
                }

                if (dataset.hasColumn(change[column])) {
                    if (change[row] === 0) {
                        dataset.column(change[column]).title(change.value);
                    }
                    else {
                        dataset.column(change[column]).raw(change[row] - 1, change.value);
                    }
                }
            });

            var columnFormats = chart.get('metadata.data.column-format', {});
            _.each(columnFormats, function(columnFormat, key) {
                if (columnFormat.type) {
                    if (dataset.hasColumn(key)) {
                        dataset.column(key).type(columnFormat.type);
                    }
                }
            });
            return dataset;
        },

        // sets or gets the theme
        theme: function(_theme) {
            if (arguments.length) {
                theme = _theme;
                return chart;
            }
            return theme;
        },

        // sets or gets the visualization
        vis: function(_vis) {
            if (arguments.length) {
                vis = _vis;
                vis.chart(chart);
                return chart;
            }
            return vis;
        },

        // returns true if the user has set any highlights
        hasHighlight: function() {
            var hl = chart.get('metadata.visualize.highlighted-series');
            return _.isArray(hl) && hl.length > 0;
        },

        isHighlighted: function(obj) {
            if (_.isUndefined(obj) === undefined) return false;
            var hl = this.get('metadata.visualize.highlighted-series'),
                obj_name = dw.utils.name(obj);
            return !_.isArray(hl) || hl.length === 0 || _.indexOf(hl, obj_name) >= 0;
        },

        locale: function(_locale) {
            if (arguments.length) {
                locale = _locale;
                Globalize.culture(locale);
                return chart;
            }
            return locale;
        },

        metricPrefix: function(_metric_prefix) {
            if (arguments.length) {
                metric_prefix = _metric_prefix;
                return chart;
            }
            return metric_prefix;
        },

        formatValue: function(val, full, round) {
            var format = chart.get('metadata.describe.number-format'),
                div = Number(chart.get('metadata.describe.number-divisor')),
                append = chart.get('metadata.describe.number-append', '').replace(' ', ' '),
                prepend = chart.get('metadata.describe.number-prepend', '').replace(' ', ' ');

            if (div !== 0) val = Number(val) / Math.pow(10, div);
            if (format != '-') {
                if (round || val == Math.round(val)) format = format.substr(0,1)+'0';
                val = Globalize.format(val, format);
            } else if (div !== 0) {
                val = val.toFixed(1);
            }
            return full ? prepend + val + append : val;
        },

        render: function(container) {
            if (!vis || !theme || !dataset) {
                throw 'cannot render the chart!';
            }
            vis.chart(chart);
            vis.__init();
            vis.render($(container));
        },

        attributes: function(attrs) {
            if (arguments.length) {
                attributes = attrs;
                return chart;
            }
            return attributes;
        },

        onChange: change_callbacks.add,

        columnFormatter: function(column) {
            // pull output config from metadata
            // return column.formatter(config);
            var colFormat = chart.get('metadata.data.column-format', {});
            return column.type(true).formatter(colFormat[column.name()] || {});
        }

    };

    return chart;
};<|endoftext|>


<commit_before>(function(cloudStack, testData) {
  cloudStack.sections.events = {
    title: 'Events',
    id: 'events',
    sectionSelect: {
      preFilter: function(args) {
        if(isAdmin())
          return ["events", "alerts"];
        else
          return ["events"];
      },
      label: 'Select view'
    },
    sections: {
      events: {
        type: 'select',
        title: 'Events',
        listView: {
          id: 'events',
          label: 'Events',
          fields: {
            type: { label: 'Type' },
            description: { label: 'Description' },
            username: { label: 'Initiated By' },
            created: { label: 'Date', converter: cloudStack.converters.toLocalDate }
          },
          dataProvider: function(args) {
            $.ajax({
              url: createURL("listEvents&page="+args.page+"&pagesize="+pageSize),
              dataType: "json",
              async: true,
              success: function(json) {
                var items = json.listeventsresponse.event;
                args.response.success({data:items});
              }
            });
          },
					detailView: {
            name: 'Event details',
            tabs: {
              details: {
                title: 'Details',
                fields: [
                  {
                    type: { label: 'Type' },
                    description: { label: 'Description' },
                    created: { label: 'Date', converter: cloudStack.converters.toLocalDate }
                  }
                ],
                dataProvider: function(args) {
								  args.response.success({data: args.context.events[0]});
								}
              }
            }
          }
        }
      },
      alerts: {
        type: 'select',
        title: 'Alerts',
        listView: {
          id: 'alerts',
          label: 'Alerts',
          fields: {
            description: { label: 'Description' },
            sent: { label: 'Date', converter: cloudStack.converters.toLocalDate }
          },
          dataProvider: function(args) {
            $.ajax({
              url: createURL("listAlerts&page="+args.page+"&pagesize="+pageSize),
              dataType: "json",
              async: true,
              success: function(json) {
                var items = json.listalertsresponse.alert;
                args.response.success({data:items});
              }
            });
          },
          detailView: {
            name: 'Alert details',
            tabs: {
              details: {
                title: 'Details',
                fields: [
                  {
                    id: { label: 'ID' },
                    description: { label: 'Description' },
                    sent: { label: 'Date', converter: cloudStack.converters.toLocalDate }
                  }
                ],
                dataProvider: function(args) {
								  args.response.success({data: args.context.alerts[0]});
								}
              }
            }
          }
        }
      }
    }
  };
})(cloudStack, testData);
<commit_msg>cloudstack 3.0 new UI - event page, alert page - implement search.<commit_after>(function(cloudStack, testData) {
  cloudStack.sections.events = {
    title: 'Events',
    id: 'events',
    sectionSelect: {
      preFilter: function(args) {
        if(isAdmin())
          return ["events", "alerts"];
        else
          return ["events"];
      },
      label: 'Select view'
    },
    sections: {
      events: {
        type: 'select',
        title: 'Events',
        listView: {
          id: 'events',
          label: 'Events',
          fields: {
            type: { label: 'Type' },
            description: { label: 'Description' },
            username: { label: 'Initiated By' },
            created: { label: 'Date', converter: cloudStack.converters.toLocalDate }
          },
          dataProvider: function(args) {
						var array1 = [];
						if(args.filterBy != null) {
							if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) {
								switch(args.filterBy.search.by) {
								case "name":
									if(args.filterBy.search.value.length > 0)
										array1.push("&keyword=" + args.filterBy.search.value);
									break;
								}
							}
						}

            $.ajax({
              url: createURL("listEvents&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
              dataType: "json",
              async: true,
              success: function(json) {
                var items = json.listeventsresponse.event;
                args.response.success({data:items});
              }
            });
          },
					detailView: {
            name: 'Event details',
            tabs: {
              details: {
                title: 'Details',
                fields: [
                  {
                    type: { label: 'Type' },
                    description: { label: 'Description' },
                    created: { label: 'Date', converter: cloudStack.converters.toLocalDate }
                  }
                ],
                dataProvider: function(args) {
								  args.response.success({data: args.context.events[0]});
								}
              }
            }
          }
        }
      },
      alerts: {
        type: 'select',
        title: 'Alerts',
        listView: {
          id: 'alerts',
          label: 'Alerts',
          fields: {
            description: { label: 'Description' },
            sent: { label: 'Date', converter: cloudStack.converters.toLocalDate }
          },
          dataProvider: function(args) {
					  var array1 = [];
						if(args.filterBy != null) {
							if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) {
								switch(args.filterBy.search.by) {
								case "name":
									if(args.filterBy.search.value.length > 0)
										array1.push("&keyword=" + args.filterBy.search.value);
									break;
								}
							}
						}
            $.ajax({
              url: createURL("listAlerts&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
              dataType: "json",
              async: true,
              success: function(json) {
                var items = json.listalertsresponse.alert;
                args.response.success({data:items});
              }
            });
          },
          detailView: {
            name: 'Alert details',
            tabs: {
              details: {
                title: 'Details',
                fields: [
                  {
                    id: { label: 'ID' },
                    description: { label: 'Description' },
                    sent: { label: 'Date', converter: cloudStack.converters.toLocalDate }
                  }
                ],
                dataProvider: function(args) {
								  args.response.success({data: args.context.alerts[0]});
								}
              }
            }
          }
        }
      }
    }
  };
})(cloudStack, testData);
<|endoftext|>