<commit_before>// Bola (JS Object)
var bola = {
	raio: 15,
	x: null,
	y: null,
	baixo: false,
	angulo: null,
	velocidade: null,
	resetX : null,
	resetY : null,
	countFail : null,
	pontuacao : null,
	randomInit : [-1, 1],
	imagem: null,
	somColisaoBloco: null,

	init : function(width, y){//largura do canvas e y do jogador
		bola.resetX = width / 2;
		bola.resetY = y - 2 * bola.raio;
		bola.countFail = 0;
		bola.pontuacao = 0;
		bola.imagem = new Image();
		bola.imagem.src = "assets/bola1.png";
		bola.somColisaoBloco = document.getElementById('colisao');
		bola.clear();
	},
	render : function(root){

		root.drawImage(bola.imagem, bola.x , bola.y);
		//root.fillStyle = "red";
		//root.beginPath();
		//root.arc(bola.x, bola.y, bola.raio, 0, Math.PI*2, true);
		//root.closePath();
		//root.fill();
	},
	atualizar : function(y, x, w, width, height, polling){
		// Movimentar a bola
		if(bola.baixo){
			bola.colisaoJogador(y, x, w);
			bola.y += bola.velocidade;
		}
		else {
			bola.y -= bola.velocidade;
		}
		// Colisao paredes
		//if(bola.x - bola.raio <= 0 || bola.x + bola.raio >= width){
		if(bola.x <= 0 || bola.x + 2* bola.raio >= width){
			bola.angulo *= -1;
		}
		//Colisao bloco
		bola.colisaoBloco(polling);

		//Colisao chao
		bola.colisaoChao(height, polling);
		//Altera o angulo da bola
		bola.x += bola.angulo;
	},
	clear : function()
	{
		bola.x = bola.resetX;
		bola.y = bola.resetY;
		bola.baixo = false;
		bola.angulo = 5 * bola.randomInit[Math.round(Math.random() * 1)]; // Random inicio da partida
		bola.velocidade = 5;
	},
	colisaoJogador : function(y, x, w){
		// Colisao jogador
	//if((bola.y + bola.raio >= y) &&
		if((bola.y + 2* bola.raio >= y) &&
			(bola.x >= x) &&
			(bola.x <= x + w)){
			bola.baixo = false;
		//	console.log("Colisao jogador");
		}
	},
	colisaoBloco : function(polling){
		//Colisao bloco
		if(bola.y - bola.raio <= (bloco.h * bloco.numLinhas) + bloco.h * 2 && bola.y >= 0){
			var linha  = Math.floor(((bola.y) - bloco.h) / bloco.h) - 2;
			var coluna = Math.floor((bola.x) / bloco.w);
			console.log("linha: " + linha + "coluna:" + coluna);

			if(coluna >= 0 && linha >= 0){
				if(bloco.blocos[linha][coluna] == 0){
					bola.somColisaoBloco.play();
					bola.baixo = !bola.baixo;
					bloco.blocos[linha][coluna] = 1;
					bola.pontuacao++;

					if(bola.pontuacao == bloco.numLinhas * bloco.numColunas){
						bola.clear(); // A bola retorna a posicao inicial
						jogador.clear(); // O jogador retorna a posicao inicial
						jogador.vitoria = true;
						clearInterval(polling);
					}
				}
				console.log("Colisao bloco");
			}else{
				bola.baixo = !bola.baixo;
			}
		}
	},
	colisaoChao : function(height, polling){
		//Colisao chao
//		if(bola.y + bola.raio >= height){
		if(bola.y - bola.raio >= height){
			bola.baixo = !bola.baixo;
			console.log("Colisao chao");
			bola.clear(); // A bola retorna a posicao inicial
			jogador.clear(); // O jogador retorna a posicao inicial
			jogador.vidas--;
			console.log(bola.countFail);
			if(jogador.vidas == 0){
				jogador.derrota = true;
				clearInterval(polling);
			}
		}
	}
};<commit_msg>ajuste do tamanho do canvas para evitar barra de rolagem no browser<commit_after>// Bola (JS Object)
var bola = {
	raio: 15,
	x: null,
	y: null,
	baixo: false,
	angulo: null,
	velocidade: null,
	resetX : null,
	resetY : null,
	countFail : null,
	pontuacao : null,
	randomInit : [-1, 1],
	imagem: null,
	somColisaoBloco: null,

	init : function(width, y){// largura do canvas e y do jogador
		bola.resetX = width / 2;
		bola.resetY = y - 2 * bola.raio;
		bola.countFail = 0;
		bola.pontuacao = 0;
		bola.imagem = new Image();
		bola.imagem.src = "assets/bola1.png";
		bola.somColisaoBloco = document.getElementById('colisao');
		bola.clear();
	},
	render : function(root){

		root.drawImage(bola.imagem, bola.x , bola.y);

		//root.fillStyle = "red";
		//root.beginPath();
		//root.arc(bola.x, bola.y, bola.raio, 0, Math.PI*2, true);
		//root.closePath();
		//root.fill();
	},
	atualizar : function(y, x, w, width, height, polling){
		// Movimentar a bola
		if(bola.baixo){
			bola.colisaoJogador(y, x, w);
			bola.y += bola.velocidade;
		}
		else {
			bola.y -= bola.velocidade;
		}
		// Colisao paredes
		//if(bola.x - bola.raio <= 0 || bola.x + bola.raio >= width){
		if(bola.x <= 0 || bola.x + 2* bola.raio >= width){
			bola.angulo *= -1;
		}
		//Colisao bloco
		bola.colisaoBloco(polling);

		//Colisao chao
		bola.colisaoChao(height, polling);
		//Altera o angulo da bola
		bola.x += bola.angulo;
	},
	clear : function()
	{
		bola.x = bola.resetX;
		bola.y = bola.resetY;
		bola.baixo = false;
		bola.angulo = 5 * bola.randomInit[Math.round(Math.random() * 1)]; // Random inicio da partida
		bola.velocidade = 5;
	},
	colisaoJogador : function(y, x, w){
		// Colisao jogador
	//if((bola.y + bola.raio >= y) &&
		if((bola.y + 2* bola.raio >= y) &&
			(bola.x >= x) &&
			(bola.x <= x + w)){
			bola.baixo = false;
		//	console.log("Colisao jogador");
		}
	},
	colisaoBloco : function(polling){
		//Colisao bloco
		if(bola.y - bola.raio <= (bloco.h * bloco.numLinhas) + bloco.h * 2 && bola.y >= 0){
			var linha  = Math.floor(((bola.y) - bloco.h) / bloco.h) - 2;
			var coluna = Math.floor((bola.x) / bloco.w);
			console.log("linha: " + linha + "coluna:" + coluna);

			if(coluna >= 0 && linha >= 0){
				if(bloco.blocos[linha][coluna] == 0){
					bola.somColisaoBloco.play();
					bola.baixo = !bola.baixo;
					bloco.blocos[linha][coluna] = 1;
					bola.pontuacao++;

					if(bola.pontuacao == bloco.numLinhas * bloco.numColunas){
						bola.clear(); // A bola retorna a posicao inicial
						jogador.clear(); // O jogador retorna a posicao inicial
						jogador.vitoria = true;
						clearInterval(polling);
					}
				}
				console.log("Colisao bloco");
			}else{
				bola.baixo = !bola.baixo;
			}
		}
	},
	colisaoChao : function(height, polling){
		//Colisao chao
//		if(bola.y + bola.raio >= height){
		if(bola.y - bola.raio >= height){
			bola.baixo = !bola.baixo;
			console.log("Colisao chao");
			bola.clear(); // A bola retorna a posicao inicial
			jogador.clear(); // O jogador retorna a posicao inicial
			jogador.vidas--;
			console.log(bola.countFail);
			if(jogador.vidas == 0){
				jogador.derrota = true;
				clearInterval(polling);
			}
		}
	}
};<|endoftext|>


<commit_before>// adapted from https://gist.github.com/magican/5574556

define(["require", "jquery", "base/js/namespace"], function (require, $, IPython) {
  "use strict";

  var make_link = function (h) {
    var a = $("");
    a.attr("href", '#' + h.attr('id'));
    var hclone = h.clone();
    // last() is the |P anchor which lights up when you hoover over the headline
    hclone.children().last().remove();
    a.text(hclone.text());
    return a;
  };

  var ol_depth = function (element) {
    // get depth of nested ol
    var d = 0;
    while (element.prop("tagName").toLowerCase() == 'ol') {
      d += 1;
      element = element.parent();
    }
    return d;
  };

  var create_toc_div = function () {
    var toc_wrapper = $('
')
    .append(
      $("
")
      .addClass("header")
      .text("Contents ")
      .click( function(){
        $('#toc').slideToggle();
        $('#toc-wrapper').toggleClass('closed');
        if ($('#toc-wrapper').hasClass('closed')){
          $('#toc-wrapper .hide-btn')
          .text('[+]')
          .attr('title', 'Show ToC');
        } else {
          $('#toc-wrapper .hide-btn')
          .text('[-]')
          .attr('title', 'Hide ToC');
        }
        return false;
      }).append(
        $("")
        .attr("href", "#")
        .addClass("hide-btn")
        .attr('title', 'Hide ToC')
        .text("[-]")
      ).append(
        $("")
        .attr("href", "#")
        .addClass("reload-btn")
        .text("  \u21BB")
        .attr('title', 'Reload ToC')
        .click( function(){
          table_of_contents();
          return false;
        })
      )
    ).append(
        $("
").attr("id", "toc")
    );
    $("body").append(toc_wrapper);
  };

  var table_of_contents = function (threshold) {
    if (threshold === undefined) {
      threshold = 4;
    }
    var toc_wrapper = $("#toc-wrapper");
    if (toc_wrapper.length === 0) {
      create_toc_div();
    }

    var ol = $("
");
    ol.addClass("toc-item");
    $("#toc").empty().append(ol);

    $("#notebook").find(":header").map(function (i, h) {
      var level = parseInt(h.tagName.slice(1), 10);
      // skip below threshold
      if (level > threshold) return;
      // skip headings with no ID to link to
      if (!h.id) return;

      var depth = ol_depth(ol);

      // walk down levels
      for (; depth < level; depth++) {
        var new_ol = $("
");
        new_ol.addClass("toc-item");
        ol.append(new_ol);
        ol = new_ol;
      }
      // walk up levels
      for (; depth > level; depth--) {
        ol = ol.parent();
      }
      //
      ol.append(
        $("
").append(make_link($(h)))
      );
    });

    $(window).resize(function(){
      $('#toc').css({maxHeight: $(window).height() - 200});
    });

    $(window).trigger('resize');
  };

  var toggle_toc = function () {
    // toggle draw (first because of first-click behavior)
    $("#toc-wrapper").toggle();
    // recompute:
    table_of_contents();
  };

  var toc_button = function () {
    if (!IPython.toolbar) {
      $([IPython.events]).on("app_initialized.NotebookApp", toc_button);
      return;
    }
    if ($("#toc_button").length === 0) {
      IPython.toolbar.add_buttons_group([
        {
          'label'   : 'Table of Contents',
          'icon'    : 'fa-list',
          'callback': toggle_toc,
          'id'      : 'toc_button'
        }
      ]);
    }
  };

  var load_css = function () {
    var link = document.createElement("link");
    link.type = "text/css";
    link.rel = "stylesheet";
    link.href = require.toUrl("./main.css");
    document.getElementsByTagName("head")[0].appendChild(link);
  };

  var load_ipython_extension = function () {
    load_css();
    toc_button();
    // $([IPython.events]).on("notebook_loaded.Notebook", table_of_contents);
    $([IPython.events]).on("notebook_saved.Notebook", table_of_contents);
    $([IPython.events]).on("rendered.MarkdownCell", table_of_contents);
  };

  return {
    load_ipython_extension : load_ipython_extension,
    toggle_toc : toggle_toc,
    table_of_contents : table_of_contents
  };
});
<commit_msg>Make it useable with math environments<commit_after>// adapted from https://gist.github.com/magican/5574556

define(["require", "jquery", "base/js/namespace"], function (require, $, IPython) {
  "use strict";

  var make_link = function (h) {
    var a = $("");
    a.attr("href", '#' + h.attr('id'));
    var hclone = h.clone();
    // last() is the |P anchor which lights up when you hoover over the headline
    hclone.children().last().remove();
    a.html(hclone.html());
    return a;
  };

  var ol_depth = function (element) {
    // get depth of nested ol
    var d = 0;
    while (element.prop("tagName").toLowerCase() == 'ol') {
      d += 1;
      element = element.parent();
    }
    return d;
  };

  var create_toc_div = function () {
    var toc_wrapper = $('
')
    .append(
      $("
")
      .addClass("header")
      .text("Contents ")
      .click( function(){
        $('#toc').slideToggle();
        $('#toc-wrapper').toggleClass('closed');
        if ($('#toc-wrapper').hasClass('closed')){
          $('#toc-wrapper .hide-btn')
          .text('[+]')
          .attr('title', 'Show ToC');
        } else {
          $('#toc-wrapper .hide-btn')
          .text('[-]')
          .attr('title', 'Hide ToC');
        }
        return false;
      }).append(
        $("")
        .attr("href", "#")
        .addClass("hide-btn")
        .attr('title', 'Hide ToC')
        .text("[-]")
      ).append(
        $("")
        .attr("href", "#")
        .addClass("reload-btn")
        .text("  \u21BB")
        .attr('title', 'Reload ToC')
        .click( function(){
          table_of_contents();
          return false;
        })
      )
    ).append(
        $("
").attr("id", "toc")
    );
    $("body").append(toc_wrapper);
  };

  var table_of_contents = function (threshold) {
    if (threshold === undefined) {
      threshold = 4;
    }
    var toc_wrapper = $("#toc-wrapper");
    if (toc_wrapper.length === 0) {
      create_toc_div();
    }

    var ol = $("
");
    ol.addClass("toc-item");
    $("#toc").empty().append(ol);

    $("#notebook").find(":header").map(function (i, h) {
      var level = parseInt(h.tagName.slice(1), 10);
      // skip below threshold
      if (level > threshold) return;
      // skip headings with no ID to link to
      if (!h.id) return;

      var depth = ol_depth(ol);

      // walk down levels
      for (; depth < level; depth++) {
        var new_ol = $("
");
        new_ol.addClass("toc-item");
        ol.append(new_ol);
        ol = new_ol;
      }
      // walk up levels
      for (; depth > level; depth--) {
        ol = ol.parent();
      }
      //
      ol.append(
        $("
").append(make_link($(h)))
      );
    });

    $(window).resize(function(){
      $('#toc').css({maxHeight: $(window).height() - 200});
    });

    $(window).trigger('resize');
  };

  var toggle_toc = function () {
    // toggle draw (first because of first-click behavior)
    $("#toc-wrapper").toggle();
    // recompute:
    table_of_contents();
  };

  var toc_button = function () {
    if (!IPython.toolbar) {
      $([IPython.events]).on("app_initialized.NotebookApp", toc_button);
      return;
    }
    if ($("#toc_button").length === 0) {
      IPython.toolbar.add_buttons_group([
        {
          'label'   : 'Table of Contents',
          'icon'    : 'fa-list',
          'callback': toggle_toc,
          'id'      : 'toc_button'
        }
      ]);
    }
  };

  var load_css = function () {
    var link = document.createElement("link");
    link.type = "text/css";
    link.rel = "stylesheet";
    link.href = require.toUrl("./main.css");
    document.getElementsByTagName("head")[0].appendChild(link);
  };

  var load_ipython_extension = function () {
    load_css();
    toc_button();
    // $([IPython.events]).on("notebook_loaded.Notebook", table_of_contents);
    $([IPython.events]).on("notebook_saved.Notebook", table_of_contents);
    $([IPython.events]).on("rendered.MarkdownCell", table_of_contents);
  };

  return {
    load_ipython_extension : load_ipython_extension,
    toggle_toc : toggle_toc,
    table_of_contents : table_of_contents
  };
});
<|endoftext|>


<commit_before>export const BITWAVE_EMBED_URL = 'https://bitwave.tv/odysee';
export const BITWAVE_LIVE_API = 'https://api.live.odysee.com/v1/odysee/live';
export const BITWAVE_REPLAY_API = 'https://api.live.odysee.com/v1/replays/odysee';
<commit_msg>embed<commit_after>export const BITWAVE_EMBED_URL = 'https://liveplayer.odysee.com/odysee';
export const BITWAVE_LIVE_API = 'https://api.live.odysee.com/v1/odysee/live';
export const BITWAVE_REPLAY_API = 'https://api.live.odysee.com/v1/replays/odysee';
<|endoftext|>


<commit_before>import {
  messages,
  ruleName,
} from ".."
import rules from "../../../rules"
import { testRule } from "../../../testUtils"

const rule = rules[ruleName]

testRule(rule, {
  ruleName,
  config: [true],
  skipBasicChecks: true,

  accept: [ {
    code: "",
  }, {
    code: "@import \"foo.css\";",
  }, {
    code: "#foo {}",
  }, {
    code: ".foo {}",
  }, {
    code: "[foo] {}",
  }, {
    code: ".foo { & {} }",
  }, {
    code: ".foo { &.bar {} }",
  }, {
    code: ".foo { &-bar {} }",
  }, {
    code: ".foo { &__bar {} }",
  }, {
    code: ".foo { [&] {} }",
  }, {
    code: ".foo { & [class*=bar] {} }",
  }, {
    code: ".foo { @nest & {} }",
  }, {
    code: ".foo:nth-child(3n + 1) {}",
  }, {
    code: ".foo:nth-child(n) {}",
  }, {
    code: ".foo:nth-child(odd) {}",
  }, {
    code: ".foo:nth-child(even) {}",
  }, {
    code: ".foo:nth-child(-n) {}",
  }, {
    code: ".foo { &:nth-child(3n + 1) {} }",
  }, {
    code: "@keyframes spin { 0% {} }",
  }, {
    code: "@keyframes spin { to {} from {} }",
  }, {
    code: "@include keyframes(identifier) { to, 50.0% {} 50.01% {} 100% {} }",
    description: "non-standard usage of keyframe selectors",
  }, {
    code: ":root { --custom-property-set: {} }",
  } ],

  reject: [ {
    code: "foo {}",
    message: messages.rejected,
    line: 1,
    column: 1,
  }, {
    code: ".bar > foo {}",
    message: messages.rejected,
    line: 1,
    column: 8,
  }, {
    code: "foo.bar {}",
    message: messages.rejected,
    line: 1,
    column: 1,
  }, {
    code: ".foo, .bar, foo.baz {}",
    message: messages.rejected,
    line: 1,
    column: 13,
  }, {
    code: ".foo { div {} }",
    description: "nested descendant",
    message: messages.rejected,
    line: 1,
    column: 8,
  } ],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: ["descendant"] } ],
  skipBasicChecks: true,

  accept: [ {
    code: ".foo div {}",
  }, {
    code: ".foo > div {}",
  }, {
    code: ".foo + div {}",
  }, {
    code: "#bar div.foo {}",
    description: "compounded and descendant",
  }, {
    code: ".foo { div {} }",
    description: "nested descendant",
  } ],

  reject: [ {
    code: "div {}",
    message: messages.rejected,
  }, {
    code: ".foo, div {}",
    message: messages.rejected,
  }, {
    code: "div.foo {}",
    message: messages.rejected,
  } ],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: ["compounded"] } ],
  skipBasicChecks: true,

  accept: [ {
    code: "div.foo {}",
  }, {
    code: "div#foo {}",
  }, {
    code: "div[something] {}",
  }, {
    code: "#bar div.foo {}",
    description: "compounded and descendant",
  } ],

  reject: [ {
    code: "div {}",
    message: messages.rejected,
  }, {
    code: ".foo, div {}",
    message: messages.rejected,
  }, {
    code: ".foo div {}",
    message: messages.rejected,
  } ],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: [ "compounded", "descendant" ] } ],
  skipBasicChecks: true,

  accept: [{
    code: "#bar div.foo {}",
    description: "compounded and descendant",
  }],
})

testRule(rule, {
  ruleName,
  config: [true],
  skipBasicChecks: true,
  syntax: "scss",

  accept: [
    { code: "// Comment\n.c {}" },
  ],

  reject: [{
    code: "@for $n from 1 through 5 { .foo-#{$n} { div { content: \"#{$n}\"; } } }",
    description: "ignore sass interpolation inside @for for nested descendant",
    line: 1,
    column: 41,
  }],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: ["descendant"] } ],
  skipBasicChecks: true,
  syntax: "scss",

  accept: [{
    code: "@for $n from 1 through 5 { .foo-#{$n} { div { content: \"#{$n}\"; } } }",
    description: "ignore sass interpolation inside @for for nested descendant",
  }],
})

testRule(rule, {
  ruleName,
  config: [true],
  skipBasicChecks: true,
  syntax: "less",

  accept: [
    { code: "// Comment\n.c {}" },
  ],

  reject: [{
    code: ".for(@n: 1) when (@n <= 5) { .foo-@{n} { div { content: \"@{n}\"; } } .for (@n + 1); }",
    description: "ignore less interpolation inside @for for nested descendant",
    line: 1,
    column: 42,
  }],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: ["descendant"] } ],
  skipBasicChecks: true,
  syntax: "less",

  accept: [{
    code: ".for(@n: 1) when (@n <= 5) { .foo-@{n} { div { content: \"@{n}\"; } } .for (@n + 1); }",
    description: "ignore less interpolation inside @for for nested descendant",
  }],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignoreTypes: ["fieldset"] } ],
  skipBasicChecks: true,

  accept: [{
    code: "fieldset .a-button { color: pink; }",
  }],
})
<commit_msg>Improve ignoreTypes test in selector-no-type<commit_after>import {
  messages,
  ruleName,
} from ".."
import rules from "../../../rules"
import { testRule } from "../../../testUtils"

const rule = rules[ruleName]

testRule(rule, {
  ruleName,
  config: [true],
  skipBasicChecks: true,

  accept: [ {
    code: "",
  }, {
    code: "@import \"foo.css\";",
  }, {
    code: "#foo {}",
  }, {
    code: ".foo {}",
  }, {
    code: "[foo] {}",
  }, {
    code: ".foo { & {} }",
  }, {
    code: ".foo { &.bar {} }",
  }, {
    code: ".foo { &-bar {} }",
  }, {
    code: ".foo { &__bar {} }",
  }, {
    code: ".foo { [&] {} }",
  }, {
    code: ".foo { & [class*=bar] {} }",
  }, {
    code: ".foo { @nest & {} }",
  }, {
    code: ".foo:nth-child(3n + 1) {}",
  }, {
    code: ".foo:nth-child(n) {}",
  }, {
    code: ".foo:nth-child(odd) {}",
  }, {
    code: ".foo:nth-child(even) {}",
  }, {
    code: ".foo:nth-child(-n) {}",
  }, {
    code: ".foo { &:nth-child(3n + 1) {} }",
  }, {
    code: "@keyframes spin { 0% {} }",
  }, {
    code: "@keyframes spin { to {} from {} }",
  }, {
    code: "@include keyframes(identifier) { to, 50.0% {} 50.01% {} 100% {} }",
    description: "non-standard usage of keyframe selectors",
  }, {
    code: ":root { --custom-property-set: {} }",
  } ],

  reject: [ {
    code: "foo {}",
    message: messages.rejected,
    line: 1,
    column: 1,
  }, {
    code: ".bar > foo {}",
    message: messages.rejected,
    line: 1,
    column: 8,
  }, {
    code: "foo.bar {}",
    message: messages.rejected,
    line: 1,
    column: 1,
  }, {
    code: ".foo, .bar, foo.baz {}",
    message: messages.rejected,
    line: 1,
    column: 13,
  }, {
    code: ".foo { div {} }",
    description: "nested descendant",
    message: messages.rejected,
    line: 1,
    column: 8,
  } ],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: ["descendant"] } ],
  skipBasicChecks: true,

  accept: [ {
    code: ".foo div {}",
  }, {
    code: ".foo > div {}",
  }, {
    code: ".foo + div {}",
  }, {
    code: "#bar div.foo {}",
    description: "compounded and descendant",
  }, {
    code: ".foo { div {} }",
    description: "nested descendant",
  } ],

  reject: [ {
    code: "div {}",
    message: messages.rejected,
  }, {
    code: ".foo, div {}",
    message: messages.rejected,
  }, {
    code: "div.foo {}",
    message: messages.rejected,
  } ],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: ["compounded"] } ],
  skipBasicChecks: true,

  accept: [ {
    code: "div.foo {}",
  }, {
    code: "div#foo {}",
  }, {
    code: "div[something] {}",
  }, {
    code: "#bar div.foo {}",
    description: "compounded and descendant",
  } ],

  reject: [ {
    code: "div {}",
    message: messages.rejected,
  }, {
    code: ".foo, div {}",
    message: messages.rejected,
  }, {
    code: ".foo div {}",
    message: messages.rejected,
  } ],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: [ "compounded", "descendant" ] } ],
  skipBasicChecks: true,

  accept: [{
    code: "#bar div.foo {}",
    description: "compounded and descendant",
  }],
})

testRule(rule, {
  ruleName,
  config: [true],
  skipBasicChecks: true,
  syntax: "scss",

  accept: [
    { code: "// Comment\n.c {}" },
  ],

  reject: [{
    code: "@for $n from 1 through 5 { .foo-#{$n} { div { content: \"#{$n}\"; } } }",
    description: "ignore sass interpolation inside @for for nested descendant",
    line: 1,
    column: 41,
  }],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: ["descendant"] } ],
  skipBasicChecks: true,
  syntax: "scss",

  accept: [{
    code: "@for $n from 1 through 5 { .foo-#{$n} { div { content: \"#{$n}\"; } } }",
    description: "ignore sass interpolation inside @for for nested descendant",
  }],
})

testRule(rule, {
  ruleName,
  config: [true],
  skipBasicChecks: true,
  syntax: "less",

  accept: [
    { code: "// Comment\n.c {}" },
  ],

  reject: [{
    code: ".for(@n: 1) when (@n <= 5) { .foo-@{n} { div { content: \"@{n}\"; } } .for (@n + 1); }",
    description: "ignore less interpolation inside @for for nested descendant",
    line: 1,
    column: 42,
  }],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignore: ["descendant"] } ],
  skipBasicChecks: true,
  syntax: "less",

  accept: [{
    code: ".for(@n: 1) when (@n <= 5) { .foo-@{n} { div { content: \"@{n}\"; } } .for (@n + 1); }",
    description: "ignore less interpolation inside @for for nested descendant",
  }],
})

testRule(rule, {
  ruleName,
  config: [ true, { ignoreTypes: [ "fieldset", "/^my-/" ] } ],
  skipBasicChecks: true,

  accept: [ {
    code: "fieldset {}",
  }, {
    code: "my-type {}",
  }, {
    code: "my-other-type {}",
  } ],

  reject: [ {
    code: "a {}",
    line: 1,
    column: 1,
  }, {
    code: "not-my-type {}",
    message: messages.rejected,
    line: 1,
    column: 1,
  } ],
})
<|endoftext|>


<commit_before>import { get, setWith } from 'lodash-es'
import isString from './isString'
import isArray from './isArray'
import deleteFromArray from './deleteFromArray'

class TreeNode {}

/*
 * A tree-structure for indexes.
 *
 * @class TreeIndex
 * @param {object} [obj] An object to operate on
 * @memberof module:Basics
 * @example
 *
 * var index = new TreeIndex({a: "aVal", b: {b1: 'b1Val', b2: 'b2Val'}});
 */

class TreeIndex {
  /**
   * Get value at path.
   *
   * @return {object} The value stored for a given path
   *
   * @example
   *
   * obj.get(['b', 'b1']);
   * => b1Val
   */
  get (path) {
    if (arguments.length > 1) {
      path = Array.prototype.slice(arguments, 0)
    }
    if (isString(path)) {
      path = [path]
    }
    return get(this, path)
  }

  getAll (path) {
    if (arguments.length > 1) {
      path = Array.prototype.slice(arguments, 0)
    }
    if (isString(path)) {
      path = [path]
    }
    if (!isArray(path)) {
      throw new Error('Illegal argument for TreeIndex.get()')
    }
    var node = get(this, path)
    return this._collectValues(node)
  }

  set (path, value) {
    if (isString(path)) {
      path = [path]
    }
    setWith(this, path, value, function (val) {
      if (!val) return new TreeNode()
    })
  }

  delete (path) {
    if (isString(path)) {
      delete this[path]
    } else if (path.length === 1) {
      delete this[path[0]]
    } else {
      var key = path[path.length - 1]
      path = path.slice(0, -1)
      var parent = get(this, path)
      if (parent) {
        delete parent[key]
      }
    }
  }

  clear () {
    var root = this
    for (var key in root) {
      if (root.hasOwnProperty(key)) {
        delete root[key]
      }
    }
  }

  traverse (fn) {
    this._traverse(this, [], fn)
  }

  forEach (...args) {
    this.traverse(...args)
  }

  _traverse (root, path, fn) {
    var id
    for (id in root) {
      if (!root.hasOwnProperty(id)) continue
      var child = root[id]
      var childPath = path.concat([id])
      if (child instanceof TreeNode) {
        this._traverse(child, childPath, fn)
      } else {
        fn(child, childPath)
      }
    }
  }

  _collectValues (root) {
    // TODO: don't know if this is the best solution
    // We use this only for indexes, e.g., to get all annotation on one node
    var vals = {}
    this._traverse(root, [], function (val, path) {
      var key = path[path.length - 1]
      vals[key] = val
    })
    return vals
  }
}

class TreeIndexArrays extends TreeIndex {
  contains (path) {
    let val = super.get(path)
    return Boolean(val)
  }

  get (path) {
    let val = super.get(path)
    if (val instanceof TreeNode) {
      val = val.__values__ || []
    }
    return val
  }

  set (path, arr) {
    let val = super.get(path)
    val.__values__ = arr
  }

  add (path, value) {
    if (isString(path)) {
      path = [path]
    }
    if (!isArray(path)) {
      throw new Error('Illegal arguments.')
    }
    var arr

    // We are using setWith, as it allows us to create nodes on the way down
    // setWith can be controlled via a hook called for each key in the path
    // If val is not defined, a new node must be created and returned.
    // If val is defined, then we must return undefined to keep the original tree node
    // __dummy__ is necessary as setWith is used to set a value, but we want
    // to append to the array
    setWith(this, path.concat(['__values__', '__dummy__']), undefined, function (val, key) {
      if (key === '__values__') {
        if (!val) val = []
        arr = val
      } else if (!val) {
        val = new TreeNode()
      }
      return val
    })
    delete arr.__dummy__
    arr.push(value)
  }

  remove (path, value) {
    var arr = get(this, path)
    if (arr instanceof TreeNode) {
      if (arguments.length === 1) {
        delete arr.__values__
      } else {
        deleteFromArray(arr.__values__, value)
      }
    }
  }

  _collectValues (root) {
    var vals = []
    this._traverse(root, [], function (val) {
      vals.push(val)
    })
    vals = Array.prototype.concat.apply([], vals)
    return vals
  }
}

TreeIndex.Arrays = TreeIndexArrays

export default TreeIndex
<commit_msg>Tidy up.<commit_after>import { get, setWith } from 'lodash-es'
import isString from './isString'
import isArray from './isArray'
import deleteFromArray from './deleteFromArray'

class TreeNode {}

/*
 * A tree-structure for indexes.
 *
 * @class TreeIndex
 * @param {object} [obj] An object to operate on
 * @memberof module:Basics
 * @example
 *
 * var index = new TreeIndex({a: "aVal", b: {b1: 'b1Val', b2: 'b2Val'}});
 */

export default class TreeIndex {
  /**
   * Get value at path.
   *
   * @return {object} The value stored for a given path
   *
   * @example
   *
   * obj.get(['b', 'b1']);
   * => b1Val
   */
  get (path) {
    if (arguments.length > 1) {
      path = Array.prototype.slice(arguments, 0)
    }
    if (isString(path)) {
      path = [path]
    }
    return get(this, path)
  }

  getAll (path) {
    if (arguments.length > 1) {
      path = Array.prototype.slice(arguments, 0)
    }
    if (isString(path)) {
      path = [path]
    }
    if (!isArray(path)) {
      throw new Error('Illegal argument for TreeIndex.get()')
    }
    var node = get(this, path)
    return this._collectValues(node)
  }

  set (path, value) {
    if (isString(path)) {
      path = [path]
    }
    setWith(this, path, value, function (val) {
      if (!val) return new TreeNode()
    })
  }

  delete (path) {
    if (isString(path)) {
      delete this[path]
    } else if (path.length === 1) {
      delete this[path[0]]
    } else {
      var key = path[path.length - 1]
      path = path.slice(0, -1)
      var parent = get(this, path)
      if (parent) {
        delete parent[key]
      }
    }
  }

  clear () {
    var root = this
    for (var key in root) {
      if (root.hasOwnProperty(key)) {
        delete root[key]
      }
    }
  }

  traverse (fn) {
    this._traverse(this, [], fn)
  }

  forEach (...args) {
    this.traverse(...args)
  }

  _traverse (root, path, fn) {
    var id
    for (id in root) {
      if (!root.hasOwnProperty(id)) continue
      var child = root[id]
      var childPath = path.concat([id])
      if (child instanceof TreeNode) {
        this._traverse(child, childPath, fn)
      } else {
        fn(child, childPath)
      }
    }
  }

  _collectValues (root) {
    // TODO: don't know if this is the best solution
    // We use this only for indexes, e.g., to get all annotation on one node
    var vals = {}
    this._traverse(root, [], function (val, path) {
      var key = path[path.length - 1]
      vals[key] = val
    })
    return vals
  }
}

class TreeIndexArrays extends TreeIndex {
  contains (path) {
    let val = super.get(path)
    return Boolean(val)
  }

  get (path) {
    let val = super.get(path)
    if (val instanceof TreeNode) {
      val = val.__values__ || []
    }
    return val
  }

  set (path, arr) {
    let val = super.get(path)
    val.__values__ = arr
  }

  add (path, value) {
    if (isString(path)) {
      path = [path]
    }
    if (!isArray(path)) {
      throw new Error('Illegal arguments.')
    }
    var arr

    // We are using setWith, as it allows us to create nodes on the way down
    // setWith can be controlled via a hook called for each key in the path
    // If val is not defined, a new node must be created and returned.
    // If val is defined, then we must return undefined to keep the original tree node
    // __dummy__ is necessary as setWith is used to set a value, but we want
    // to append to the array
    setWith(this, path.concat(['__values__', '__dummy__']), undefined, function (val, key) {
      if (key === '__values__') {
        if (!val) val = []
        arr = val
      } else if (!val) {
        val = new TreeNode()
      }
      return val
    })
    delete arr.__dummy__
    arr.push(value)
  }

  remove (path, value) {
    var arr = get(this, path)
    if (arr instanceof TreeNode) {
      if (arguments.length === 1) {
        delete arr.__values__
      } else {
        deleteFromArray(arr.__values__, value)
      }
    }
  }

  _collectValues (root) {
    var vals = []
    this._traverse(root, [], function (val) {
      vals.push(val)
    })
    vals = Array.prototype.concat.apply([], vals)
    return vals
  }
}

TreeIndex.Arrays = TreeIndexArrays
<|endoftext|>


<commit_before>import * as $j from 'jquery';
import * as arrayUtils from './utility/arrayUtils';

export class Animations {
	constructor(game) {
		this.game = game;
		this.movementPoints = 0;
	}

	walk(creature, path, opts) {
		let game = this.game;

		if (opts.customMovementPoint > 0) {
			path = path.slice(0, opts.customMovementPoint);
			// For compatibility
			this.movementPoints = creature.remainingMove;
			creature.remainingMove = opts.customMovementPoint;
		}

		game.freezedInput = true;

		let animId = Math.random();
		game.animationQueue.push(animId);

		let hexId = 0;

		creature.healthHide();

		let anim = function () {
			let hex = path[hexId];

			if (hexId < path.length && (creature.remainingMove > 0 || opts.ignoreMovementPoint)) {
				this.leaveHex(creature, hex, opts);
			} else {
				this.movementComplete(creature, path[path.length - 1], animId, opts);
				return;
			}

			let nextPos = game.grid.hexes[hex.y][hex.x - creature.size + 1];
			let speed = !opts.overrideSpeed ? creature.animation.walk_speed : opts.overrideSpeed;

			let tween = game.Phaser.add
				.tween(creature.grp)
				.to(nextPos.displayPos, parseInt(speed, 10), Phaser.Easing.Linear.None)
				.start();

			// Ignore traps for hover creatures, unless this is the last hex
			let enterHexOpts = $j.extend(
				{
					ignoreTraps: creature.movementType() !== 'normal' && hexId < path.length - 1,
				},
				opts,
			);

			tween.onComplete.add(() => {
				if (creature.dead) {
					// Stop moving if creature has died while moving
					this.movementComplete(creature, hex, animId, opts);
					return;
				}

				// Sound Effect
				game.soundsys.playSound(game.soundLoaded[0], game.soundsys.effectsGainNode);

				if (!opts.ignoreMovementPoint) {
					creature.remainingMove--;

					if (opts.customMovementPoint === 0) {
						creature.travelDist++;
					}
				}

				this.enterHex(creature, hex, enterHexOpts);

				anim(); // Next tween
			});

			hexId++;
		}.bind(this);

		anim();
	}

	fly(creature, path, opts) {
		let game = this.game;

		if (opts.customMovementPoint > 0) {
			path = path.slice(0, opts.customMovementPoint);
			// For compatibility
			this.movementPoints = creature.remainingMove;
			creature.remainingMove = opts.customMovementPoint;
		}

		game.freezedInput = true;

		let animId = Math.random();
		game.animationQueue.push(animId);

		creature.healthHide();

		let hex = path[0];

		let start = game.grid.hexes[creature.y][creature.x - creature.size + 1];
		let currentHex = game.grid.hexes[hex.y][hex.x - creature.size + 1];

		this.leaveHex(creature, currentHex, opts);

		let speed = !opts.overrideSpeed ? creature.animation.walk_speed : opts.overrideSpeed;

		let tween = game.Phaser.add
			.tween(creature.grp)
			.to(currentHex.displayPos, parseInt(speed, 10), Phaser.Easing.Linear.None)
			.start();

		tween.onComplete.add(() => {
			// Sound Effect
			game.soundsys.playSound(game.soundLoaded[0], game.soundsys.effectsGainNode);

			if (!opts.ignoreMovementPoint) {
				// Determine distance
				let distance = 0;
				let k = 0;
				while (!distance) {
					k++;

					if (arrayUtils.findPos(start.adjacentHex(k), currentHex)) {
						distance = k;
					}
				}

				creature.remainingMove -= distance;
				if (opts.customMovementPoint === 0) {
					creature.travelDist += distance;
				}
			}

			this.enterHex(creature, hex, opts);
			this.movementComplete(creature, hex, animId, opts);
			return;
		});
	}

	teleport(creature, path, opts) {
		let game = this.game,
			hex = path[0],
			currentHex = game.grid.hexes[hex.y][hex.x - creature.size + 1];

		this.leaveHex(creature, currentHex, opts);

		let animId = Math.random();
		game.animationQueue.push(animId);

		// FadeOut
		let tween = game.Phaser.add
			.tween(creature.grp)
			.to(
				{
					alpha: 0,
				},
				500,
				Phaser.Easing.Linear.None,
			)
			.start();

		tween.onComplete.add(() => {
			// Sound Effect
			game.soundsys.playSound(game.soundLoaded[0], game.soundsys.effectsGainNode);

			// position
			creature.grp.x = currentHex.displayPos.x;
			creature.grp.y = currentHex.displayPos.y;

			// FadeIn
			game.Phaser.add
				.tween(creature.grp)
				.to(
					{
						alpha: 1,
					},
					500,
					Phaser.Easing.Linear.None,
				)
				.start();

			this.enterHex(creature, hex, opts);
			this.movementComplete(creature, hex, animId, opts);
			return;
		});
	}

	push(creature, path, opts) {
		opts.pushed = true;
		this.walk(creature, path, opts);
	}

	//--------Special Functions---------//

	enterHex(creature, hex, opts) {
		let game = this.game;

		creature.cleanHex();
		creature.x = hex.x - 0;
		creature.y = hex.y - 0;
		creature.pos = hex.pos;
		creature.updateHex();

		game.onStepIn(creature, hex, opts);

		creature.pickupDrop();

		opts.callbackStepIn(hex);

		game.grid.orderCreatureZ();
	}

	leaveHex(creature, hex, opts) {
		let game = this.game;

		if (!opts.pushed) {
			creature.faceHex(hex, creature.hexagons[0]); // Determine facing
		}

		game.onStepOut(creature, creature.hexagons[0]); // Trigger
		game.grid.orderCreatureZ();
	}

	movementComplete(creature, hex, animId, opts) {
		let game = this.game;

		if (opts.customMovementPoint > 0) {
			creature.remainingMove = this.movementPoints;
		}

		// TODO: Turn around animation
		if (opts.turnAroundOnComplete) {
			creature.facePlayerDefault();
		}

		// TODO: Reveal health indicator
		creature.healthShow();

		game.onCreatureMove(creature, hex); // Trigger

		creature.hexagons.forEach((h) => {
			h.pickupDrop(creature);
		});

		game.grid.orderCreatureZ();

		let queue = game.animationQueue.filter((item) => item != animId);

		if (queue.length === 0) {
			game.freezedInput = false;
		}

		game.animationQueue = queue;
	}

	projectile(this2, target, spriteId, path, args, startX, startY) {
		//Get the side of the target that is closest to emission
		let emissionPointX = this2.creature.grp.x + startX;
		let targetLeftX = target.grp.x + 52;
		let targetRightX = target.grp.x + 52 + (target.size - 1) * 90;
		let targetX =
			Math.abs(emissionPointX - targetLeftX) < Math.abs(emissionPointX - targetRightX)
				? targetLeftX
				: targetRightX;

		let game = this.game,
			baseDist = arrayUtils.filterCreature(path.slice(0), false, false).length,
			dist = baseDist == 0 ? 1 : baseDist,
			emissionPoint = {
				x: emissionPointX,
				y: this2.creature.grp.y + startY,
			},
			targetPoint = {
				x: targetX,
				y: target.grp.y - 20,
			},
			// Sprite id here
			sprite = game.grid.creatureGroup.create(emissionPoint.x, emissionPoint.y, spriteId),
			duration = dist * 75;

		sprite.anchor.setTo(0.5);
		sprite.rotation = Math.atan(
			(emissionPoint.y - targetPoint.y) / (emissionPoint.x - targetPoint.x),
		);
		if (emissionPoint.x - targetPoint.x > 0) {
			sprite.rotation += Math.PI;
		}
		let tween = game.Phaser.add
			.tween(sprite)
			.to(
				{
					x: targetPoint.x,
					y: targetPoint.y,
				},
				duration,
				Phaser.Easing.Linear.None,
			)
			.start();

		return [tween, sprite, dist];
	}
}
<commit_msg>Fix comment style<commit_after>import * as $j from 'jquery';
import * as arrayUtils from './utility/arrayUtils';

export class Animations {
	constructor(game) {
		this.game = game;
		this.movementPoints = 0;
	}

	walk(creature, path, opts) {
		let game = this.game;

		if (opts.customMovementPoint > 0) {
			path = path.slice(0, opts.customMovementPoint);
			// For compatibility
			this.movementPoints = creature.remainingMove;
			creature.remainingMove = opts.customMovementPoint;
		}

		game.freezedInput = true;

		let animId = Math.random();
		game.animationQueue.push(animId);

		let hexId = 0;

		creature.healthHide();

		let anim = function () {
			let hex = path[hexId];

			if (hexId < path.length && (creature.remainingMove > 0 || opts.ignoreMovementPoint)) {
				this.leaveHex(creature, hex, opts);
			} else {
				this.movementComplete(creature, path[path.length - 1], animId, opts);
				return;
			}

			let nextPos = game.grid.hexes[hex.y][hex.x - creature.size + 1];
			let speed = !opts.overrideSpeed ? creature.animation.walk_speed : opts.overrideSpeed;

			let tween = game.Phaser.add
				.tween(creature.grp)
				.to(nextPos.displayPos, parseInt(speed, 10), Phaser.Easing.Linear.None)
				.start();

			// Ignore traps for hover creatures, unless this is the last hex
			let enterHexOpts = $j.extend(
				{
					ignoreTraps: creature.movementType() !== 'normal' && hexId < path.length - 1,
				},
				opts,
			);

			tween.onComplete.add(() => {
				if (creature.dead) {
					// Stop moving if creature has died while moving
					this.movementComplete(creature, hex, animId, opts);
					return;
				}

				// Sound Effect
				game.soundsys.playSound(game.soundLoaded[0], game.soundsys.effectsGainNode);

				if (!opts.ignoreMovementPoint) {
					creature.remainingMove--;

					if (opts.customMovementPoint === 0) {
						creature.travelDist++;
					}
				}

				this.enterHex(creature, hex, enterHexOpts);

				anim(); // Next tween
			});

			hexId++;
		}.bind(this);

		anim();
	}

	fly(creature, path, opts) {
		let game = this.game;

		if (opts.customMovementPoint > 0) {
			path = path.slice(0, opts.customMovementPoint);
			// For compatibility
			this.movementPoints = creature.remainingMove;
			creature.remainingMove = opts.customMovementPoint;
		}

		game.freezedInput = true;

		let animId = Math.random();
		game.animationQueue.push(animId);

		creature.healthHide();

		let hex = path[0];

		let start = game.grid.hexes[creature.y][creature.x - creature.size + 1];
		let currentHex = game.grid.hexes[hex.y][hex.x - creature.size + 1];

		this.leaveHex(creature, currentHex, opts);

		let speed = !opts.overrideSpeed ? creature.animation.walk_speed : opts.overrideSpeed;

		let tween = game.Phaser.add
			.tween(creature.grp)
			.to(currentHex.displayPos, parseInt(speed, 10), Phaser.Easing.Linear.None)
			.start();

		tween.onComplete.add(() => {
			// Sound Effect
			game.soundsys.playSound(game.soundLoaded[0], game.soundsys.effectsGainNode);

			if (!opts.ignoreMovementPoint) {
				// Determine distance
				let distance = 0;
				let k = 0;
				while (!distance) {
					k++;

					if (arrayUtils.findPos(start.adjacentHex(k), currentHex)) {
						distance = k;
					}
				}

				creature.remainingMove -= distance;
				if (opts.customMovementPoint === 0) {
					creature.travelDist += distance;
				}
			}

			this.enterHex(creature, hex, opts);
			this.movementComplete(creature, hex, animId, opts);
			return;
		});
	}

	teleport(creature, path, opts) {
		let game = this.game,
			hex = path[0],
			currentHex = game.grid.hexes[hex.y][hex.x - creature.size + 1];

		this.leaveHex(creature, currentHex, opts);

		let animId = Math.random();
		game.animationQueue.push(animId);

		// FadeOut
		let tween = game.Phaser.add
			.tween(creature.grp)
			.to(
				{
					alpha: 0,
				},
				500,
				Phaser.Easing.Linear.None,
			)
			.start();

		tween.onComplete.add(() => {
			// Sound Effect
			game.soundsys.playSound(game.soundLoaded[0], game.soundsys.effectsGainNode);

			// position
			creature.grp.x = currentHex.displayPos.x;
			creature.grp.y = currentHex.displayPos.y;

			// FadeIn
			game.Phaser.add
				.tween(creature.grp)
				.to(
					{
						alpha: 1,
					},
					500,
					Phaser.Easing.Linear.None,
				)
				.start();

			this.enterHex(creature, hex, opts);
			this.movementComplete(creature, hex, animId, opts);
			return;
		});
	}

	push(creature, path, opts) {
		opts.pushed = true;
		this.walk(creature, path, opts);
	}

	//--------Special Functions---------//

	enterHex(creature, hex, opts) {
		let game = this.game;

		creature.cleanHex();
		creature.x = hex.x - 0;
		creature.y = hex.y - 0;
		creature.pos = hex.pos;
		creature.updateHex();

		game.onStepIn(creature, hex, opts);

		creature.pickupDrop();

		opts.callbackStepIn(hex);

		game.grid.orderCreatureZ();
	}

	leaveHex(creature, hex, opts) {
		let game = this.game;

		if (!opts.pushed) {
			creature.faceHex(hex, creature.hexagons[0]); // Determine facing
		}

		game.onStepOut(creature, creature.hexagons[0]); // Trigger
		game.grid.orderCreatureZ();
	}

	movementComplete(creature, hex, animId, opts) {
		let game = this.game;

		if (opts.customMovementPoint > 0) {
			creature.remainingMove = this.movementPoints;
		}

		// TODO: Turn around animation
		if (opts.turnAroundOnComplete) {
			creature.facePlayerDefault();
		}

		// TODO: Reveal health indicator
		creature.healthShow();

		game.onCreatureMove(creature, hex); // Trigger

		creature.hexagons.forEach((h) => {
			h.pickupDrop(creature);
		});

		game.grid.orderCreatureZ();

		let queue = game.animationQueue.filter((item) => item != animId);

		if (queue.length === 0) {
			game.freezedInput = false;
		}

		game.animationQueue = queue;
	}

	projectile(this2, target, spriteId, path, args, startX, startY) {
		// Get the side of the target that is closest to emission
		let emissionPointX = this2.creature.grp.x + startX;
		let targetLeftX = target.grp.x + 52;
		let targetRightX = target.grp.x + 52 + (target.size - 1) * 90;
		let targetX =
			Math.abs(emissionPointX - targetLeftX) < Math.abs(emissionPointX - targetRightX)
				? targetLeftX
				: targetRightX;

		let game = this.game,
			baseDist = arrayUtils.filterCreature(path.slice(0), false, false).length,
			dist = baseDist == 0 ? 1 : baseDist,
			emissionPoint = {
				x: emissionPointX,
				y: this2.creature.grp.y + startY,
			},
			targetPoint = {
				x: targetX,
				y: target.grp.y - 20,
			},
			// Sprite id here
			sprite = game.grid.creatureGroup.create(emissionPoint.x, emissionPoint.y, spriteId),
			duration = dist * 75;

		sprite.anchor.setTo(0.5);
		sprite.rotation = Math.atan(
			(emissionPoint.y - targetPoint.y) / (emissionPoint.x - targetPoint.x),
		);
		if (emissionPoint.x - targetPoint.x > 0) {
			sprite.rotation += Math.PI;
		}
		let tween = game.Phaser.add
			.tween(sprite)
			.to(
				{
					x: targetPoint.x,
					y: targetPoint.y,
				},
				duration,
				Phaser.Easing.Linear.None,
			)
			.start();

		return [tween, sprite, dist];
	}
}
<|endoftext|>


<commit_before>steal("./dojo-1.8.1.js", '../event.js', '../fragment.js', './trigger', 'can/util/array/each.js', 'can/util/object/isplain',
	function(){

	// dojo.js
	// ---------
	// _dojo node list._
	//
	// These are pre-loaded by `steal` -> no callback.
	require(["dojo", "dojo/query", "plugd/trigger", "dojo/NodeList-dom"]);

	// Map string helpers.
	can.trim = function(s){
		return s && dojo.trim(s);
	}

	// Map array helpers.
	can.makeArray = function(arr){
		array = [];
		dojo.forEach(arr, function(item){ array.push(item)});
		return array;
	};
	can.isArray = dojo.isArray;
	can.inArray = function(item,arr){
		return dojo.indexOf(arr, item);
	};
	can.map = function(arr, fn){
		return dojo.map(can.makeArray(arr||[]), fn);
	};
	// Map object helpers.
	can.extend = function(first){
		if(first === true){
			var args = can.makeArray(arguments);
			args.shift();
			return dojo.mixin.apply(dojo, args)
		}
		return dojo.mixin.apply(dojo, arguments)
	}
	can.isEmptyObject = function(object){
		var prop;
		for(prop in object){
			break;
		}
		return prop === undefined;;
	}

	// Use a version of param similar to jQuery's param that
	// handles nested data instead of dojo.objectToQuery which doesn't
	can.param = function(object){
		var pairs = [],
			add = function( key, value ){
				pairs.push(encodeURIComponent(key) + "=" + encodeURIComponent(value))
			};

		for(var name in object){
			can.buildParam(name, object[name], add);
		}
		return pairs.join("&").replace(/%20/g, "+");
	}
	can.buildParam = function(prefix, obj, add){
        if(can.isArray(obj)){
            for(var i = 0, l = obj.length; i < l; ++i){
                add(prefix + "[]", obj[i])
            }
        } else if( dojo.isObject(obj) ){
        	for (var name in obj){
        		can.buildParam(prefix + "[" + name + "]", obj[name], add);
        	}
        } else {
        	add(prefix, obj);
        }
	}

	// Map function helpers.
	can.proxy = function(func, context){
		return dojo.hitch(context, func)
	}
	can.isFunction = function(f){
		return dojo.isFunction(f);
	}
	/**
	 * EVENTS
	 *
	 * Dojo does not use the callback handler when unbinding.  Instead
	 * when binding (dojo.connect or dojo.on) an object with a remove
	 * method is returned.
	 *
	 * Because of this, we have to map each callback to the "remove"
	 * object to it can be passed to dojo.disconnect.
	 */

	// The id of the `function` to be bound, used as an expando on the `function`
	// so we can lookup it's `remove` object.
	var dojoId = 0,
		// Takes a node list, goes through each node
		// and adds events data that has a map of events to
		// callbackId to `remove` object.  It looks like
		// `{click: {5: {remove: fn}}}`.
		dojoAddBinding = function( nodelist, ev, cb ) {
			nodelist.forEach(function(node){
				// Converting a raw select node to a node list
				// returns a node list of its options due to a
				// bug in Dojo 1.7.1, this is sovled by wrapping
				// it in an array.
				node = new dojo.NodeList(node.nodeName === "SELECT" ? [node] : node)
				var events = can.data(node,"events");
				if(!events){
					can.data(node,"events", events = {})
				}
				if(!events[ev]){
					events[ev] = {};
				}
				if(cb.__bindingsIds === undefined) {
					cb.__bindingsIds=dojoId++;
				}
				events[ev][cb.__bindingsIds] = node.on(ev, cb)[0]
			});
		},
		// Removes a binding on a `nodelist` by finding
		// the remove object within the object's data.
		dojoRemoveBinding = function(nodelist,ev,cb){
			nodelist.forEach(function(node){
				var node = new dojo.NodeList(node),
					events = can.data(node,"events"),
					handlers = events[ev],
					handler = handlers[cb.__bindingsIds];

				dojo.disconnect(handler);
				delete handlers[cb.__bindingsIds];

				if(can.isEmptyObject(handlers)){
					delete events[ev]
				}
			});
		}

	can.bind = function( ev, cb){
		// If we can bind to it...
		if(this.bind && this.bind !== can.bind){
			this.bind(ev, cb)

		// Otherwise it's an element or `nodeList`.
		} else if(this.on || this.nodeType){
			// Converting a raw select node to a node list
			// returns a node list of its options due to a
			// bug in Dojo 1.7.1, this is sovled by wrapping
			// it in an array.
			dojoAddBinding( new dojo.NodeList(this.nodeName === "SELECT" ? [this] : this), ev, cb)
		} else if(this.addEvent) {
			this.addEvent(ev, cb)
		} else {
			// Make it bind-able...
			can.addEvent.call(this, ev, cb)
		}
		return this;
	}
	can.unbind = function(ev, cb){
		// If we can bind to it...
		if(this.unbind && this.unbind !== can.unbind){
			this.unbind(ev, cb)
		}

		else if(this.on || this.nodeType) {
			dojoRemoveBinding(new dojo.NodeList(this), ev, cb);
		} else {
			// Make it bind-able...
			can.removeEvent.call(this, ev, cb)
		}
		return this;
	}

	can.trigger = function(item, event, args, bubble){
		item = item instanceof dojo.NodeList ? item : item.nodeName ? can.$(item) : item;
		if(item.trigger){
			if(bubble === false){
				if(!item[0] || item[0].nodeType === 3){
					return;
				}
				// Force stop propagation by
				// listening to `on` and then immediately disconnecting.
				var connect = item.on(event, function(ev){

					ev.stopPropagation && ev.stopPropagation();
					ev.cancelBubble = true;
					ev._stopper && ev._stopper();

					dojo.disconnect(connect);
				})
				item.trigger(event,args)
			} else {
				item.trigger(event,args)
			}

		} else {
			if(typeof event === 'string'){
				event = {type: event}
			}
			event.data = args
			event.target = event.target || item;
			can.dispatch.call(item, event)
		}
	}

	can.delegate = function(selector, ev , cb){
		if(this.on || this.nodeType){
			dojoAddBinding( new dojo.NodeList(this), selector+":"+ev, cb)
		} else if(this.delegate) {
			this.delegate(selector, ev , cb)
		}
		return this;
	}
	can.undelegate = function(selector, ev , cb){
		if(this.on || this.nodeType){
			dojoRemoveBinding(new dojo.NodeList(this), selector+":"+ev, cb);
		} else if(this.undelegate) {
			this.undelegate(selector, ev , cb)
		}

		return this;
	}

	/**
	 * Ajax
	 */
	var optionsMap = {
		type:"method",
		success : undefined,
		error: undefined
	}
	var updateDeferred = function(xhr, d){
		for(var prop in xhr){
			if(typeof d[prop] == 'function'){
				d[prop] = function(){
					xhr[prop].apply(xhr, arguments)
				}
			} else {
				d[prop] = prop[xhr]
			}
		}
	}

	can.ajax = function(options){
		var type = can.capitalize( (options.type || "get").toLowerCase() ),
			method = dojo["xhr"+type];
		var success = options.success,
			error = options.error,
			d = new can.Deferred();

		var def = method({
			url : options.url,
			handleAs : options.dataType,
			sync : !options.async,
			headers : options.headers,
			content: options.data
		})
		def.then(function(data, ioargs){
			updateDeferred(xhr, d);
			d.resolve(data,"success",xhr);
			success && success(data,"success",xhr);
		},function(data,ioargs){
			updateDeferred(xhr, d);
			d.reject(xhr,"error");
			error(xhr,"error");
		})

		var xhr = def.ioArgs.xhr;

		updateDeferred(xhr, d);
		return d;

	}
	// Element - get the wrapped helper.
	can.$ = function(selector){
		if(selector === window){
			return window;
		}
		if(typeof selector === "string"){
			return dojo.query(selector)
		} else {
			return new dojo.NodeList(selector);
		}
	}

	can.append = function(wrapped, html){
		return wrapped.forEach(function(node){
			dojo.place( html, node)
		});
	}

	/**
	 * can.data
	 *
	 * can.data is used to store arbitrary data on an element.
	 * Dojo does not support this, so we implement it itself.
	 *
	 * The important part is to call cleanData on any elements
	 * that are removed from the DOM.  For this to happen, we
	 * overwrite
	 *
	 *   -dojo.empty
	 *   -dojo.destroy
	 *   -dojo.place when "replace" is used TODO!!!!
	 *
	 * For can.Control, we also need to trigger a non bubbling event
	 * when an element is removed.  We do this also in cleanData.
	 */
	var data = {},
	    uuid = can.uuid = +new Date(),
	    exp  = can.expando = 'can' + uuid;

	function getData(node, name) {
	    var id = node[exp], store = id && data[id];
	    return name === undefined ? store || setData(node) :
	      (store && store[name]);
	}

	function setData(node, name, value) {
	    var id = node[exp] || (node[exp] = ++uuid),
	      store = data[id] || (data[id] = {});
	    if (name !== undefined) store[name] = value;
	    return store;
	};

	var cleanData = function(elems){
	  	can.trigger(new dojo.NodeList(elems),"destroyed",[],false)
	  	for ( var i = 0, elem;
			(elem = elems[i]) !== undefined; i++ ) {
				var id = elem[exp]
				delete data[id];
			}
	};

	can.data = function(wrapped, name, value){
		return value === undefined ?
			wrapped.length == 0 ? undefined : getData(wrapped[0], name) :
			wrapped.forEach(function(node){
				setData(node, name, value);
			});
	};

	// Overwrite `dojo.destroy`, `dojo.empty` and `dojo.place`.
	var empty = dojo.empty;
	dojo.empty = function(){
		for(var c; c = node.lastChild;){ // Intentional assignment.
			dojo.destroy(c);
		}
	}

	var destroy = dojo.destroy;
	dojo.destroy = function(node){
		node = dojo.byId(node);
		cleanData([node]);
		node.getElementsByTagName && cleanData(node.getElementsByTagName('*'))

		return destroy.apply(dojo, arguments);
	};

	can.addClass = function(wrapped, className){
		return wrapped.addClass(className);
	}

	can.remove = function(wrapped){
		// We need to remove text nodes ourselves.
		wrapped.forEach(dojo.destroy);
	}

	can.get = function(wrapped, index){
		return wrapped[index];
	}

	// Add pipe to `dojo.Deferred`.
	can.extend(dojo.Deferred.prototype, {
		pipe : function(done, fail){
			var d = new dojo.Deferred();
			this.addCallback(function(){
				d.resolve( done.apply(this, arguments) );
			});

			this.addErrback(function(){
				if(fail){
					d.reject( fail.apply(this, arguments) );
				} else {
					d.reject.apply(d, arguments);
				}
			});
			return d;
		}
	});

	return can;
}).then('../deferred.js')
<commit_msg>Added a then() to the dojo shim so we guarantee define() is there when we need it.<commit_after>steal("./dojo-1.8.1.js", '../event.js', '../fragment.js').then('./trigger', 'can/util/array/each.js', 'can/util/object/isplain',
	function(){

	// dojo.js
	// ---------
	// _dojo node list._
	//
	// These are pre-loaded by `steal` -> no callback.
	require(["dojo", "dojo/query", "plugd/trigger", "dojo/NodeList-dom"]);

	// Map string helpers.
	can.trim = function(s){
		return s && dojo.trim(s);
	}

	// Map array helpers.
	can.makeArray = function(arr){
		array = [];
		dojo.forEach(arr, function(item){ array.push(item)});
		return array;
	};
	can.isArray = dojo.isArray;
	can.inArray = function(item,arr){
		return dojo.indexOf(arr, item);
	};
	can.map = function(arr, fn){
		return dojo.map(can.makeArray(arr||[]), fn);
	};
	// Map object helpers.
	can.extend = function(first){
		if(first === true){
			var args = can.makeArray(arguments);
			args.shift();
			return dojo.mixin.apply(dojo, args)
		}
		return dojo.mixin.apply(dojo, arguments)
	}
	can.isEmptyObject = function(object){
		var prop;
		for(prop in object){
			break;
		}
		return prop === undefined;;
	}

	// Use a version of param similar to jQuery's param that
	// handles nested data instead of dojo.objectToQuery which doesn't
	can.param = function(object){
		var pairs = [],
			add = function( key, value ){
				pairs.push(encodeURIComponent(key) + "=" + encodeURIComponent(value))
			};

		for(var name in object){
			can.buildParam(name, object[name], add);
		}
		return pairs.join("&").replace(/%20/g, "+");
	}
	can.buildParam = function(prefix, obj, add){
        if(can.isArray(obj)){
            for(var i = 0, l = obj.length; i < l; ++i){
                add(prefix + "[]", obj[i])
            }
        } else if( dojo.isObject(obj) ){
        	for (var name in obj){
        		can.buildParam(prefix + "[" + name + "]", obj[name], add);
        	}
        } else {
        	add(prefix, obj);
        }
	}

	// Map function helpers.
	can.proxy = function(func, context){
		return dojo.hitch(context, func)
	}
	can.isFunction = function(f){
		return dojo.isFunction(f);
	}
	/**
	 * EVENTS
	 *
	 * Dojo does not use the callback handler when unbinding.  Instead
	 * when binding (dojo.connect or dojo.on) an object with a remove
	 * method is returned.
	 *
	 * Because of this, we have to map each callback to the "remove"
	 * object to it can be passed to dojo.disconnect.
	 */

	// The id of the `function` to be bound, used as an expando on the `function`
	// so we can lookup it's `remove` object.
	var dojoId = 0,
		// Takes a node list, goes through each node
		// and adds events data that has a map of events to
		// callbackId to `remove` object.  It looks like
		// `{click: {5: {remove: fn}}}`.
		dojoAddBinding = function( nodelist, ev, cb ) {
			nodelist.forEach(function(node){
				// Converting a raw select node to a node list
				// returns a node list of its options due to a
				// bug in Dojo 1.7.1, this is sovled by wrapping
				// it in an array.
				node = new dojo.NodeList(node.nodeName === "SELECT" ? [node] : node)
				var events = can.data(node,"events");
				if(!events){
					can.data(node,"events", events = {})
				}
				if(!events[ev]){
					events[ev] = {};
				}
				if(cb.__bindingsIds === undefined) {
					cb.__bindingsIds=dojoId++;
				}
				events[ev][cb.__bindingsIds] = node.on(ev, cb)[0]
			});
		},
		// Removes a binding on a `nodelist` by finding
		// the remove object within the object's data.
		dojoRemoveBinding = function(nodelist,ev,cb){
			nodelist.forEach(function(node){
				var node = new dojo.NodeList(node),
					events = can.data(node,"events"),
					handlers = events[ev],
					handler = handlers[cb.__bindingsIds];

				dojo.disconnect(handler);
				delete handlers[cb.__bindingsIds];

				if(can.isEmptyObject(handlers)){
					delete events[ev]
				}
			});
		}

	can.bind = function( ev, cb){
		// If we can bind to it...
		if(this.bind && this.bind !== can.bind){
			this.bind(ev, cb)

		// Otherwise it's an element or `nodeList`.
		} else if(this.on || this.nodeType){
			// Converting a raw select node to a node list
			// returns a node list of its options due to a
			// bug in Dojo 1.7.1, this is sovled by wrapping
			// it in an array.
			dojoAddBinding( new dojo.NodeList(this.nodeName === "SELECT" ? [this] : this), ev, cb)
		} else if(this.addEvent) {
			this.addEvent(ev, cb)
		} else {
			// Make it bind-able...
			can.addEvent.call(this, ev, cb)
		}
		return this;
	}
	can.unbind = function(ev, cb){
		// If we can bind to it...
		if(this.unbind && this.unbind !== can.unbind){
			this.unbind(ev, cb)
		}

		else if(this.on || this.nodeType) {
			dojoRemoveBinding(new dojo.NodeList(this), ev, cb);
		} else {
			// Make it bind-able...
			can.removeEvent.call(this, ev, cb)
		}
		return this;
	}

	can.trigger = function(item, event, args, bubble){
		item = item instanceof dojo.NodeList ? item : item.nodeName ? can.$(item) : item;
		if(item.trigger){
			if(bubble === false){
				if(!item[0] || item[0].nodeType === 3){
					return;
				}
				// Force stop propagation by
				// listening to `on` and then immediately disconnecting.
				var connect = item.on(event, function(ev){

					ev.stopPropagation && ev.stopPropagation();
					ev.cancelBubble = true;
					ev._stopper && ev._stopper();

					dojo.disconnect(connect);
				})
				item.trigger(event,args)
			} else {
				item.trigger(event,args)
			}

		} else {
			if(typeof event === 'string'){
				event = {type: event}
			}
			event.data = args
			event.target = event.target || item;
			can.dispatch.call(item, event)
		}
	}

	can.delegate = function(selector, ev , cb){
		if(this.on || this.nodeType){
			dojoAddBinding( new dojo.NodeList(this), selector+":"+ev, cb)
		} else if(this.delegate) {
			this.delegate(selector, ev , cb)
		}
		return this;
	}
	can.undelegate = function(selector, ev , cb){
		if(this.on || this.nodeType){
			dojoRemoveBinding(new dojo.NodeList(this), selector+":"+ev, cb);
		} else if(this.undelegate) {
			this.undelegate(selector, ev , cb)
		}

		return this;
	}

	/**
	 * Ajax
	 */
	var optionsMap = {
		type:"method",
		success : undefined,
		error: undefined
	}
	var updateDeferred = function(xhr, d){
		for(var prop in xhr){
			if(typeof d[prop] == 'function'){
				d[prop] = function(){
					xhr[prop].apply(xhr, arguments)
				}
			} else {
				d[prop] = prop[xhr]
			}
		}
	}

	can.ajax = function(options){
		var type = can.capitalize( (options.type || "get").toLowerCase() ),
			method = dojo["xhr"+type];
		var success = options.success,
			error = options.error,
			d = new can.Deferred();

		var def = method({
			url : options.url,
			handleAs : options.dataType,
			sync : !options.async,
			headers : options.headers,
			content: options.data
		})
		def.then(function(data, ioargs){
			updateDeferred(xhr, d);
			d.resolve(data,"success",xhr);
			success && success(data,"success",xhr);
		},function(data,ioargs){
			updateDeferred(xhr, d);
			d.reject(xhr,"error");
			error(xhr,"error");
		})

		var xhr = def.ioArgs.xhr;

		updateDeferred(xhr, d);
		return d;

	}
	// Element - get the wrapped helper.
	can.$ = function(selector){
		if(selector === window){
			return window;
		}
		if(typeof selector === "string"){
			return dojo.query(selector)
		} else {
			return new dojo.NodeList(selector);
		}
	}

	can.append = function(wrapped, html){
		return wrapped.forEach(function(node){
			dojo.place( html, node)
		});
	}

	/**
	 * can.data
	 *
	 * can.data is used to store arbitrary data on an element.
	 * Dojo does not support this, so we implement it itself.
	 *
	 * The important part is to call cleanData on any elements
	 * that are removed from the DOM.  For this to happen, we
	 * overwrite
	 *
	 *   -dojo.empty
	 *   -dojo.destroy
	 *   -dojo.place when "replace" is used TODO!!!!
	 *
	 * For can.Control, we also need to trigger a non bubbling event
	 * when an element is removed.  We do this also in cleanData.
	 */
	var data = {},
	    uuid = can.uuid = +new Date(),
	    exp  = can.expando = 'can' + uuid;

	function getData(node, name) {
	    var id = node[exp], store = id && data[id];
	    return name === undefined ? store || setData(node) :
	      (store && store[name]);
	}

	function setData(node, name, value) {
	    var id = node[exp] || (node[exp] = ++uuid),
	      store = data[id] || (data[id] = {});
	    if (name !== undefined) store[name] = value;
	    return store;
	};

	var cleanData = function(elems){
	  	can.trigger(new dojo.NodeList(elems),"destroyed",[],false)
	  	for ( var i = 0, elem;
			(elem = elems[i]) !== undefined; i++ ) {
				var id = elem[exp]
				delete data[id];
			}
	};

	can.data = function(wrapped, name, value){
		return value === undefined ?
			wrapped.length == 0 ? undefined : getData(wrapped[0], name) :
			wrapped.forEach(function(node){
				setData(node, name, value);
			});
	};

	// Overwrite `dojo.destroy`, `dojo.empty` and `dojo.place`.
	var empty = dojo.empty;
	dojo.empty = function(){
		for(var c; c = node.lastChild;){ // Intentional assignment.
			dojo.destroy(c);
		}
	}

	var destroy = dojo.destroy;
	dojo.destroy = function(node){
		node = dojo.byId(node);
		cleanData([node]);
		node.getElementsByTagName && cleanData(node.getElementsByTagName('*'))

		return destroy.apply(dojo, arguments);
	};

	can.addClass = function(wrapped, className){
		return wrapped.addClass(className);
	}

	can.remove = function(wrapped){
		// We need to remove text nodes ourselves.
		wrapped.forEach(dojo.destroy);
	}

	can.get = function(wrapped, index){
		return wrapped[index];
	}

	// Add pipe to `dojo.Deferred`.
	can.extend(dojo.Deferred.prototype, {
		pipe : function(done, fail){
			var d = new dojo.Deferred();
			this.addCallback(function(){
				d.resolve( done.apply(this, arguments) );
			});

			this.addErrback(function(){
				if(fail){
					d.reject( fail.apply(this, arguments) );
				} else {
					d.reject.apply(d, arguments);
				}
			});
			return d;
		}
	});

	return can;
}).then('../deferred.js')
<|endoftext|>


<commit_before>'use strict';

import express from 'express';
import OAuth2Server from 'oauth2-server';
import bodyParser from 'body-parser';
import Model from './oauth/twolevel.model.js';
import {authorizeFull, authorizePartial} from './oauth/twolevel.middleware.js';
import throttle from './throttle/throttle.middleware.js';

export default function createApp(tokenStore, userStore, configStore) {
  var app = express();

  app.oauth = OAuth2Server({
    model: new Model(tokenStore, userStore),
    grants: ['password', 'client_credentials'],
    debug: true
  });

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

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

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

    tokenStore.getAccessToken(bearerToken)
      .then(() => {
        configStore.get(bearerToken)
          .then((config) => {
            res.send(JSON.stringify(config));
          })
          .catch((err) => {
            return next(err);
          });
      })
      .catch((err) => {
        return next(err);
      });
  });

  app.all('/oauth/token', app.oauth.grant());

// Examples of OAuth middleware
  app.get('/secret', app.oauth.authorise(), authorizePartial(), function (req, res) {
    res.send('Secret area');
  });

  app.get('/test', app.oauth.authorise(), authorizeFull(), function (req, res) {
    res.send('Super secret area');
  });

  return app;
}
<commit_msg>disable the X-Powered-By header<commit_after>'use strict';

import express from 'express';
import OAuth2Server from 'oauth2-server';
import bodyParser from 'body-parser';
import Model from './oauth/twolevel.model.js';
import {authorizeFull, authorizePartial} from './oauth/twolevel.middleware.js';
import throttle from './throttle/throttle.middleware.js';

export default function createApp(tokenStore, userStore, configStore) {
  var app = express();

  app.oauth = OAuth2Server({
    model: new Model(tokenStore, userStore),
    grants: ['password', 'client_credentials'],
    debug: true
  });

  app.disable('x-powered-by');
  app.use(bodyParser.urlencoded({extended: true}));
  app.use(bodyParser.json());
  app.use(app.oauth.errorHandler());
  app.use(throttle());

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

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

    tokenStore.getAccessToken(bearerToken)
      .then(() => {
        configStore.get(bearerToken)
          .then((config) => {
            res.send(JSON.stringify(config));
          })
          .catch((err) => {
            return next(err);
          });
      })
      .catch((err) => {
        return next(err);
      });
  });

  app.all('/oauth/token', app.oauth.grant());

// Examples of OAuth middleware
  app.get('/secret', app.oauth.authorise(), authorizePartial(), function (req, res) {
    res.send('Secret area');
  });

  app.get('/test', app.oauth.authorise(), authorizeFull(), function (req, res) {
    res.send('Super secret area');
  });

  return app;
}
<|endoftext|>


<commit_before>// @flow

import { create } from 'apisauce'
import camelcaseKeys from 'camelcase-keys'
import _ from 'lodash'
import { normalizeStories } from './normalize'

import type { Story, Blog, QueryParams, PageInfo, Screen } from '../types'

const host =
  process.env.NODE_ENV == 'development'
    ? // ? 'http://localhost:3001'
      'https://ssconnect.elzup.com'
    : 'https://ssconnect.elzup.com'
const TIMEOUT = 1000

const api = create({
  baseURL: host,
  timeout: TIMEOUT,
})

function permitQuery(screen: Screen): QueryParams {
  switch (screen.type) {
    case 'new': {
      const { page } = screen
      return { page, tag: '', q: '' }
    }
    case 'search': {
      const { page, tag, q } = screen
      return { page, tag, q }
    }
    default: {
      // NOTE: Why can remove?
      return { page: 0, tag: '', q: '' }
    }
  }
}

type GetStoriesCallback = ({
  stories: Story[],
  articles: Article[],
  blogs: Blog[],
}) => void

export function getStories(
  screen: Screen,
  cb: GetStoriesCallback,
  timeout: number = TIMEOUT
) {
  const params = permitQuery(screen)
  const res = api.get('/v1/stories', params).then(res => {
    // { stories: res.data, pageInfo: FeedClient.getPageInfo(res) }
    const normalizedData = normalizeStories(res.data)
    const camelizedData = camelcaseKeys(normalizedData, { deep: true })
    cb(_.mapValues(camelizedData.entities, _.values))
  })
}

function getPageInfo(res: any): PageInfo {
  return {
    page: parseInt(res.headers['x-page'], 10),
    total: parseInt(res.headers['x-total-pages'], 10),
    next: parseInt(res.headers['x-next-page'], 10) || false,
    prev: parseInt(res.headers['x-prev-page'], 10) || false,
  }
}
<commit_msg>Fix type improt<commit_after>// @flow

import { create } from 'apisauce'
import camelcaseKeys from 'camelcase-keys'
import _ from 'lodash'
import { normalizeStories } from './normalize'

import type {
  Story,
  Blog,
  QueryParams,
  PageInfo,
  Screen,
  Article,
} from '../types'

const host =
  process.env.NODE_ENV == 'development'
    ? // ? 'http://localhost:3001'
      'https://ssconnect.elzup.com'
    : 'https://ssconnect.elzup.com'
const TIMEOUT = 1000

const api = create({
  baseURL: host,
  timeout: TIMEOUT,
})

function permitQuery(screen: Screen): QueryParams {
  switch (screen.type) {
    case 'new': {
      const { page } = screen
      return { page, tag: '', q: '' }
    }
    case 'search': {
      const { page, tag, q } = screen
      return { page, tag, q }
    }
    default: {
      // NOTE: Why can remove?
      return { page: 0, tag: '', q: '' }
    }
  }
}

type GetStoriesCallback = ({
  stories: Story[],
  articles: Article[],
  blogs: Blog[],
}) => void

export function getStories(
  screen: Screen,
  cb: GetStoriesCallback,
  timeout: number = TIMEOUT
) {
  const params = permitQuery(screen)
  const res = api.get('/v1/stories', params).then(res => {
    // { stories: res.data, pageInfo: FeedClient.getPageInfo(res) }
    const normalizedData = normalizeStories(res.data)
    const camelizedData = camelcaseKeys(normalizedData, { deep: true })
    cb(_.mapValues(camelizedData.entities, _.values))
  })
}

function getPageInfo(res: any): PageInfo {
  return {
    page: parseInt(res.headers['x-page'], 10),
    total: parseInt(res.headers['x-total-pages'], 10),
    next: parseInt(res.headers['x-next-page'], 10) || false,
    prev: parseInt(res.headers['x-prev-page'], 10) || false,
  }
}
<|endoftext|>


<commit_before>/*!
 * jQuery UI Selectmenu @VERSION
 * http://jqueryui.com
 *
 * Copyright 2012 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectmenu
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 *	jquery.ui.menu.js
 */
(function( $, undefined ) {

$.widget( "ui.selectmenu", {
	version: "@VERSION",
	defaultElement: "<select>",
	options: {
		dropdown: true,
		appendTo: "body",
		position: {
			my: "left top",
			at: "left bottom",
			collision: "none"
		},
		// callbacks
		open: null,
		focus: null,
		select: null,
		close: null,
		change: null
	},

	_create: function() {
		// make / set unique id
		var selectmenuId = this.element.uniqueId().attr( 'id' );

		// array of button and menu id's
		this.ids = { id: selectmenuId, button: selectmenuId + '-button', menu: selectmenuId + '-menu' };

		this._drawButton();
		this._on( this.button, this._buttonEvents );
		this._hoverable( this.button );
		this._focusable( this.button );

		this._drawMenu();

		// document click closes menu
		this._on( document, {
			click: function( event ) {
				if ( this.isOpen && !$( event.target ).closest( "li.ui-state-disabled, li.ui-selectmenu-optgroup, #" + this.ids.button ).length ) {
					this.close( event );
				}
			}
		});

		if ( this.options.disabled ) {
			this.disable();
		}
	},

	_drawButton: function() {
		var tabindex = this.element.attr( 'tabindex' );

		// fix existing label
		this.label = $( "label[for='" + this.ids.id + "']" ).attr( "for", this.ids.button );
		// catch click event of the label
		this._on( this.label, {
			'click':  function( event ) {
				this.button.focus();
				event.preventDefault();
			}
		});

		// hide original select tag
		this.element.hide();

		// create button
		this.button = $( '<a />', {
			'class': 'ui-button ui-widget ui-state-default ui-corner-all',
			href: '#' + this.ids.id,
			tabindex: ( tabindex ? tabindex : this.options.disabled ? -1 : 0 ),
			id: this.ids.button,
			width: this.element.outerWidth(),
			role: 'combobox',
			'aria-expanded': false,
			'aria-autocomplete': 'list',
			'aria-owns': this.ids.menu,
			'aria-haspopup': true
		});

		this.button.prepend( $( '<span class="ui-icon ' + ( this.options.dropdown ? 'ui-icon-triangle-1-s' : 'ui-icon-triangle-2-n-s' ) + '"/>' ) );

		this.buttonText = $( '<span />', {
				'class': 'ui-selectmenu-text' ,
				html: this.element.find( "option:selected" ).text() || ' '
			})
			.appendTo( this.button );

		// wrap and insert new button
		this.buttonWrap = $( '<span />', {
				'class': 'ui-selectmenu-button'
			})
			.append( this.button )
			.insertAfter( this.element );
	},

	_drawMenu: function() {
		var menuInstance,
			that = this;

		// create menu portion, append to body
		this.menu = $( '<ul />', {
			'aria-hidden': true,
			'aria-labelledby': this.ids.button,
			id: this.ids.menu
		});

		// wrap menu
		this.menuWrap = $( '<div />', {
				'class': 'ui-selectmenu-menu',
				width: ( this.options.dropdown ) ? this.button.outerWidth() : this.buttonText.width() + parseFloat( this.buttonText.css( "padding-left" ) ) || 0 + parseFloat( this.buttonText.css( "margin-left" ) ) || 0
			})
			.append( this.menu )
			.appendTo( this.options.appendTo );

		// init menu widget
		menuInstance = this.menu.menu({
			select: function( event, ui ) {
				var item = ui.item.data( "ui-selectmenu-item" );

				that._select( item, event );

				if ( that.isOpen ) {
					event.preventDefault();
					that.close( event );
				}
			},
			focus: function( event, ui ) {
				var item = ui.item.data( "ui-selectmenu-item" );

				if ( that.focus !== undefined ) {
					if ( item.index !== that.focus ) {
						that._trigger( "focus", event, { item: item } );
						if ( !that.isOpen ) {
							that._select( item, event );
						}
					}
				}
				that.focus = item.index;

				// Set ARIA active decendent
				that.button.attr( "aria-activedescendant", that.menuItems.eq( item.index ).find( "a" ).attr( "id" ) );
			},
			// set ARIA role
			role: 'listbox'
		})
		.data( "ui-menu" );

		// change menu styles?
		if ( this.options.dropdown ) {
			this.menu.addClass( 'ui-corner-bottom' ).removeClass( 'ui-corner-all' );
		}

		// make sure focus stays on selected item
		menuInstance.delay = 999999999;
		// unbind uneeded Menu events
		menuInstance._off( this.menu, "mouseleave" );
	},

	refresh: function() {
		this.menu.empty();

		var item,
			options = this.element.find( 'option' );
		if ( options.length ) {
			this._readOptions( options );
			this._renderMenu( this.menu, this.items );

			this.menu.menu( "refresh" );
			this.menuItems = this.menu.find( "li" ).not( '.ui-selectmenu-optgroup' );

			// select current item
			item = this._getSelectedItem();
			this.menu.menu( "focus", null, item );
			this._setSelected( item.data( "ui-selectmenu-item" ) );

			// set disabled state
			this._setOption( "disabled", this._getCreateOptions().disabled );
		}
	},

	open: function( event ) {
		if ( !this.options.disabled ) {
			// make sure menu is refreshed on first init (needed at least for IE9)
			if ( this.isOpen === undefined ) {
				this.button.trigger( "focus" );
			}

			this.isOpen = true;
			this._toggleAttr();
			this.menu.menu( "focus", event, this._getSelectedItem() );

			if ( this.items && !this.options.dropdown ) {
				var currentItem = this._getSelectedItem();
				// center current item
				if ( this.menu.outerHeight() < this.menu.prop( "scrollHeight" ) ) {
					this.menuWrap.css( "left" , -10000 );
					this.menu.scrollTop( this.menu.scrollTop() + currentItem.position().top - this.menu.outerHeight() / 2 + currentItem.outerHeight() / 2 );
					this.menuWrap.css( "left" , "auto" );
				}

				$.extend( this.options.position, {
					my: "left top",
					at: "left top",
					// calculate offset
					offset: "0 " + ( this.menu.offset().top  - currentItem.offset().top + ( this.button.outerHeight() - currentItem.outerHeight() ) / 2 )
				});
			}

			this.options.position.of = this.button;
			this.menuWrap
				.zIndex( this.element.zIndex() + 1 )
				.position( this.options.position );

			this._trigger( "open", event );
		}
	},

	close: function( event ) {
		if ( this.isOpen ) {
			var id = this._getSelectedItem().find( "a" ).attr( "id" );
			this.isOpen = false;
			this._toggleAttr();
			this.button.attr( "aria-activedescendant", id );
			this.menu.attr( "aria-activedescendant", id );
			this._trigger( "close", event );
		}
	},

	widget: function() {
		return this.button;
	},

	menuWidget: function() {
		return this.menu;
	},

	_renderMenu: function( ul, items ) {
		var that = this,
			currentOptgroup = "";

		$.each( items, function( index, item ) {
			if ( item.optgroup !== currentOptgroup ) {
				$( '<li />', {
					'class': 'ui-selectmenu-optgroup' + ( item.element.parent( "optgroup" ).attr( "disabled" ) ? ' ui-state-disabled' : '' ),
					html: item.optgroup
				}).appendTo( ul );
				currentOptgroup = item.optgroup;
			}
			that._renderItem( ul, item );
		});
	},

	_renderItem: function( ul, item ) {
		var li = $( "<li />" ).data( "ui-selectmenu-item", item );
		if ( item.disabled ) {
			li.addClass( 'ui-state-disabled' );
		}
		li.append( $( "<a />", {
				html: item.label,
				href: '#'
			})
		);

		return li.appendTo( ul );
	},

	_move: function( direction, event ) {
		if ( direction === "first" || direction === "last" ) {
			// set focus manually for first or last item
			this.menu.menu( "focus", event, this.menuItems[ direction ]() );
		} else {
			// move to and focus next or prev item
			this.menu.menu( direction, event );
		}
	},

	_getSelectedItem: function() {
		return this.menuItems.eq( this.element[ 0 ].selectedIndex );
	},

	_toggle: function( event ) {
		if ( this.isOpen ) {
			this.close( event );
		} else {
			this.open( event );
		}
	},

	_buttonEvents: {
		focus: function( event ) {
			// init Menu on first focus
			this.refresh();
			// reset focus class as its removed by ui.widget._setOption
			this.button.addClass( "ui-state-focus" );
			this._off( this.button, "focus" );
		},
		click: function( event ) {
			this._toggle( event );
			event.preventDefault();
		},
		keydown: function( event ) {
			var prevDef = true;
			switch ( event.keyCode ) {
				case $.ui.keyCode.TAB:
				case $.ui.keyCode.ESCAPE:
					if ( this.isOpen ) {
						this.close( event );
					}
					prevDef = false;
					break;
				case $.ui.keyCode.ENTER:
					if ( this.isOpen ) {
						this.menu.menu( "select", event );
					}
					break;
				case $.ui.keyCode.UP:
					if ( event.altKey ) {
						this._toggle( event );
					} else {
						this._move( "previous", event );
					}
					break;
				case $.ui.keyCode.DOWN:
					if ( event.altKey ) {
						this._toggle( event );
					} else {
						this._move( "next", event );
					}
					break;
				case $.ui.keyCode.SPACE:
					this._toggle( event );
					break;
				case $.ui.keyCode.LEFT:
					this._move( "previous", event );
					break;
				case $.ui.keyCode.RIGHT:
					this._move( "next", event );
					break;
				case $.ui.keyCode.HOME:
				case $.ui.keyCode.PAGE_UP:
					this._move( "first", event );
					break;
				case $.ui.keyCode.END:
				case $.ui.keyCode.PAGE_DOWN:
					this._move( "last", event );
					break;
				default:
					this.menu.trigger( event );
					prevDef = false;
			}
			if ( prevDef ) {
				event.preventDefault();
			}
		}
	},

	_select: function( item, event ) {
		var oldIndex = this.element[ 0 ].selectedIndex;
		// change native select element
		this.element[ 0 ].selectedIndex = item.index;
		this._setSelected( item );
		this._trigger( "select", event, { item: item } );

		if ( item.index !== oldIndex ) {
			this._trigger( "change", event, { item: item } );
		}
	},

	_setSelected: function( item ) {
		// update button text
		this.buttonText.html( item.label );
		// change ARIA attr
		this.menuItems.find( "a" ).attr( "aria-selected", false );
		this._getSelectedItem().find( "a" ).attr( "aria-selected", true );
		this.button.attr( "aria-labelledby", this.menuItems.eq( item.index ).find( "a" ).attr( "id" ) );
	},

	_setOption: function( key, value ) {
		this._super( key, value );

		if ( key === "appendTo" ) {
			this.menuWrap.appendTo( $( value || "body", this.element[ 0 ].ownerDocument )[ 0 ] );
		}
		if ( key === "disabled" ) {
			this.menu.menu( "option", "disabled", value );
			if ( value ) {
				this.element.attr( "disabled", "disabled" );
				this.button.attr( "tabindex", -1 );
				this.close();
			} else {
				this.element.removeAttr( "disabled" );
				this.button.attr( "tabindex", 0 );
			}
		}
	},

	_toggleAttr: function(){
		if ( this.options.dropdown ) {
			this.button.toggleClass( 'ui-corner-top', this.isOpen ).toggleClass( 'ui-corner-all', !this.isOpen );
		}
		this.menuWrap.toggleClass( 'ui-selectmenu-open', this.isOpen );
		this.menu.attr("aria-hidden", !this.isOpen);
		this.button.attr("aria-expanded", this.isOpen);
	},

	_getCreateOptions: function() {
		return { disabled: !!this.element.attr( 'disabled' ) };
	},

	_readOptions: function( options ) {
		var data = [];
		$.each( options, function( index, item ) {
			var option = $( item ),
				optgroup = option.parent( "optgroup" );
			data.push({
				element: option,
				index: index,
				value: option.attr( 'value' ),
				label: option.text() || ' ',
				optgroup: optgroup.attr( "label" ) || "",
				disabled: optgroup.attr( "disabled" ) || option.attr( "disabled" )
			});
		});
		this.items = data;
	},

	_destroy: function() {
		this.menuWrap.remove();
		this.buttonWrap.remove();
		this.element.show();
		this.element.removeUniqueId();
		this.label.attr( "for", this.ids.id );
	}
});

}( jQuery ));
<commit_msg>Selectmenu: cleanup, CGL and lint fix<commit_after>/*!
 * jQuery UI Selectmenu @VERSION
 * http://jqueryui.com
 *
 * Copyright 2012 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Selectmenu
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 *	jquery.ui.menu.js
 */
(function( $, undefined ) {

$.widget( "ui.selectmenu", {
	version: "@VERSION",
	defaultElement: "<select>",
	options: {
		dropdown: true,
		appendTo: "body",
		position: {
			my: "left top",
			at: "left bottom",
			collision: "none"
		},
		// callbacks
		open: null,
		focus: null,
		select: null,
		close: null,
		change: null
	},

	_create: function() {
		// make / set unique id
		var selectmenuId = this.element.uniqueId().attr( "id" );

		// array of button and menu id's
		this.ids = { id: selectmenuId, button: selectmenuId + "-button", menu: selectmenuId + "-menu" };

		this._drawButton();
		this._on( this.button, this._buttonEvents );
		this._hoverable( this.button );
		this._focusable( this.button );

		this._drawMenu();

		// document click closes menu
		this._on( document, {
			click: function( event ) {
				if ( this.isOpen && !$( event.target ).closest( "li.ui-state-disabled, li.ui-selectmenu-optgroup, #" + this.ids.button ).length ) {
					this.close( event );
				}
			}
		});

		if ( this.options.disabled ) {
			this.disable();
		}
	},

	_drawButton: function() {
		var tabindex = this.element.attr( "tabindex" );

		// fix existing label
		this.label = $( "label[for='" + this.ids.id + "']" ).attr( "for", this.ids.button );
		// catch click event of the label
		this._on( this.label, {
			"click":  function( event ) {
				this.button.focus();
				event.preventDefault();
			}
		});

		// hide original select tag
		this.element.hide();

		// create button
		this.button = $( "<a />", {
			"class": "ui-button ui-widget ui-state-default ui-corner-all",
			href: "#" + this.ids.id,
			tabindex: ( tabindex ? tabindex : this.options.disabled ? -1 : 0 ),
			id: this.ids.button,
			width: this.element.outerWidth(),
			role: "combobox",
			"aria-expanded": false,
			"aria-autocomplete": "list",
			"aria-owns": this.ids.menu,
			"aria-haspopup": true
		});

		this.button.prepend( $( "<span />", {
			"class": "ui-icon " + ( ( this.options.dropdown ) ? "ui-icon-triangle-1-s" : "ui-icon-triangle-2-n-s" )
		}));

		this.buttonText = $( "<span />", {
				"class": "ui-selectmenu-text" ,
				html: this.element.find( "option:selected" ).text() || " "
			})
			.appendTo( this.button );

		// wrap and insert new button
		this.buttonWrap = $( "<span />", {
				"class": "ui-selectmenu-button"
			})
			.append( this.button )
			.insertAfter( this.element );
	},

	_drawMenu: function() {
		var menuInstance,
			that = this;

		// create menu portion, append to body
		this.menu = $( "<ul />", {
			"aria-hidden": true,
			"aria-labelledby": this.ids.button,
			id: this.ids.menu
		});

		// wrap menu
		this.menuWrap = $( "<div />", {
				"class": "ui-selectmenu-menu",
				width: ( this.options.dropdown ) ? this.button.outerWidth() : this.buttonText.width() + parseFloat( this.buttonText.css( "padding-left" ) ) || 0 + parseFloat( this.buttonText.css( "margin-left") ) || 0
			})
			.append( this.menu )
			.appendTo( this.options.appendTo );

		// init menu widget
		menuInstance = this.menu.menu({
			select: function( event, ui ) {
				var item = ui.item.data( "ui-selectmenu-item" );

				that._select( item, event );

				if ( that.isOpen ) {
					event.preventDefault();
					that.close( event );
				}
			},
			focus: function( event, ui ) {
				var item = ui.item.data( "ui-selectmenu-item" );

				if ( that.focus !== undefined ) {
					if ( item.index !== that.focus ) {
						that._trigger( "focus", event, { item: item } );
						if ( !that.isOpen ) {
							that._select( item, event );
						}
					}
				}
				that.focus = item.index;

				// Set ARIA active decendent
				that.button.attr( "aria-activedescendant", that.menuItems.eq( item.index ).find( "a" ).attr( "id" ) );
			},
			// set ARIA role
			role: "listbox"
		})
		.data( "ui-menu" );

		// change menu styles?
		if ( this.options.dropdown ) {
			this.menu.addClass( "ui-corner-bottom" ).removeClass( "ui-corner-all" );
		}

		// make sure focus stays on selected item
		menuInstance.delay = 999999999;
		// unbind uneeded Menu events
		menuInstance._off( this.menu, "mouseleave" );
	},

	refresh: function() {
		this.menu.empty();

		var item,
			options = this.element.find( "option" );
		if ( options.length ) {
			this._readOptions( options );
			this._renderMenu( this.menu, this.items );

			this.menu.menu( "refresh" );
			this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );

			// select current item
			item = this._getSelectedItem();
			this.menu.menu( "focus", null, item );
			this._setSelected( item.data( "ui-selectmenu-item" ) );

			// set disabled state
			this._setOption( "disabled", this._getCreateOptions().disabled );
		}
	},

	open: function( event ) {
		if ( !this.options.disabled ) {
			// make sure menu is refreshed on first init (needed at least for IE9)
			if ( this.isOpen === undefined ) {
				this.button.trigger( "focus" );
			}

			this.isOpen = true;
			this._toggleAttr();
			this.menu.menu( "focus", event, this._getSelectedItem() );

			if ( this.items && !this.options.dropdown ) {
				var currentItem = this._getSelectedItem();
				// center current item
				if ( this.menu.outerHeight() < this.menu.prop( "scrollHeight" ) ) {
					this.menuWrap.css( "left" , -10000 );
					this.menu.scrollTop( this.menu.scrollTop() + currentItem.position().top - this.menu.outerHeight() / 2 + currentItem.outerHeight() / 2 );
					this.menuWrap.css( "left" , "auto" );
				}

				$.extend( this.options.position, {
					my: "left top",
					at: "left top",
					// calculate offset
					offset: "0 " + ( this.menu.offset().top  - currentItem.offset().top + ( this.button.outerHeight() - currentItem.outerHeight() ) / 2 )
				});
			}

			this.options.position.of = this.button;
			this.menuWrap
				.zIndex( this.element.zIndex() + 1 )
				.position( this.options.position );

			this._trigger( "open", event );
		}
	},

	close: function( event ) {
		if ( this.isOpen ) {
			var id = this._getSelectedItem().find( "a" ).attr( "id" );
			this.isOpen = false;
			this._toggleAttr();
			this.button.attr( "aria-activedescendant", id );
			this.menu.attr( "aria-activedescendant", id );
			this._trigger( "close", event );
		}
	},

	widget: function() {
		return this.button;
	},

	menuWidget: function() {
		return this.menu;
	},

	_renderMenu: function( ul, items ) {
		var that = this,
			currentOptgroup = "";

		$.each( items, function( index, item ) {
			if ( item.optgroup !== currentOptgroup ) {
				$( "<li />", {
					"class": "ui-selectmenu-optgroup" + ( item.element.parent( "optgroup" ).attr( "disabled" ) ? " ui-state-disabled" : "" ),
					html: item.optgroup
				}).appendTo( ul );
				currentOptgroup = item.optgroup;
			}
			that._renderItem( ul, item );
		});
	},

	_renderItem: function( ul, item ) {
		var li = $( "<li />" ).data( "ui-selectmenu-item", item );
		if ( item.disabled ) {
			li.addClass( "ui-state-disabled" );
		}
		li.append( $( "<a />", {
				html: item.label,
				href: "#"
			})
		);

		return li.appendTo( ul );
	},

	_move: function( direction, event ) {
		if ( direction === "first" || direction === "last" ) {
			// set focus manually for first or last item
			this.menu.menu( "focus", event, this.menuItems[ direction ]() );
		} else {
			// move to and focus next or prev item
			this.menu.menu( direction, event );
		}
	},

	_getSelectedItem: function() {
		return this.menuItems.eq( this.element[ 0 ].selectedIndex );
	},

	_toggle: function( event ) {
		if ( this.isOpen ) {
			this.close( event );
		} else {
			this.open( event );
		}
	},

	_buttonEvents: {
		focus: function() {
			// init Menu on first focus
			this.refresh();
			// reset focus class as its removed by ui.widget._setOption
			this.button.addClass( "ui-state-focus" );
			this._off( this.button, "focus" );
		},
		click: function( event ) {
			this._toggle( event );
			event.preventDefault();
		},
		keydown: function( event ) {
			var prevDef = true;
			switch ( event.keyCode ) {
				case $.ui.keyCode.TAB:
				case $.ui.keyCode.ESCAPE:
					if ( this.isOpen ) {
						this.close( event );
					}
					prevDef = false;
					break;
				case $.ui.keyCode.ENTER:
					if ( this.isOpen ) {
						this.menu.menu( "select", event );
					}
					break;
				case $.ui.keyCode.UP:
					if ( event.altKey ) {
						this._toggle( event );
					} else {
						this._move( "previous", event );
					}
					break;
				case $.ui.keyCode.DOWN:
					if ( event.altKey ) {
						this._toggle( event );
					} else {
						this._move( "next", event );
					}
					break;
				case $.ui.keyCode.SPACE:
					this._toggle( event );
					break;
				case $.ui.keyCode.LEFT:
					this._move( "previous", event );
					break;
				case $.ui.keyCode.RIGHT:
					this._move( "next", event );
					break;
				case $.ui.keyCode.HOME:
				case $.ui.keyCode.PAGE_UP:
					this._move( "first", event );
					break;
				case $.ui.keyCode.END:
				case $.ui.keyCode.PAGE_DOWN:
					this._move( "last", event );
					break;
				default:
					this.menu.trigger( event );
					prevDef = false;
			}
			if ( prevDef ) {
				event.preventDefault();
			}
		}
	},

	_select: function( item, event ) {
		var oldIndex = this.element[ 0 ].selectedIndex;
		// change native select element
		this.element[ 0 ].selectedIndex = item.index;
		this._setSelected( item );
		this._trigger( "select", event, { item: item } );

		if ( item.index !== oldIndex ) {
			this._trigger( "change", event, { item: item } );
		}
	},

	_setSelected: function( item ) {
		// update button text
		this.buttonText.html( item.label );
		// change ARIA attr
		this.menuItems.find( "a" ).attr( "aria-selected", false );
		this._getSelectedItem().find( "a" ).attr( "aria-selected", true );
		this.button.attr( "aria-labelledby", this.menuItems.eq( item.index ).find( "a" ).attr( "id" ) );
	},

	_setOption: function( key, value ) {
		this._super( key, value );

		if ( key === "appendTo" ) {
			this.menuWrap.appendTo( $( value || "body", this.element[ 0 ].ownerDocument )[ 0 ] );
		}
		if ( key === "disabled" ) {
			this.menu.menu( "option", "disabled", value );
			if ( value ) {
				this.element.attr( "disabled", "disabled" );
				this.button.attr( "tabindex", -1 );
				this.close();
			} else {
				this.element.removeAttr( "disabled" );
				this.button.attr( "tabindex", 0 );
			}
		}
	},

	_toggleAttr: function(){
		if ( this.options.dropdown ) {
			this.button.toggleClass( "ui-corner-top", this.isOpen ).toggleClass( "ui-corner-all", !this.isOpen );
		}
		this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
		this.menu.attr( "aria-hidden", !this.isOpen);
		this.button.attr( "aria-expanded", this.isOpen);
	},

	_getCreateOptions: function() {
		return { disabled: !!this.element.attr( "disabled" ) };
	},

	_readOptions: function( options ) {
		var data = [];
		$.each( options, function( index, item ) {
			var option = $( item ),
				optgroup = option.parent( "optgroup" );
			data.push({
				element: option,
				index: index,
				value: option.attr( "value" ),
				label: option.text() || " ",
				optgroup: optgroup.attr( "label" ) || "",
				disabled: optgroup.attr( "disabled" ) || option.attr( "disabled" )
			});
		});
		this.items = data;
	},

	_destroy: function() {
		this.menuWrap.remove();
		this.buttonWrap.remove();
		this.element.show();
		this.element.removeUniqueId();
		this.label.attr( "for", this.ids.id );
	}
});

}( jQuery ));
<|endoftext|>