<commit_before>const JEST_TIMEOUT_MS = 60 * 1000;

// Print test name at the beginning of each test
jasmine.getEnv().addReporter({
  specStarted: function(result) {
    console.log(result.fullName);
  }
});

describe("End-to-end", () => {
  beforeAll(async () => {
    // It can take a while for servers to start up
    jest.setTimeout(JEST_TIMEOUT_MS);
    await waitForElasticsearchIndex();
  });

  beforeEach(async () => {
    await page.goto("http://localhost:4400");
    await page.waitForSelector(".datasetName");
  });

  test("Header", async () => {
    await expect(page).toMatch("1000 Genomes");
    await assertHeaderTotalCount("3500");
  });

  test("Participant facet", async () => {
    // Assert facet rendered correctly
    await assertFacet("Super Population", "3500", "African", "1018");

    // Click on facet value
    let facetValueRow = await getFacetValueRow("Super Population", "African");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1018);

    // Assert page updated correctly.
    await assertHeaderTotalCount("1018");
    await assertFacet("Gender", "1018", "male", "518");

    // Make sure non-selected facet values are gray.
    facetValueRow = await getFacetValueRow("Super Population", "European");
    const grayDiv = await facetValueRow.$("*[class*='FacetCard-grayText-']");

    expect(grayDiv).toBeTruthy();
  });

  test("Sample facet", async () => {
    // Assert facet rendered correctly
    await assertFacet("Total Low Coverage Sequence", "2688", "0B-10B", "10");

    // Click on facet value
    let facetValueRow = await getFacetValueRow(
      "Total Low Coverage Sequence",
      "10B-20B"
    );
    await facetValueRow.click("input");
    // Wait for data to be returned from backend.
    // See #63 for why we can't wait for .grayText.
    await page.waitForXPath(
      "//*[contains(@class, 'totalCountText') and text() = '1122']"
    );

    // Assert page updated correctly.
    await assertHeaderTotalCount("1122");
    await assertFacet("Gender", "1122", "female", "569");

    // Make sure non-selected facet values are gray.
    facetValueRow = await getFacetValueRow(
      "Total Low Coverage Sequence",
      "0B-10B"
    );
    const grayDiv = await facetValueRow.$("*[class*='FacetCard-grayText-']");
    expect(grayDiv).toBeTruthy();
  });

  test("Samples Overview facet", async () => {
    // Skip asserting facet rendered correctly, because this facet doesn't have
    // totalFacetValueCount span.

    // Click on facet value
    let facetValueRow = await getFacetValueRow(
      "Samples Overview",
      "Has WGS Low Coverage BAM"
    );
    await facetValueRow.click("input");
    await waitForFacetsUpdate(2535);

    // Assert page updated correctly.
    await assertHeaderTotalCount("2535");
    await assertFacet("Gender", "2535", "female", "1291");

    // Make sure non-selected facet values are gray.
    facetValueRow = await getFacetValueRow("Samples Overview", "Has Exome BAM");
    const grayDiv = await facetValueRow.$("*[class*='FacetCard-grayText-']");
    expect(grayDiv).toBeTruthy();

    // Test exporting to saturn.
    await exportToSaturn_selectedCohort();
  });

  test("Export to Saturn - no selected cohort", async () => {
    await exportToSaturn_noSelectedCohort();
  });

  test("Export to Saturn - selected cohort", async () => {
    // Click first Super Population facet value.
    let facetValueRow = await getFacetValueRow("Super Population", "African");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1018);

    await exportToSaturn_selectedCohort();
  });

  test("Search box - click on drop-down row", async () => {
    // Click on the drop down
    let initial_select = await page.$x("//div[text()='Select...']");
    initial_select[0].click();
    // Click on the 'Avuncular' option
    let avuncular_xpath = "//span[text()[contains(., 'Avuncular')]]";
    await page.waitForXPath(avuncular_xpath);
    let avuncular = await page.$x(avuncular_xpath);
    avuncular[0].click();
    // Wait for the facet card to be rendered and then assert.
    await waitForFacetCard("Avuncular");
    await assertFacet("Avuncular", "46", "HG00658 (aunt/uncle)", "1");
  });

  test("Search box - chips", async () => {
    // Select the 'Gender - female' facet value.
    let facetValueRow = await getFacetValueRow("Gender", "female");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1760);

    // Assert chip is added
    await page.waitForXPath("//div[text()='Gender=female']");
    let chip = await page.$x("//div[text()='Gender=female']");
    expect(chip.length).toBe(1);

    // Unselect the 'Gender - female' facet value.
    facetValueRow = await getFacetValueRow("Gender", "female");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(3500);

    // Assert chip is deleted.
    chip = await page.$x("//div[text()='Gender=female']");
    expect(chip.length).toBe(0);

    // Select the 'Gender - female' facet value.
    facetValueRow = await getFacetValueRow("Gender", "female");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1760);

    // Click on 'x' on the chip.
    let chipX = await page.$x(
      "//div[text()[contains(.,'Gender=female')]]/../div[2]"
    );
    chipX[0].click();
    // Assert that female is unselected. (3500 includes males and females).
    await waitForFacetsUpdate(3500);
  });

  async function waitForElasticsearchIndex() {
    var waitOneSec = function() {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve();
        }, 1000);
      });
    };
    const MAX_RETRIES = 60;
    console.log("Waiting for servers to come up and test data to be indexed.");
    for (let i = 0; i <= MAX_RETRIES; i++) {
      try {
        var result = await page.goto(
          "http://localhost:9200/_cluster/health?wait_for_status=yellow"
        );
        // Elasticsearch has come up. Now wait for test data to be indexed.
        await page.goto("http://localhost:9200/1000_genomes/type/_count");
        await page.waitForXPath("//*[contains(text(), '3500')]");
        console.log(
          "Servers up and test data indexed after " + i + " seconds."
        );
        return result;
      } catch (err) {
        await waitOneSec();
      }
    }
    errorMsg =
      "Servers failed to come up/test data failed to be " +
      "indexed after " +
      MAX_RETRIES +
      " seconds.";
    console.log(errorMsg);
    return Promise.reject(errorMsg);
  }

  async function assertHeaderTotalCount(count) {
    // e.innerText looks like "3500 Participants"
    const totalCount = await page.$eval(
      ".totalCountText",
      e => e.innerText.split(" ")[0]
    );
    await expect(totalCount).toBe(count);
  }

  async function assertFacet(
    facetName,
    totalCount,
    firstValueName,
    firstValueCount
  ) {
    const facetCard = await getFacetCard(facetName);

    expect(
      await facetCard.$eval(
        "*[class*='FacetCard-totalFacetValueCount-']",
        node => node.innerText
      )
    ).toBe(totalCount);
    expect(
      await facetCard.$eval(
        "*[class*='FacetCard-facetValueName-']",
        node => node.innerText
      )
    ).toBe(firstValueName);
    expect(
      await facetCard.$eval(
        "*[class*='FacetCard-facetValueCount-']",
        node => node.innerText
      )
    ).toBe(firstValueCount);
  }

  /**
   * Returns Promise of JSHandle of facetValueRow label.
   */
  async function getFacetValueRow(facetName, valueName) {
    let facetCard = await getFacetCard(facetName);
    let facetValueRow = (await page.evaluateHandle(
      (facetCard, valueName) => {
        let divs = facetCard.querySelectorAll("*[class*='MuiListItem-']");
        for (let div of divs) {
          if (div.innerText.includes(valueName)) return div;
        }
        return null;
      },
      facetCard,
      valueName
    )).asElement();
    expect(facetValueRow).toBeTruthy();
    return facetValueRow;
  }

  /**
   * Returns Promise of JSHandle of facetCard div.
   */
  async function getFacetCard(facetName) {
    const facetCard = (await page.evaluateHandle(innerFacetName => {
      const divs = document.querySelectorAll(
        "*[class*='FacetCard-facetCard-']"
      );
      for (const div of divs) {
        const name = div.querySelector("p").innerText;
        if (name.includes(innerFacetName)) return div;
      }
      return null;
    }, facetName)).asElement();
    expect(facetCard).toBeTruthy();
    return facetCard;
  }

  /**
   * Waits for new facets data from backend, and Data Explorer UI to update.
   */
  async function waitForFacetsUpdate(newTotalCount) {
    // See #63 for why we can't wait for .grayText.
    await page.waitForXPath(
      "//*[contains(@class, 'totalCountText') and contains(text(),'" +
        newTotalCount +
        "')]"
    );
  }

  /**
   * Waits for facet card to be rendered.
   */
  async function waitForFacetCard(facetName) {
    await page.waitForXPath("//*[contains(text(),'" + facetName + "')]");
  }

  async function exportToSaturn_noSelectedCohort() {
    await page.click("button[title='Send to Terra']");
    // Jest documentation says to use waitForNavigation():
    // https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageclickselector-options
    // Here we use waitForRequest() instead. waitForRequest() is slightly
    // faster because it doesn't wait for the Saturn page to finish (or start?)
    // loading.
    await page.waitForRequest("https://bvdp-saturn-prod.appspot.com/");
  }

  async function exportToSaturn_selectedCohort() {
    await page.click("button[title='Send to Terra']");
    // Wait for cohort name dialog
    await page.waitForSelector("#name");

    await page.type("#name", "c");
    await page.click("#save");
    await page.waitForRequest("https://bvdp-saturn-prod.appspot.com/");
  }
});
<commit_msg>Test extra facet chip (#235)<commit_after>const JEST_TIMEOUT_MS = 60 * 1000;

// Print test name at the beginning of each test
jasmine.getEnv().addReporter({
  specStarted: function(result) {
    console.log(result.fullName);
  }
});

describe("End-to-end", () => {
  beforeAll(async () => {
    // It can take a while for servers to start up
    jest.setTimeout(JEST_TIMEOUT_MS);
    await waitForElasticsearchIndex();
  });

  beforeEach(async () => {
    await page.goto("http://localhost:4400");
    await page.waitForSelector(".datasetName");
  });

  test("Header", async () => {
    await expect(page).toMatch("1000 Genomes");
    await assertHeaderTotalCount("3500");
  });

  test("Participant facet", async () => {
    // Assert facet rendered correctly
    await assertFacet("Super Population", "3500", "African", "1018");

    // Click on facet value
    let facetValueRow = await getFacetValueRow("Super Population", "African");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1018);

    // Assert page updated correctly.
    await assertHeaderTotalCount("1018");
    await assertFacet("Gender", "1018", "male", "518");

    // Make sure non-selected facet values are gray.
    facetValueRow = await getFacetValueRow("Super Population", "European");
    const grayDiv = await facetValueRow.$("*[class*='FacetCard-grayText-']");

    expect(grayDiv).toBeTruthy();
  });

  test("Sample facet", async () => {
    // Assert facet rendered correctly
    await assertFacet("Total Low Coverage Sequence", "2688", "0B-10B", "10");

    // Click on facet value
    let facetValueRow = await getFacetValueRow(
      "Total Low Coverage Sequence",
      "10B-20B"
    );
    await facetValueRow.click("input");
    // Wait for data to be returned from backend.
    // See #63 for why we can't wait for .grayText.
    await page.waitForXPath(
      "//*[contains(@class, 'totalCountText') and text() = '1122']"
    );

    // Assert page updated correctly.
    await assertHeaderTotalCount("1122");
    await assertFacet("Gender", "1122", "female", "569");

    // Make sure non-selected facet values are gray.
    facetValueRow = await getFacetValueRow(
      "Total Low Coverage Sequence",
      "0B-10B"
    );
    const grayDiv = await facetValueRow.$("*[class*='FacetCard-grayText-']");
    expect(grayDiv).toBeTruthy();
  });

  test("Samples Overview facet", async () => {
    // Skip asserting facet rendered correctly, because this facet doesn't have
    // totalFacetValueCount span.

    // Click on facet value
    let facetValueRow = await getFacetValueRow(
      "Samples Overview",
      "Has WGS Low Coverage BAM"
    );
    await facetValueRow.click("input");
    await waitForFacetsUpdate(2535);

    // Assert page updated correctly.
    await assertHeaderTotalCount("2535");
    await assertFacet("Gender", "2535", "female", "1291");

    // Make sure non-selected facet values are gray.
    facetValueRow = await getFacetValueRow("Samples Overview", "Has Exome BAM");
    const grayDiv = await facetValueRow.$("*[class*='FacetCard-grayText-']");
    expect(grayDiv).toBeTruthy();

    // Test exporting to saturn.
    await exportToSaturn_selectedCohort();
  });

  test("Export to Saturn - no selected cohort", async () => {
    await exportToSaturn_noSelectedCohort();
  });

  test("Export to Saturn - selected cohort", async () => {
    // Click first Super Population facet value.
    let facetValueRow = await getFacetValueRow("Super Population", "African");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1018);

    await exportToSaturn_selectedCohort();
  });

  test("Search box - click on drop-down row", async () => {
    // Click on Avuncular from drop-down
    let initial_select = await page.$x("//div[text()='Select...']");
    initial_select[0].click();
    let avuncular_xpath = "//span[text()[contains(., 'Avuncular')]]";
    await page.waitForXPath(avuncular_xpath);
    let avuncular = await page.$x(avuncular_xpath);
    avuncular[0].click();

    // Assert Avuncular facet is added
    await waitForFacetCard("Avuncular");
    await assertFacet("Avuncular", "46", "HG00658 (aunt/uncle)", "1");

    // Select first Avuncular facet value
    let facetValueRow = await getFacetValueRow(
      "Avuncular",
      "HG00658 (aunt/uncle)"
    );
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1);

    // Assert chip is added
    await waitForChip("Avuncular=HG00658 (aunt/uncle)");
  });

  test("Search box - chips", async () => {
    // Select the 'Gender - female' facet value.
    let facetValueRow = await getFacetValueRow("Gender", "female");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1760);

    // Assert chip is added
    await waitForChip("Gender=female");

    // Unselect the 'Gender - female' facet value.
    facetValueRow = await getFacetValueRow("Gender", "female");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(3500);

    // Assert chip is deleted.
    chip = await page.$x("//div[text()='Gender=female']");
    expect(chip.length).toBe(0);

    // Select the 'Gender - female' facet value.
    facetValueRow = await getFacetValueRow("Gender", "female");
    await facetValueRow.click("input");
    await waitForFacetsUpdate(1760);

    // Click on 'x' on the chip.
    let chipX = await page.$x(
      "//div[text()[contains(.,'Gender=female')]]/../div[2]"
    );
    chipX[0].click();
    // Assert that female is unselected. (3500 includes males and females).
    await waitForFacetsUpdate(3500);
  });

  async function waitForElasticsearchIndex() {
    var waitOneSec = function() {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve();
        }, 1000);
      });
    };
    const MAX_RETRIES = 60;
    console.log("Waiting for servers to come up and test data to be indexed.");
    for (let i = 0; i <= MAX_RETRIES; i++) {
      try {
        var result = await page.goto(
          "http://localhost:9200/_cluster/health?wait_for_status=yellow"
        );
        // Elasticsearch has come up. Now wait for test data to be indexed.
        await page.goto("http://localhost:9200/1000_genomes/type/_count");
        await page.waitForXPath("//*[contains(text(), '3500')]");
        console.log(
          "Servers up and test data indexed after " + i + " seconds."
        );
        return result;
      } catch (err) {
        await waitOneSec();
      }
    }
    errorMsg =
      "Servers failed to come up/test data failed to be " +
      "indexed after " +
      MAX_RETRIES +
      " seconds.";
    console.log(errorMsg);
    return Promise.reject(errorMsg);
  }

  async function assertHeaderTotalCount(count) {
    // e.innerText looks like "3500 Participants"
    const totalCount = await page.$eval(
      ".totalCountText",
      e => e.innerText.split(" ")[0]
    );
    await expect(totalCount).toBe(count);
  }

  async function assertFacet(
    facetName,
    totalCount,
    firstValueName,
    firstValueCount
  ) {
    const facetCard = await getFacetCard(facetName);

    expect(
      await facetCard.$eval(
        "*[class*='FacetCard-totalFacetValueCount-']",
        node => node.innerText
      )
    ).toBe(totalCount);
    expect(
      await facetCard.$eval(
        "*[class*='FacetCard-facetValueName-']",
        node => node.innerText
      )
    ).toBe(firstValueName);
    expect(
      await facetCard.$eval(
        "*[class*='FacetCard-facetValueCount-']",
        node => node.innerText
      )
    ).toBe(firstValueCount);
  }

  /**
   * Returns Promise of JSHandle of facetValueRow label.
   */
  async function getFacetValueRow(facetName, valueName) {
    let facetCard = await getFacetCard(facetName);
    let facetValueRow = (await page.evaluateHandle(
      (facetCard, valueName) => {
        let divs = facetCard.querySelectorAll("*[class*='MuiListItem-']");
        for (let div of divs) {
          if (div.innerText.includes(valueName)) return div;
        }
        return null;
      },
      facetCard,
      valueName
    )).asElement();
    expect(facetValueRow).toBeTruthy();
    return facetValueRow;
  }

  /**
   * Returns Promise of JSHandle of facetCard div.
   */
  async function getFacetCard(facetName) {
    const facetCard = (await page.evaluateHandle(innerFacetName => {
      const divs = document.querySelectorAll(
        "*[class*='FacetCard-facetCard-']"
      );
      for (const div of divs) {
        const name = div.querySelector("p").innerText;
        if (name.includes(innerFacetName)) return div;
      }
      return null;
    }, facetName)).asElement();
    expect(facetCard).toBeTruthy();
    return facetCard;
  }

  /**
   * Waits for new facets data from backend, and Data Explorer UI to update.
   */
  async function waitForFacetsUpdate(newTotalCount) {
    // See #63 for why we can't wait for .grayText.
    await page.waitForXPath(
      "//*[contains(@class, 'totalCountText') and contains(text(),'" +
        newTotalCount +
        "')]"
    );
  }

  /**
   * Waits for facet card to be rendered.
   */
  async function waitForFacetCard(facetName) {
    await page.waitForXPath("//*[contains(text(),'" + facetName + "')]");
  }

  async function waitForChip(chipText) {
    await page.waitForXPath("//div[text()='" + chipText + "']");
  }

  async function exportToSaturn_noSelectedCohort() {
    await page.click("button[title='Send to Terra']");
    // Jest documentation says to use waitForNavigation():
    // https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageclickselector-options
    // Here we use waitForRequest() instead. waitForRequest() is slightly
    // faster because it doesn't wait for the Saturn page to finish (or start?)
    // loading.
    await page.waitForRequest("https://bvdp-saturn-prod.appspot.com/");
  }

  async function exportToSaturn_selectedCohort() {
    await page.click("button[title='Send to Terra']");
    // Wait for cohort name dialog
    await page.waitForSelector("#name");

    await page.type("#name", "c");
    await page.click("#save");
    await page.waitForRequest("https://bvdp-saturn-prod.appspot.com/");
  }
});
<|endoftext|>


<commit_before>/*
 * jQuery UI ProgressBar @VERSION
 *
 * Copyright (c) 2008 Eduardo Lundgren
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/ProgressBar
 *
 * Depends:
 *   ui.core.js
 */
(function($) {

$.widget("ui.progressbar", {
	_init: function() {

		this._interval = this.options.interval;

		var self = this,
			options = this.options,
			id = (new Date()).getTime()+Math.random(),
			text = options.text || '0%';

		this.element.addClass("ui-progressbar").width(options.width);

		$.extend(this, {
			active: false,
			pixelState: 0,
			percentState: 0,
			identifier: id,
			bar: $('

').css({
				width: '0px', overflow: 'hidden', zIndex: 100
			}),
			textElement: $('

').html(text).css({
				width: '0px', overflow: 'hidden'
			}),
			textBg: $('

').html(text).css({
					width: this.element.width()
			}),
			wrapper: $('

')
		});

		this.wrapper
			.append(this.bar.append(this.textElement.addClass(options.textClass)), this.textBg)
			.appendTo(this.element);
	},

	plugins: {},
	ui: function(e) {
		return {
			instance: this,
			identifier: this.identifier,
			options: this.options,
			element: this.bar,
			textElement: this.textElement,
			pixelState: this.pixelState,
			percentState: this.percentState
		};
	},

	_propagate: function(n,e) {
		$.ui.plugin.call(this, n, [e, this.ui()]);
		this.element.triggerHandler(n == "progressbar" ? n : ["progressbar", n].join(""), [e, this.ui()], this.options[n]);
	},

	destroy: function() {
		this.stop();

		this.element
			.removeClass("ui-progressbar ui-progressbar-disabled")
			.removeData("progressbar").unbind(".progressbar")
			.find('.ui-progressbar-wrap').remove();

		delete jQuery.easing[this.identifier];
	},

	enable: function() {
		this.element.removeClass("ui-progressbar-disabled");
		this.disabled = false;
	},

	disable: function() {
		this.element.addClass("ui-progressbar-disabled");
		this.disabled = true;
	},

	start: function() {
		var self = this, options = this.options;

		if (this.disabled) {
			return;
		}

		jQuery.easing[this.identifier] = function (x, t, b, c, d) {
			var inc = options.increment,
				width = options.width,
				step = ((inc > width ? width : inc)/width),
				state = Math.round(x/step)*step;
			return state > 1 ? 1 : state;
		};

		self.active = true;

		if (options.duration < options.interval) {
			options.duration = options.interval;
		}

		setTimeout(
			function() {
				self.active = false;
			},
			options.duration
		);

		this._animate();

		this._propagate('start', this.ui());
		return false;
	},

	_animate: function() {
		var self = this,
			options = this.options,
			interval = options.interval;

		this.bar.animate(
			{
				width: options.width
			},
			{
				duration: interval,
				easing: options.equation || this.identifier,
				step: function(step, b) {
					self.progress((step/options.width)*100);
					var timestamp = new Date().getTime(), elapsedTime  = (timestamp - b.startTime);
					options.interval = interval - elapsedTime;
				},
				complete: function() {
					if (self.active) {
						options.interval = self._interval;
						self.bar.width(0);
						self.textElement.width(0);
						self._animate();
					}
					else {
						delete jQuery.easing[self.identifier];
					}
				}
			}
		);
	},

	pause: function() {
		if (this.disabled) return;
		this.bar.stop();
		this._propagate('pause', this.ui());
	},

	stop: function() {
		this.bar.stop();
		this.bar.width(0);
		this.textElement.width(0);
		this.bar.addClass('ui-hidden');
		this.options.interval = this._interval;
		this._propagate('stop', this.ui());
	},

	text: function(text){
		this.textElement.html(text);
		this.textBg.html(text);
	},

	progress: function(percentState) {
		if (this.bar.is('.ui-hidden')) {
			this.bar.removeClass('ui-hidden');
		}

		this.percentState = percentState > 100 ? 100 : percentState;
		this.pixelState = (this.percentState/100)*this.options.width;
		this.bar.width(this.pixelState);
		this.textElement.width(this.pixelState);

		if (this.options.range && !this.options.text) {
			this.textElement.html(Math.round(this.percentState) + '%');
		}
		this._propagate('progress', this.ui());
	}
});

$.ui.progressbar.defaults = {
	width: 300,
	duration: 1000,
	interval: 1000,
	increment: 1,
	range: true,
	text: '',
	addClass: '',
	textClass: ''
};

})(jQuery);
<commit_msg>Progressbar - Source formatting<commit_after>/*
 * jQuery UI ProgressBar @VERSION
 *
 * Copyright (c) 2008 Eduardo Lundgren
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/ProgressBar
 *
 * Depends:
 *   ui.core.js
 */
(function($) {

$.widget("ui.progressbar", {
	_init: function() {

		this._interval = this.options.interval;

		var self = this,
			options = this.options,
			id = ((new Date()).getTime() + Math.random()),
			text = options.text || '0%';

		this.element.addClass("ui-progressbar").width(options.width);

		$.extend(this, {
			active: false,
			pixelState: 0,
			percentState: 0,
			identifier: id,
			bar: $('

').css({
				width: '0px', overflow: 'hidden', zIndex: 100
			}),
			textElement: $('

').html(text).css({
				width: '0px', overflow: 'hidden'
			}),
			textBg: $('

').html(text).css({
					width: this.element.width()
			}),
			wrapper: $('

')
		});

		this.wrapper
			.append(this.bar.append(this.textElement.addClass(options.textClass)), this.textBg)
			.appendTo(this.element);
	},

	plugins: {},
	ui: function(e) {
		return {
			instance: this,
			identifier: this.identifier,
			options: this.options,
			element: this.bar,
			textElement: this.textElement,
			pixelState: this.pixelState,
			percentState: this.percentState
		};
	},

	_propagate: function(n,e) {
		$.ui.plugin.call(this, n, [e, this.ui()]);
		this.element.triggerHandler(n == "progressbar" ? n : ["progressbar", n].join(""), [e, this.ui()], this.options[n]);
	},

	destroy: function() {
		this.stop();

		this.element
			.removeClass("ui-progressbar ui-progressbar-disabled")
			.removeData("progressbar").unbind(".progressbar")
			.find('.ui-progressbar-wrap').remove();

		delete jQuery.easing[this.identifier];
	},

	enable: function() {
		this.element.removeClass("ui-progressbar-disabled");
		this.disabled = false;
	},

	disable: function() {
		this.element.addClass("ui-progressbar-disabled");
		this.disabled = true;
	},

	start: function() {
		var self = this, options = this.options;

		if (this.disabled) {
			return;
		}

		jQuery.easing[this.identifier] = function (x, t, b, c, d) {
			var inc = options.increment,
				width = options.width,
				step = ((inc > width ? width : inc)/width),
				state = Math.round(x/step)*step;
			return state > 1 ? 1 : state;
		};

		self.active = true;

		if (options.duration < options.interval) {
			options.duration = options.interval;
		}

		setTimeout(
			function() {
				self.active = false;
			},
			options.duration
		);

		this._animate();

		this._propagate('start', this.ui());
		return false;
	},

	_animate: function() {
		var self = this,
			options = this.options,
			interval = options.interval;

		this.bar.animate(
			{
				width: options.width
			},
			{
				duration: interval,
				easing: options.equation || this.identifier,
				step: function(step, b) {
					var timestamp = new Date().getTime(), elapsedTime  = (timestamp - b.startTime);
					self.progress( (step/options.width) * 100 );
					options.interval = interval - elapsedTime;
				},
				complete: function() {
					if (self.active) {
						options.interval = self._interval;
						self.bar.width(0);
						self.textElement.width(0);
						self._animate();
					}
					else {
						delete jQuery.easing[self.identifier];
					}
				}
			}
		);
	},

	pause: function() {
		if (this.disabled) return;
		this.bar.stop();
		this._propagate('pause', this.ui());
	},

	stop: function() {
		this.bar.stop();
		this.bar.width(0);
		this.textElement.width(0);
		this.bar.addClass('ui-hidden');
		this.options.interval = this._interval;
		this._propagate('stop', this.ui());
	},

	text: function(text){
		this.textElement.html(text);
		this.textBg.html(text);
	},

	progress: function(percentState) {
		if (this.bar.is('.ui-hidden')) {
			this.bar.removeClass('ui-hidden');
		}

		this.percentState = percentState > 100 ? 100 : percentState;
		this.pixelState = (this.percentState/100) * this.options.width;
		this.bar.width(this.pixelState);
		this.textElement.width(this.pixelState);

		if (this.options.range && !this.options.text) {
			this.textElement.html(Math.round(this.percentState) + '%');
		}
		this._propagate('progress', this.ui());
	}
});

$.ui.progressbar.defaults = {
	width: 300,
	duration: 1000,
	interval: 1000,
	increment: 1,
	range: true,
	text: '',
	addClass: '',
	textClass: ''
};

})(jQuery);
<|endoftext|>


<commit_before>"use strict";
define(['../objects/View'],function(view){
	return view.extend({
		_columnsConfig:null,
		_filterConfig:null,
		_paginatorConfig:null,
		_actions:null,
		metadata:null,
		_recordActions:null,
		_dataGridEL:'.data-grid',
		collection:null,
		elements:{},
		initialize:function(){
			this.template = _.template(this.template);
		 	this.collection = new this.collection();
			this.metadata = openbiz.MetadataParser.call(this,this.metadata)
			openbiz.View.prototype.initialize.apply(this);
			return this;
		},
		_bindEvents:function(){
			this.undelegateEvents();
			var actions = this._getActions();
			for (var i in actions){
				var action = actions[i];
				var key = action.event + " ." + "act-"+action.name.toLowerCase();
				this.events[key] = action.function;
			}
			var recordActions = this._getRecordActions();
			for (var i in recordActions){
				var recordAction = recordActions[i];
				if(typeof recordAction.function != 'undefined' && recordAction.function)
				{
					var key = recordAction.event + " ." + "rec-act-"+recordAction.name.toLowerCase();
					this.events[key] = recordAction.function;
				}
			}
			this.delegateEvents();
			return this;
		},
		beforeRender:function(){},
		afterRender:function(){},
		render:function(){
			console.log(this.collection);
			$(window).off('resize');
			openbiz.ui.update($(this.el));
			if(this._canDisplayView())
			{
				this.beforeRender();
				$(this.el).html(this.template(this.locale));
				this._renderDataGridConfig()._bindEvents();
				this.afterRender();
			}
			else
			{
				this._renderNoPermissionView();
			}
		},
		_renderDataGridConfig:function(){
			var columns = [];
			var columnConfigs = this._getColumnsConfig();
			for (var i in columnConfigs){
				var column = columnConfigs[i];
				if(this._canDisplayColumn(column)){
					var type = column['type'];
					if(typeof  type == 'undefined' || type == null){
						type = 'text';
					}
					var field;
					if(this.elements[type]){
						field = this.elements[type].getConfig(this,column,this._getRecordActions());
					}
					else{
						field = openbiz.elements.columns[type].getConfig(this,column,this._getRecordActions());
					}
					if(field != null){
						columns.push(field);
					}
				}
			}
			if(this._getFilterConfig()){
				var filter = new Backgrid.Extension.ServerSideFilter({
					collection: this.collection,
					name: "query",
					placeholder: ""
				});
				$(this.el).find(this._dataGridEL).append(filter.render().el);
			}
			var grid = new Backgrid.Grid({
				columns:columns,
				collection: this.collection,
				className: 'backgrid table table-striped table-bordered text-center',
				emptyText: this.metadata.gridEmptyText
			});
			$(this.el).find(this._dataGridEL).append(grid.render().el);
			if(this._getPaginatorConfig()){
				var paginator = new Backgrid.Extension.Paginator({
					windowSize: 10,
					slideScale: 0.5,
					goBackFirstOnSort: true,
					collection: this.collection,
					className:'pagination'
				});
				$(this.el).find(this._dataGridEL).append(paginator.render().el);
			}
			this.collection.fetch();
			return this;
		},
		_renderNoPermissionView:function(){
			//render 403 page
		},
		_canDisplayView:function(){
			if(typeof this.metadata.permission == 'undefined' || this.metadata.permission == null){
				return true;
			}
			return openbiz.session.me.hasPermission(this.metadata.permission);
		},
		_canDisplayColumn:function(column){
			if(typeof column.permission != 'undefined' && column.permission)
				return openbiz.session.me.hasPermission(column.permission);
			return true;
		},
		_getRecordActions:function(){
			if(! this._recordActions){
				this._recordActions = this.metadata.recordActions;
			}
			return this._recordActions;
		},
		_getActions:function(){

			if(! this._actions){
				this._actions = this.metadata.actions;
			}
			return this._actions;
		},
		_getColumnsConfig:function(){
			if(! this._columnsConfig){
				this._columnsConfig = this.metadata.fields;
			}
			return this._columnsConfig;
		},
		_getFilterConfig:function(){
			if(! this._filterConfig){
				this._filterConfig = this.metadata.filter;
			}
			return this._filterConfig;
		},
		_getPaginatorConfig:function(){
			if(! this._paginatorConfig){
				this._paginatorConfig = this.metadata.paginator;
			}
			return this._paginatorConfig;
		},

		beforeDeleteRecord:function(){},
		afterDeleteRecord:function(){},
		deleteRecord:function(event){
	    	event.preventDefault();
	    	var self = this;
	    	var recordId = $(event.currentTarget).attr('record-id');
	    	var recordName = $(event.currentTarget).attr('record-name');
	    	bootbox.confirm({
	    		title: this.locale.deleteConfirmationTitle ? this.locale.deleteConfirmationTitle: this.app.locale.common.deleteConfirmationTitle,
	    		message:_.template(this.locale.deleteConfirmationMessage ? this.locale.deleteConfirmationMessage: this.app.locale.common.deleteConfirmationMessage,{record:recordName}),
				callback:function(result){
		    		if(result){
		    			self.beforeDeleteRecord();
		    			self.collection.get(recordId).destroy({success:function(){
                            self.collection.fetch();
                        }});
                        self.afterDeleteRecord();
		    		}
		    	}
	    	});
	    }
	});
});<commit_msg>bug fix<commit_after>"use strict";
define(['../objects/View'],function(view){
	return view.extend({
		_columnsConfig:null,
		_filterConfig:null,
		_paginatorConfig:null,
		_actions:null,
		metadata:null,
		_recordActions:null,
		_dataGridEL:'.data-grid',
		collection:null,
		elements:{},
		initialize:function(){
			this.template = _.template(this.template);
		 	this.collection = new this.collection();
			this.metadata = openbiz.MetadataParser.call(this,this.metadata)
			openbiz.View.prototype.initialize.apply(this);
			return this;
		},
		_bindEvents:function(){
			this.undelegateEvents();
			var actions = this._getActions();
			for (var i in actions){
				var action = actions[i];
				var key = action.event + " ." + "act-"+action.name.toLowerCase();
				this.events[key] = action.function;
			}
			var recordActions = this._getRecordActions();
			for (var i in recordActions){
				var recordAction = recordActions[i];
				if(typeof recordAction.function != 'undefined' && recordAction.function)
				{
					var key = recordAction.event + " ." + "rec-act-"+recordAction.name.toLowerCase();
					this.events[key] = recordAction.function;
				}
			}
			this.delegateEvents();
			return this;
		},
		beforeRender:function(){},
		afterRender:function(){},
		render:function(){
			$(window).off('resize');
			openbiz.ui.update($(this.el));
			if(this._canDisplayView())
			{
				this.beforeRender();
				$(this.el).html(this.template(this.locale));
				this._renderDataGridConfig()._bindEvents();
				this.afterRender();
			}
			else
			{
				this._renderNoPermissionView();
			}
		},
		_renderDataGridConfig:function(){
			var columns = [];
			var columnConfigs = this._getColumnsConfig();
			for (var i in columnConfigs){
				var column = columnConfigs[i];
				if(this._canDisplayColumn(column)){
					var type = column['type'];
					if(typeof  type == 'undefined' || type == null){
						type = 'text';
					}
					var field;
					if(this.elements[type]){
						field = this.elements[type].getConfig(this,column,this._getRecordActions());
					}
					else{
						field = openbiz.elements.columns[type].getConfig(this,column,this._getRecordActions());
					}
					if(field != null){
						columns.push(field);
					}
				}
			}
			if(this._getFilterConfig()){
				var filter = new Backgrid.Extension.ServerSideFilter({
					collection: this.collection,
					name: "query",
					placeholder: ""
				});
				$(this.el).find(this._dataGridEL).append(filter.render().el);
			}
			var grid = new Backgrid.Grid({
				columns:columns,
				collection: this.collection,
				className: 'backgrid table table-striped table-bordered text-center',
				emptyText: this.metadata.gridEmptyText
			});
			$(this.el).find(this._dataGridEL).append(grid.render().el);
			if(this._getPaginatorConfig()){
				var paginator = new Backgrid.Extension.Paginator({
					windowSize: 10,
					slideScale: 0.5,
					goBackFirstOnSort: true,
					collection: this.collection,
					className:'pagination'
				});
				$(this.el).find(this._dataGridEL).append(paginator.render().el);
			}
			this.collection.fetch();
			return this;
		},
		_renderNoPermissionView:function(){
			//render 403 page
		},
		_canDisplayView:function(){
			if(typeof this.metadata.permission == 'undefined' || this.metadata.permission == null){
				return true;
			}
			return openbiz.session.me.hasPermission(this.metadata.permission);
		},
		_canDisplayColumn:function(column){
			if(typeof column.permission != 'undefined' && column.permission)
				return openbiz.session.me.hasPermission(column.permission);
			return true;
		},
		_getRecordActions:function(){
			if(! this._recordActions){
				this._recordActions = this.metadata.recordActions;
			}
			return this._recordActions;
		},
		_getActions:function(){

			if(! this._actions){
				this._actions = this.metadata.actions;
			}
			return this._actions;
		},
		_getColumnsConfig:function(){
			if(! this._columnsConfig){
				this._columnsConfig = this.metadata.fields;
			}
			return this._columnsConfig;
		},
		_getFilterConfig:function(){
			if(! this._filterConfig){
				this._filterConfig = this.metadata.filter;
			}
			return this._filterConfig;
		},
		_getPaginatorConfig:function(){
			if(! this._paginatorConfig){
				this._paginatorConfig = this.metadata.paginator;
			}
			return this._paginatorConfig;
		},

		beforeDeleteRecord:function(){},
		afterDeleteRecord:function(){},
		deleteRecord:function(event){
	    	event.preventDefault();
	    	var self = this;
	    	var recordId = $(event.currentTarget).attr('record-id');
	    	var recordName = $(event.currentTarget).attr('record-name');
	    	bootbox.confirm({
	    		title: this.locale.deleteConfirmationTitle ? this.locale.deleteConfirmationTitle: this.app.locale.common.deleteConfirmationTitle,
	    		message:_.template(this.locale.deleteConfirmationMessage ? this.locale.deleteConfirmationMessage: this.app.locale.common.deleteConfirmationMessage,{record:recordName}),
				callback:function(result){
		    		if(result){
		    			self.beforeDeleteRecord();
		    			self.collection.get(recordId).destroy({success:function(){
                            self.collection.fetch();
                        }});
                        self.afterDeleteRecord();
		    		}
		    	}
	    	});
	    }
	});
});<|endoftext|>


<commit_before>// Copyright (c) 2013 David Gallardo Moreno. All rights reserved.

/**
 * @fileoverview Basic scroll-animatable bitmap text sprite.
 * @author David Gallardo Moreno (portalg@gmail.com)
 */

goog.provide('ss2d.BitmapTextSprite');

goog.require('ss2d.Quad');

/**
 * @constructor
 * @extends {ss2d.Quad}
 * @param {number=} x Position in x axis
 * @param {number=} y Position in y axis
 * @param {string} textString The text that will be displayed.
 * @param {string} bitmapFont Bitmap font name.
 * @param {number} fontSize size in pixels of the line-height
 * @property {*} inherited @see ss2d.Quad
 * @property {string} mTextString
 * @property {number} mFontSize
 * @property {string} mBitmapFont
 * @property {string} mDisplayChars Number of chars that will be displayed, by default -1 (all), used for text scrolling.
 * @property {number[5]} mClip
 */
ss2d.BitmapTextSprite = function(x, y, textString, bitmapFont, fontSize)
{
	ss2d.Quad.call(this, x, y, 0, 0);

	this.mTextString = textString||'';
	this.mFontSize = fontSize||16;
	this.mDisplayChars = -1;
	this.mBitmapFont = ss2d.ResourceManager.loadBitmapFont(bitmapFont);

	if(COMPILING_CLIENT || COMPILING_OFFLINE)
	{
		this.mGlyphSprite = new ss2d.Sprite;
		this.mClip = [];
	}
	//WEBGL
	//if(RENDER_CONTEXT == 'webgl')
	//{

	//}
};

goog.inherits(ss2d.BitmapTextSprite, ss2d.Quad);

ss2d.Object.assignClassId(ss2d.BitmapTextSprite, 1007);

/**
 * Sets the number of chars that will be displayed, use with ss2d.Tween to create scroll animation.
 * @param {number} displayChars
 */
ss2d.BitmapTextSprite.prototype.setDisplayChars = function(displayChars)
{
	this.mDisplayChars = Math.floor(displayChars);
}

/**
 * Gets the number of chars that will be displayed, use with ss2d.Tween to create scroll animation.
 * @return {number}
 */
ss2d.BitmapTextSprite.prototype.getDisplayChars = function()
{
	return this.mDisplayChars;
}

if(COMPILING_CLIENT||COMPILING_OFFLINE)
{
	/** @override */
	ss2d.BitmapTextSprite.prototype.render = function(renderSupport)
	{

		//if(RENDER_CONTEXT == 'webgl')
		//{

		//}
		//else
		//{
			renderSupport.pushTransform(this);
			var ctx = renderSupport.mContext;
			try{
				this.mWidth = 0;
				var xTranslation = 0;
				this.mGlyphSprite.mTexture = this.mBitmapFont.mTexture;
				var s = this.mFontSize /this.mBitmapFont.mMidHeight;
				this.mScaleX = this.mScaleY = s;
				var charsToShow = (this.mDisplayChars > -1)?
								  Math.min(this.mDisplayChars, this.mTextString.length):
								  this.mTextString.length;

				for(var c = 0; c < charsToShow; ++c)
				{
					var charCode = this.mTextString.charCodeAt(c);
					if(charCode == 32){
						ctx.translate(this.mBitmapFont.mMidWidth, 0);
						continue;
					}

					this.mBitmapFont.getGlyphClip(charCode, this.mClip);

					//this.mGlyphSprite.mScaleX = this.mGlyphSprite.mScaleY = s;
					//ctx.scale(s, s);
					this.mGlyphSprite.mLocation.mX = xTranslation;
					this.mGlyphSprite.mLocation.mY = this.mClip[5];
					//ctx.translate(0, this.mClip[5]);

					//this.mGlyphSprite.mRotation = this.mRotation
					this.mGlyphSprite.mClip = this.mClip;
					this.mGlyphSprite.mWidth =  this.mClip[2];
					this.mGlyphSprite.mHeight =  this.mClip[3];

					this.mGlyphSprite.render(renderSupport);
					//ctx.rotate(this.mRotation);

					/*ctx.drawImage(this.mBitmapFont.mTexture.mTextureElement,
								  this.mClip[0],
								  this.mClip[1],
								  this.mClip[2],
								  this.mClip[3],
								  0,
								  0,
								  this.mClip[2],
								  this.mClip[3]);
					ctx.translate(0, -this.mClip[5]);
					ctx.translate(this.mClip[4], 0);
					ctx.scale(1/s, 1/s);*/
					xTranslation += this.mClip[4];

				}
			} catch (t) { }
			renderSupport.popTransform();

		//}
	};
}

//*****************
//* SERIALIZATION *
//*****************/

if(COMPILING_CLIENT)
{
	/** @override */
	ss2d.BitmapTextSprite.convert = function(obj)
	{
		var objBackup =  ss2d.Object.backupAndDeleteObjectProperties(obj);

		ss2d.BitmapTextSprite.call(obj);

		obj.__proto__ = ss2d.BitmapTextSprite.prototype;

		//now obj is a BitmapTextSprite
		obj.restoreSerializedProperties(objBackup);

		return obj;
	}

	ss2d.BitmapTextSprite.prototype.restoreSerializedProperties = function(objBackup)
	{
		ss2d.Quad.prototype.restoreSerializedProperties.call(this, objBackup);

		this.mTextString = objBackup['str'];
		this.mFontSize = objBackup['fsize'];
		this.mBitmapFont = ss2d.ResourceManager.loadBitmapFont(objBackup['bmfname']);
		this.mFontStyle = objBackup['fstyle'];
		this.mDisplayChars = objBackup['dc'];
	}

	ss2d.BitmapTextSprite.createFromSerializedObject = function(obj)
	{
		var newObj = new ss2d.BitmapTextSprite(obj['x'],
											   obj['y'],
											   obj['str'],
											   obj['bmfname'],
											   obj['fsize']);
		newObj.mObjectId = obj['doid'];
		return newObj;
	}

	ss2d.BitmapTextSprite.prototype.interpolateState = function(prevState, nextState, part)
	{
		ss2d.Quad.prototype.interpolateState.call(this, prevState, nextState, part, deltaTime);

		this.mTextString = prevState['str'];
		this.mFontSize = prevState['fsize'];

		if(!this.mBitmapFont ||this.mBitmapFont.mName != prevState['bmfname'])
			this.mBitmapFont = ss2d.ResourceManager.loadBitmapFont(prevState['bmfname']);

		this.mDisplayChars = Math.floor(prevState['dc'] + (nextState['dc'] - prevState['dc']) * part);
	}
}

if(COMPILING_SERVER)
{
	ss2d.BitmapTextSprite.prototype.toJSON = function()
	{
		return '{'+this.getPropertiesJSON()+'}';
	}

	/**
	 * SERIALIZACION SPEC:
	 * mTextString : str
	 * @override
	 */
	ss2d.BitmapTextSprite.prototype.getPropertiesJSON = function()
	{
		var str = ss2d.Quad.prototype.getPropertiesJSON.call(this);

		str += ',"str": "'+this.mTextString+'"';
		str += ',"fsize": "'+this.mFontSize+'"';
		str += ',"bmfname": "'+this.mBitmapFont.mName+'"';
		str += ',"dc": "'+this.mDisplayChars+'"';

		return str;
	}
}

//************************
//* END OF SERIALIZATION *
//************************/<commit_msg>BitmapTextSprite polished<commit_after>// Copyright (c) 2013 David Gallardo Moreno. All rights reserved.

/**
 * @fileoverview Basic scroll-animatable bitmap text sprite.
 * @author David Gallardo Moreno (portalg@gmail.com)
 */

goog.provide('ss2d.BitmapTextSprite');

goog.require('ss2d.Quad');

/**
 * @constructor
 * @extends {ss2d.Quad}
 * @param {number=} x Position in x axis
 * @param {number=} y Position in y axis
 * @param {string} textString The text that will be displayed.
 * @param {string} bitmapFont Bitmap font name.
 * @param {number} fontSize size in pixels of the line-height
 * @property {*} inherited @see ss2d.Quad
 * @property {string} mTextString
 * @property {number} mFontSize
 * @property {string} mBitmapFont
 * @property {string} mDisplayChars Number of chars that will be displayed, by default -1 (all), used for text scrolling.
 * @property {number[5]} mClip
 */
ss2d.BitmapTextSprite = function(x, y, textString, bitmapFont, fontSize)
{
	ss2d.Quad.call(this, x, y, 0, 0);

	this.mTextString = textString||'';
	this.mFontSize = fontSize||16;
	this.mDisplayChars = -1;
	this.mBitmapFont = ss2d.ResourceManager.loadBitmapFont(bitmapFont);

	if(COMPILING_CLIENT || COMPILING_OFFLINE)
	{
		this.mGlyphSprite = new ss2d.Sprite;
		this.mClip = [];
	}
	//WEBGL
	//if(RENDER_CONTEXT == 'webgl')
	//{

	//}
};

goog.inherits(ss2d.BitmapTextSprite, ss2d.Quad);

ss2d.Object.assignClassId(ss2d.BitmapTextSprite, 1007);

/**
 * Sets the number of chars that will be displayed, use with ss2d.Tween to create scroll animation.
 * @param {number} displayChars
 */
ss2d.BitmapTextSprite.prototype.setDisplayChars = function(displayChars)
{
	this.mDisplayChars = Math.floor(displayChars);
}

/**
 * Gets the number of chars that will be displayed, use with ss2d.Tween to create scroll animation.
 * @return {number}
 */
ss2d.BitmapTextSprite.prototype.getDisplayChars = function()
{
	return this.mDisplayChars;
}

if(COMPILING_CLIENT||COMPILING_OFFLINE)
{
	/** @override */
	ss2d.BitmapTextSprite.prototype.render = function(renderSupport)
	{

		//if(RENDER_CONTEXT == 'webgl')
		//{

		//}
		//else
		//{
			renderSupport.pushTransform(this);
			var ctx = renderSupport.mContext;
			try{
				this.mWidth = 0;
				var xTranslation = 0;
				this.mGlyphSprite.mTexture = this.mBitmapFont.mTexture;
				var s = this.mFontSize /this.mBitmapFont.mMidHeight;
				this.mScaleX = this.mScaleY = s;
				var charsToShow = (this.mDisplayChars > -1)?
								  Math.min(this.mDisplayChars, this.mTextString.length):
								  this.mTextString.length;

				for(var c = 0; c < charsToShow; ++c)
				{
					var charCode = this.mTextString.charCodeAt(c);
					if(charCode == 32){
						ctx.translate(this.mBitmapFont.mMidWidth*0.5, 0);
						continue;
					}

					this.mBitmapFont.getGlyphClip(charCode, this.mClip);

					//this.mGlyphSprite.mScaleX = this.mGlyphSprite.mScaleY = s;
					//ctx.scale(s, s);
					this.mGlyphSprite.mLocation.mX = xTranslation;
					this.mGlyphSprite.mLocation.mY = this.mClip[5];
					//ctx.translate(0, this.mClip[5]);

					//this.mGlyphSprite.mRotation = this.mRotation
					this.mGlyphSprite.mClip = this.mClip;
					this.mGlyphSprite.mWidth =  this.mClip[2];
					this.mGlyphSprite.mHeight =  this.mClip[3];

					this.mGlyphSprite.render(renderSupport);
					//ctx.rotate(this.mRotation);

					/*ctx.drawImage(this.mBitmapFont.mTexture.mTextureElement,
								  this.mClip[0],
								  this.mClip[1],
								  this.mClip[2],
								  this.mClip[3],
								  0,
								  0,
								  this.mClip[2],
								  this.mClip[3]);
					ctx.translate(0, -this.mClip[5]);
					ctx.translate(this.mClip[4], 0);
					ctx.scale(1/s, 1/s);*/
					xTranslation += this.mClip[4];

				}
			} catch (t) { }
			renderSupport.popTransform();

		//}
	};
}

//*****************
//* SERIALIZATION *
//*****************/

if(COMPILING_CLIENT)
{
	/** @override */
	ss2d.BitmapTextSprite.convert = function(obj)
	{
		var objBackup =  ss2d.Object.backupAndDeleteObjectProperties(obj);

		ss2d.BitmapTextSprite.call(obj);

		obj.__proto__ = ss2d.BitmapTextSprite.prototype;

		//now obj is a BitmapTextSprite
		obj.restoreSerializedProperties(objBackup);

		return obj;
	}

	ss2d.BitmapTextSprite.prototype.restoreSerializedProperties = function(objBackup)
	{
		ss2d.Quad.prototype.restoreSerializedProperties.call(this, objBackup);

		this.mTextString = objBackup['str'];
		this.mFontSize = objBackup['fsize'];
		this.mBitmapFont = ss2d.ResourceManager.loadBitmapFont(objBackup['bmfname']);
		this.mFontStyle = objBackup['fstyle'];
		this.mDisplayChars = objBackup['dc'];
	}

	ss2d.BitmapTextSprite.createFromSerializedObject = function(obj)
	{
		var newObj = new ss2d.BitmapTextSprite(obj['x'],
											   obj['y'],
											   obj['str'],
											   obj['bmfname'],
											   obj['fsize']);
		newObj.mObjectId = obj['doid'];
		return newObj;
	}

	ss2d.BitmapTextSprite.prototype.interpolateState = function(prevState, nextState, part)
	{
		ss2d.Quad.prototype.interpolateState.call(this, prevState, nextState, part, deltaTime);

		this.mTextString = prevState['str'];
		this.mFontSize = prevState['fsize'];

		if(!this.mBitmapFont ||this.mBitmapFont.mName != prevState['bmfname'])
			this.mBitmapFont = ss2d.ResourceManager.loadBitmapFont(prevState['bmfname']);

		this.mDisplayChars = Math.floor(prevState['dc'] + (nextState['dc'] - prevState['dc']) * part);
	}
}

if(COMPILING_SERVER)
{
	ss2d.BitmapTextSprite.prototype.toJSON = function()
	{
		return '{'+this.getPropertiesJSON()+'}';
	}

	/**
	 * SERIALIZACION SPEC:
	 * mTextString : str
	 * @override
	 */
	ss2d.BitmapTextSprite.prototype.getPropertiesJSON = function()
	{
		var str = ss2d.Quad.prototype.getPropertiesJSON.call(this);

		str += ',"str": "'+this.mTextString+'"';
		str += ',"fsize": "'+this.mFontSize+'"';
		str += ',"bmfname": "'+this.mBitmapFont.mName+'"';
		str += ',"dc": "'+this.mDisplayChars+'"';

		return str;
	}
}

//************************
//* END OF SERIALIZATION *
//************************/<|endoftext|>


<commit_before>var fs = require("q-io/fs"),
    q = require("q"),
    git = require("gift-wrapper"),
    generate = require("./generate.js"),
    exec = require('child_process').exec;

var repoDir = __dirname + "/../"
var credentialFilePath = repoDir + ".git/credentials";
var repo = git(repoDir);

function setAuthConfig(){
  var deferred = q.defer();
  exec('git config credential.helper "store --file=' + credentialFilePath + '"',
    {
        cwd: repoDir,
        encoding: "utf8",
        maxBuffer: 5000 * 1024
    },
    function(err){
      if(err){
        return deferred.reject(err);
      }

      return deferred.resolve();
    }
  );

  return deferred.promise;
};

function publishChanges(github_personal_access_token){
  return setAuthConfig()
  .then(function(){
    var content = "https://" + github_personal_access_token + ":@github.com"
    console.log("content: " + content);
    return fs.write(credentialFilePath, content);
  })
  .then(function(){
    return repo.identify({name: "javiercancela", email: "javier.cancela.vicente@gmail.com"});
  })
  .then(function(){
    console.log("Adding all files...");
    return repo.add("-A");
  })
  .then(function(){
    console.log("Committing changes...");
    return repo.commit("[ci skip] automated comment issue creation and tag+archive page generation");
  })
  .then(function(){
    console.log("Pushing changes...");
    return repo.remote_push("--force --quiet origin", "HEAD:master");
  })
  .then(function(){
    console.log("Pushed successfully.");
    return repo.status().then(console.log);
  })
};

// the main entry point
generate()
.then(function(){
  return repo.status();
})
.then(function(status){
  if(!status.clean){
    return publishChanges(process.env.GH_TOKEN);
  }
})
.fail(console.error);
<commit_msg>Revert "Eliminamos la generación de comentarios"<commit_after>var fs = require("q-io/fs"),
    q = require("q"),
    git = require("gift-wrapper"),
    generate = require("./generate.js"),
    ghi_create = require("./create_gh_issues.js"),
    exec = require('child_process').exec;

var repoDir = __dirname + "/../"
var credentialFilePath = repoDir + ".git/credentials";
var repo = git(repoDir);

function setAuthConfig(){
  var deferred = q.defer();
  exec('git config credential.helper "store --file=' + credentialFilePath + '"',
    {
        cwd: repoDir,
        encoding: "utf8",
        maxBuffer: 5000 * 1024
    },
    function(err){
      if(err){
        return deferred.reject(err);
      }

      return deferred.resolve();
    }
  );

  return deferred.promise;
};

function publishChanges(github_personal_access_token){
  return setAuthConfig()
  .then(function(){
    var content = "https://" + github_personal_access_token + ":@github.com"
    console.log("content: " + content);
    return fs.write(credentialFilePath, content);
  })
  .then(function(){
    return repo.identify({name: "javiercancela", email: "javier.cancela.vicente@gmail.com"});
  })
  .then(function(){
    console.log("Adding all files...");
    return repo.add("-A");
  })
  .then(function(){
    console.log("Committing changes...");
    return repo.commit("[ci skip] automated comment issue creation and tag+archive page generation");
  })
  .then(function(){
    console.log("Pushing changes...");
    return repo.remote_push("--force --quiet origin", "HEAD:master");
  })
  .then(function(){
    console.log("Pushed successfully.");
    return repo.status().then(console.log);
  })
};

// the main entry point
generate()
.then(function(){
    return ghi_create(process.env.GH_TOKEN);
})
.then(function(){
  return repo.status();
})
.then(function(status){
  if(!status.clean){
    return publishChanges(process.env.GH_TOKEN);
  }
})
.fail(console.error);
<|endoftext|>


<commit_before>// Get stories from JSON
//
$(document).ready(getstories);
function getstories(){

    $.getJSON('stories.json', function(data) {
		$.each(data.list, function(key, val) {
        var output="
";
		    output+="
" + val.resolved_title +"
";
		    output+="
" + "val.resolved_url"+"
";
		    output+="
" + val.excerpt +"
";
		    output+="
";
			output+="
";

			$("#news").append(output);
      	});
    });
}<commit_msg>Added Link to title<commit_after>// Get stories from JSON
//
$(document).ready(getstories);
function getstories(){

    $.getJSON('stories.json', function(data) {
		$.each(data.list, function(key, val) {
        var output="
";
		    output+="
" + val.resolved_title +"
";
		    output+="
" + "'"val.resolved_title"'"+"
";
		    output+="
" + val.excerpt +"
";
		    output+="
";
			output+="
";

			$("#news").append(output);
      	});
    });
}<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

//******************************
// Class Connexion
function Connexion() {
  var self = this;

  self.etatApplication = null;
  var lastDataVersion;

  this.verifieVersion = function(){
    var etatApplication = false;
    if(this.testConnectivite())
    {
      etatApplication = true;

        $.ajax({
                  type: 'POST',
                  url: webservice_version,
                  data: {},
                  dataType: "json",
                  async:true
                }).done(function(data){
                      var appVersion = "";
                      var dataVersion = "";
                      //var resultat = JSON.parse(data); // convert to JSON from string
                      var resultat = data; // data already JSON

                      if(resultat["app-version"] != undefined)
                      {
                        appVersion = resultat["app-version"];
                      }
                      if(resultat["data-version"] != undefined)
                      {
                        dataVersion = resultat["data-version"];
                      }

                      compareVersionAppEtData(appVersion,dataVersion);

                    }
                );

    }else{
      // pas de connexion tourne en local
      etatApplication = false;
    }
    return etatApplication;
  };

  function compareVersionAppEtData(appVersion,dataVersion){
    // test si différence de version de l'application
    if(appVersion != self.getAppVersion())
    {
      self.etatApplication = -1; // il faut mettre à jour l'application
    }else{
      // test si différence de version des données
      if(dataVersion != self.getDataVersion())
      {
        self.etatApplication = 0; // il faut mettre à jour les données
        self.lastDataVersion = dataVersion;
      }else{
        // OK, application et données à jour
        self.etatApplication = 1;
        self.lastDataVersion = dataVersion;
      }
    }

    // annonce que la vérificaiton est terminée
    $("#eventManager").trigger('versionVerifiee');
  }

  this.getEtatApplication = function(){
    return self.etatApplication;
  };

  function gotFSforCheckUpdate(fileSystem) {
    //console.log(fileSystem.name);
    //console.log(fileSystem.root);
    fileSystem.root.getFile("check-update.json", {create: true, exclusive: false}, gotFileEntryforCheckUpdate, failFile);
  }
  function gotFileEntryforCheckUpdate(fileEntry) {
    //console.log(fileEntry);
    //console.log(fileEntry.name);
    fileEntry.file(gotFileforCheckUpdate, fail);
  }
  function gotFileforCheckUpdate(file){
    //readDataUrl(file);
    readAsTextforCheckUpdate(file);
  }
  function readAsTextforCheckUpdate(file) {
    var reader = new FileReader();
    reader.onloadend = function(evt) {
      //console.log("Read as text");
      //console.log(evt.target.result);
    };
    reader.readAsText(file);
  }
  function fail(error) {
    //console.log(error);
    //console.log(error.code);
  }
  function failFile(error) {
    //console.log(error);
    //console.log(error.code);
    //console.log("error getting file");
  }

  // ---------------------------
  this.testConnectivite = function() {
    var networkState = navigator.connection.type;
    //console.log("testConnectivite : "+networkState);
    var states = {};
    states[Connection.UNKNOWN]  = 'Unknown connection';
    states[Connection.ETHERNET] = 'Ethernet connection';
    states[Connection.WIFI]     = 'WiFi connection';
    states[Connection.CELL_2G]  = 'Cell 2G connection';
    states[Connection.CELL_3G]  = 'Cell 3G connection';
    states[Connection.CELL_4G]  = 'Cell 4G connection';
    states[Connection.CELL]     = 'Cell generic connection';
    states[Connection.NONE]     = 'No network connection';
    if((networkState === Connection.UNKNOWN)||(networkState === Connection.NONE))
    {
      return false;
    }else{
      return true;
    }
  };

  // initalisation des tableaux de données
  this.initialiseDonnees = function() {
    var etatApplication = false;
    if(this.testConnectivite())
    {
      etatApplication = true;

        $.ajax({
                  type: 'POST',
                  url: webservice_update,
                  data: {},
                  dataType: "json",
                  async:true
                }).done(function(data){
                      // data already JSON
                      analyseDonnees(data);
                    }
                );

    }else{
      // pas de connexion tourne en local
      etatApplication = false;
    }
    return etatApplication;
  };

  function analyseDonnees(objJSon) {

    configJson = objJSon["config"];

    donneesJson = objJSon["contenu"];

    menuJson = objJSon["menu"];

    pubsJson = objJSon["pub"];

    updateConfig();

    // annonce que nos données sont à jour à cette version
    setDataVersion();

    // libère mémoire
    objJSon = null;

    // annonce que la données sont chargées
    $("#eventManager").trigger('initialiseDonneesReady');
  };

  function updateConfig(){
    cdn_visuel_menu = configJson['cdn_visuel_menu'];
    cdn_visuel = configJson['cdn_visuel'];
    cdn_visuel_small = configJson['cdn_visuel_small'];
  }

  this.getAppVersion = function(){
    var appVersion = "1.0.0";

    return appVersion;
  };

  this.getDataVersion = function(){
    //var dataVersion = "20131208.150000";
    var dataVersion = "";

    if(permanentStorage.getItem("data-version")!= null)
    {
      dataVersion = permanentStorage.getItem("data-version");
    }

    return dataVersion;
  };

  function setDataVersion(){
    permanentStorage.setItem("data-version",self.lastDataVersion);
    //console.log("place en stockage permanent : "+self.lastDataVersion);
    //console.log("permanentStorage.getItem( data-version ) : "+permanentStorage.getItem("data-version"));
  }

  this.subscribeToNotification = function(_platform, _token){
    var etatApplication = false;
    if(this.testConnectivite())
    {
      etatApplication = true;

        $.ajax({
                  type: 'POST',
                  url: webservice_subscribe,
                  data: {platform:_platform, token:_token},
                  dataType: "json",
                  async:true
                }).done(function(data){
                      // envoi du token pour notification terminé
                      //navigator.notification.alert(data, null, 'DEBUG : data', 'OK');
                    }
                );

    }else{
      // pas de connexion tourne en local
      etatApplication = false;
    }
    return etatApplication;
  }

}<commit_msg>Notification : debug _platform en minuscule<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

//******************************
// Class Connexion
function Connexion() {
  var self = this;

  self.etatApplication = null;
  var lastDataVersion;

  this.verifieVersion = function(){
    var etatApplication = false;
    if(this.testConnectivite())
    {
      etatApplication = true;

        $.ajax({
                  type: 'POST',
                  url: webservice_version,
                  data: {},
                  dataType: "json",
                  async:true
                }).done(function(data){
                      var appVersion = "";
                      var dataVersion = "";
                      //var resultat = JSON.parse(data); // convert to JSON from string
                      var resultat = data; // data already JSON

                      if(resultat["app-version"] != undefined)
                      {
                        appVersion = resultat["app-version"];
                      }
                      if(resultat["data-version"] != undefined)
                      {
                        dataVersion = resultat["data-version"];
                      }

                      compareVersionAppEtData(appVersion,dataVersion);

                    }
                );

    }else{
      // pas de connexion tourne en local
      etatApplication = false;
    }
    return etatApplication;
  };

  function compareVersionAppEtData(appVersion,dataVersion){
    // test si différence de version de l'application
    if(appVersion != self.getAppVersion())
    {
      self.etatApplication = -1; // il faut mettre à jour l'application
    }else{
      // test si différence de version des données
      if(dataVersion != self.getDataVersion())
      {
        self.etatApplication = 0; // il faut mettre à jour les données
        self.lastDataVersion = dataVersion;
      }else{
        // OK, application et données à jour
        self.etatApplication = 1;
        self.lastDataVersion = dataVersion;
      }
    }

    // annonce que la vérificaiton est terminée
    $("#eventManager").trigger('versionVerifiee');
  }

  this.getEtatApplication = function(){
    return self.etatApplication;
  };

  function gotFSforCheckUpdate(fileSystem) {
    //console.log(fileSystem.name);
    //console.log(fileSystem.root);
    fileSystem.root.getFile("check-update.json", {create: true, exclusive: false}, gotFileEntryforCheckUpdate, failFile);
  }
  function gotFileEntryforCheckUpdate(fileEntry) {
    //console.log(fileEntry);
    //console.log(fileEntry.name);
    fileEntry.file(gotFileforCheckUpdate, fail);
  }
  function gotFileforCheckUpdate(file){
    //readDataUrl(file);
    readAsTextforCheckUpdate(file);
  }
  function readAsTextforCheckUpdate(file) {
    var reader = new FileReader();
    reader.onloadend = function(evt) {
      //console.log("Read as text");
      //console.log(evt.target.result);
    };
    reader.readAsText(file);
  }
  function fail(error) {
    //console.log(error);
    //console.log(error.code);
  }
  function failFile(error) {
    //console.log(error);
    //console.log(error.code);
    //console.log("error getting file");
  }

  // ---------------------------
  this.testConnectivite = function() {
    var networkState = navigator.connection.type;
    //console.log("testConnectivite : "+networkState);
    var states = {};
    states[Connection.UNKNOWN]  = 'Unknown connection';
    states[Connection.ETHERNET] = 'Ethernet connection';
    states[Connection.WIFI]     = 'WiFi connection';
    states[Connection.CELL_2G]  = 'Cell 2G connection';
    states[Connection.CELL_3G]  = 'Cell 3G connection';
    states[Connection.CELL_4G]  = 'Cell 4G connection';
    states[Connection.CELL]     = 'Cell generic connection';
    states[Connection.NONE]     = 'No network connection';
    if((networkState === Connection.UNKNOWN)||(networkState === Connection.NONE))
    {
      return false;
    }else{
      return true;
    }
  };

  // initalisation des tableaux de données
  this.initialiseDonnees = function() {
    var etatApplication = false;
    if(this.testConnectivite())
    {
      etatApplication = true;

        $.ajax({
                  type: 'POST',
                  url: webservice_update,
                  data: {},
                  dataType: "json",
                  async:true
                }).done(function(data){
                      // data already JSON
                      analyseDonnees(data);
                    }
                );

    }else{
      // pas de connexion tourne en local
      etatApplication = false;
    }
    return etatApplication;
  };

  function analyseDonnees(objJSon) {

    configJson = objJSon["config"];

    donneesJson = objJSon["contenu"];

    menuJson = objJSon["menu"];

    pubsJson = objJSon["pub"];

    updateConfig();

    // annonce que nos données sont à jour à cette version
    setDataVersion();

    // libère mémoire
    objJSon = null;

    // annonce que la données sont chargées
    $("#eventManager").trigger('initialiseDonneesReady');
  };

  function updateConfig(){
    cdn_visuel_menu = configJson['cdn_visuel_menu'];
    cdn_visuel = configJson['cdn_visuel'];
    cdn_visuel_small = configJson['cdn_visuel_small'];
  }

  this.getAppVersion = function(){
    var appVersion = "1.0.0";

    return appVersion;
  };

  this.getDataVersion = function(){
    //var dataVersion = "20131208.150000";
    var dataVersion = "";

    if(permanentStorage.getItem("data-version")!= null)
    {
      dataVersion = permanentStorage.getItem("data-version");
    }

    return dataVersion;
  };

  function setDataVersion(){
    permanentStorage.setItem("data-version",self.lastDataVersion);
    //console.log("place en stockage permanent : "+self.lastDataVersion);
    //console.log("permanentStorage.getItem( data-version ) : "+permanentStorage.getItem("data-version"));
  }

  this.subscribeToNotification = function(_platform, _token){
    var etatApplication = false;

    _platform = _platform.toLowerCase();

    if(this.testConnectivite())
    {
      etatApplication = true;

        $.ajax({
                  type: 'POST',
                  url: webservice_subscribe,
                  data: {platform:_platform, token:_token},
                  dataType: "json",
                  async:true
                }).done(function(data){
                      // envoi du token pour notification terminé
                      //navigator.notification.alert(data, null, 'DEBUG : data', 'OK');
                    }
                );

    }else{
      // pas de connexion tourne en local
      etatApplication = false;
    }
    return etatApplication;
  }

}<|endoftext|>


<commit_before>define(function(require) {
  'use strict'

  function makeWheel (color1, color2) {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    canvas.width = 32;
    canvas.height = 32;
    ctx.beginPath();
    ctx.arc(16, 16, 15, 0, Math.PI, false);
    ctx.closePath();
    ctx.fillStyle = color1;
    ctx.fill();
    ctx.beginPath();
    ctx.arc(16, 16, 15, Math.PI, 0, false);
    ctx.closePath();
    ctx.fillStyle = color2;
    ctx.fill();
    return function (ctx, x, y, theta) {
      ctx.save();
      ctx.translate(x, y);
      ctx.rotate(theta);
      ctx.drawImage(canvas, -16, -16);
      ctx.restore();
    }
  }

  function makeSeat (color) {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    canvas.width = 30;
    canvas.height = 29;
    ctx.lineWidth=7;
    ctx.lineCap='round';
    ctx.strokeStyle='#3996E8';
    ctx.beginPath();
    ctx.moveTo(15,25);
    ctx.lineTo(15,5);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(15-11,4);
    ctx.lineTo(15+11,4);
    ctx.stroke();
    return function (ctx, x, y, theta) {
      ctx.save();
      ctx.translate(x, y);
      ctx.rotate(theta);
      ctx.drawImage(canvas, -15, -25);
      ctx.restore();
    }
  }

  var drawWheel = makeWheel ('#C13FFF', '#7F3FFF');
  var drawSeat = makeSeat ('#3996E8');

  function drawPlayer (ctx, player) {
    drawWheel (ctx, player.pos.x+300, 35, player.wheel.theta);
    drawSeat (ctx, player.pos.x+300, 35, player.seatAngle.value);
  }

  return function (ctx) {
    return function (state) {
      ctx.canvas.width = ctx.canvas.width;
      console.log (state.players);
      for (var i = 0; i < state.players.length; ++i) {
        drawPlayer (ctx, state.players[i]);
      }
    }
  }
});
<commit_msg>Removed debugging statement<commit_after>define(function(require) {
  'use strict'

  function makeWheel (color1, color2) {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    canvas.width = 32;
    canvas.height = 32;
    ctx.beginPath();
    ctx.arc(16, 16, 15, 0, Math.PI, false);
    ctx.closePath();
    ctx.fillStyle = color1;
    ctx.fill();
    ctx.beginPath();
    ctx.arc(16, 16, 15, Math.PI, 0, false);
    ctx.closePath();
    ctx.fillStyle = color2;
    ctx.fill();
    return function (ctx, x, y, theta) {
      ctx.save();
      ctx.translate(x, y);
      ctx.rotate(theta);
      ctx.drawImage(canvas, -16, -16);
      ctx.restore();
    }
  }

  function makeSeat (color) {
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    canvas.width = 30;
    canvas.height = 29;
    ctx.lineWidth=7;
    ctx.lineCap='round';
    ctx.strokeStyle='#3996E8';
    ctx.beginPath();
    ctx.moveTo(15,25);
    ctx.lineTo(15,5);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(15-11,4);
    ctx.lineTo(15+11,4);
    ctx.stroke();
    return function (ctx, x, y, theta) {
      ctx.save();
      ctx.translate(x, y);
      ctx.rotate(theta);
      ctx.drawImage(canvas, -15, -25);
      ctx.restore();
    }
  }

  var drawWheel = makeWheel ('#C13FFF', '#7F3FFF');
  var drawSeat = makeSeat ('#3996E8');

  function drawPlayer (ctx, player) {
    drawWheel (ctx, player.pos.x+300, 35, player.wheel.theta);
    drawSeat (ctx, player.pos.x+300, 35, player.seatAngle.value);
  }

  return function (ctx) {
    return function (state) {
      ctx.canvas.width = ctx.canvas.width;
      for (var i = 0; i < state.players.length; ++i) {
        drawPlayer (ctx, state.players[i]);
      }
    }
  }
});
<|endoftext|>


<commit_before>"use strict"

class Entity{
  init(){
    this.nextId = 1
    this.views = {}

    $(document).keyup((e) => {
      if (e.keyCode == 27) { // escape key maps to keycode `27`
        $(".toolbarbutton").removeClass("open")
        $(".itemaction").removeClass("clicked")
      }
    });
  }

  async run(){
    await mscp.ready;
    this.types = await mscp.types()
    this.addView(getUrlVar("folder") || "/")
  }

  addView(folder){
    let id = `folderview${this.nextId}`
    this.nextId++

    let view = new FolderView(id)
    view.create()
    view.showFolder(folder)

    this.views[id] = view
  }
}

class FolderView{
  constructor(elementId){
    this.elementId = elementId
  }

  create(){
    this.typeHandler = new TypeHandler(this)

    let html = `

            <button class="backbutton">Back</button>

              <button>Add new</button>

                <select name="type" value="folder" size="${Object.keys(this.typeHandler.types).length}">${this.typeHandler.typesSelectValues}</select>
                <input type="text" name="title" placeholder="Title"></input>

                <button>Add</button>

              <button>Add existing</button>

                <select name="type" value="folder" size="${Object.keys(this.typeHandler.types).length-1}">${this.typeHandler.typesSelectValuesNoFolder}</select>
                <input type="text" name="identifier" placeholder="Identifier"></input>
                <input type="text" name="title" placeholder="Title"></input>

                <button>Add</button>

`

    this.element = $(html)
    $("#content").append(this.element)
    this.element.find(".toolbarbutton > button").click((e) => {
      let isOpen = $(e.target).parent().is(".open")
      this.element.find(".toolbarbutton").removeClass("open")
      $(e.target).parent().toggleClass('open', !isOpen).find('select').focus().val('folder');
      e.stopPropagation();
    })
    this.element.find("button.backbutton").click((e) => this.back($(e.target)))
    this.element.find("span.addnewcontainer typeselct").change((e) => this.typeHandler.addNewTypeChanged($(e.target)))
    this.element.find("span.addnewcontainer button").click((e) => this.typeHandler.addNewExecute($(e.target)))
    this.element.find("span.addexistingcontainer button").click((e) => this.typeHandler.addExistingExecute($(e.target)))
  }

  async showFolder(path){

    let folder = await mscp.folder(path)
    if(folder == null){
      alert("Unknown folder")
      return;
    }

    this.path = path
    this.element.find(".backbutton").prop("disabled",this.path == "/")
    this.element.find("span.folderpath").html(folder.path)

    let container = this.element.find(".foldercontent")
    container.empty()

    folder.content = folder.content.sort((a, b) => {
      if(a.properties.type == "folder" && b.properties.type != "folder") return -1
      else if(a.properties.type != "folder" && b.properties.type == "folder") return 1
      else return a.properties.title.toLowerCase() > b.properties.title.toLowerCase() ? 1 : -1
    })

    for(let e of folder.content){
      let folderItem = $("
", {class: "folderitem"})

      let title = e.properties.title || e.id
      folderItem.append($("", {src: this.typeHandler.types[e.properties.type].icon || "/mscp/libs/img/help.png"}))
      $("", {class: "itemname", html: title}).appendTo(folderItem).click((e) => {this.itemClicked($(e.target).parent()); e.stopPropagation();})
      folderItem.data("item", e)
      folderItem.click((e) => {
        let selected = $(e.currentTarget).is(".selected")
        $(e.currentTarget).parents(".foldercontent").find(".folderitem").removeClass("selected");
        $(e.currentTarget).toggleClass("selected", !selected)
      })

      let itemActions = $(`<span class="itemactions"/>`)

      // DELETE BUTTON
      let deleteActionHTML = `

Are you sure?

                                  Yes
                                  No

                              </`

      let deleteAction = $(deleteActionHTML)
      deleteAction.find(".ok").click((e) => {this.itemDelete($(e.target).parents(".folderitem").data("item")); e.stopPropagation();})
      itemActions.append(deleteAction)

      // RENAME BUTTON
      if(e.properties.type != "folder"){
        let editActionHTML = `

                                    <input name="title" placeholder="Title" value="${title}"/>
                                    Ok
                                    Cancel

                                </`

        let editAction = $(editActionHTML)
        editAction.find(".ok").click((e) => {this.itemRename($(e.target).parents(".folderitem").data("item"), $(e.target).parent().find("input[name=title]").val()); e.stopPropagation();})
        itemActions.append(editAction)

        // MOVE BUTTON
        let moveActionHTML = `

                                    <input name="dest" placeholder="Destination path" value="${this.path}"/>
                                    Ok
                                    Cancel

                                </`

        let moveAction = $(moveActionHTML)
        moveAction.find(".ok").click((e) => {this.itemMove($(e.target).parents(".folderitem").data("item"), $(e.target).parent().find("input[name=dest]").val()); e.stopPropagation();})
        itemActions.append(moveAction)
      }

      // SHARE BUTTON
      if(this.typeHandler.types[e.properties.type].allowShare){
        let shareActionHTML = `

                                    <input type="checkbox" name="writeaccess"/>Write access
                                    <input style="display: none;" type="text" name="generatedlink"/>
                                    Generate
                                    Close

                                </`

        let shareAction = $(shareActionHTML)
        shareAction.find(".generate").click(async (e) => {
          let writeAccess = $(e.target).parents(".folderitem").find("input[name=writeaccess]").is(":checked")
          $(e.target).parents(".folderitem").find("input[name=generatedlink]").val(await this.itemShare($(e.target).parents(".folderitem").data("item"), writeAccess)).show().focus().select();
          e.stopPropagation();
        })
        itemActions.append(shareAction)
      }

      folderItem.append(itemActions)
      container.append(folderItem)
    }

    container.find(".itemaction").click((e) => {
      if(!$(e.target).is("img"))
        return;
      let clicked = $(e.currentTarget).is(".clicked");
      $(".folderitem .itemaction").removeClass("clicked");
      $(e.currentTarget).toggleClass("clicked", !clicked);
      if(!clicked) {
        $(e.currentTarget).find("input:first").focus().select();
        $(e.currentTarget).find("input").keyup((e)=>{if(e.keyCode == 13) $(e.target).parents(".itemaction").find(".ok").click(); e.stopPropagation();});
      }
      e.stopPropagation();
    })
    container.find(".itemaction .cancel").click((e) => {$(e.target).parents(".itemaction").removeClass("clicked"); e.stopPropagation()})
  }

  refreshContent(){
    this.showFolder(this.path)
  }

  itemClicked(itemElement){
    let item = itemElement.data("item")

    if(item.properties.type == "folder"){
      this.showFolder(this.path + item.properties.title)
    } else {
      this.typeHandler.openItem(item)
    }
  }

  back(){
    let idx = this.path.substring(0, this.path.length - 1).lastIndexOf("/")
    if(idx < 0)
      this.showFolder("/")
    else
      this.showFolder(this.path.substring(0, idx+1))
  }

  async itemDelete(item){
    await mscp.remove(this.path, item.id)
    this.refreshContent()
  }

  async itemRename(item, newName){
    await mscp.setProperty(item.id, "title", newName)
    this.refreshContent()
  }

  async itemShare(item, writeAccess){
    return this.typeHandler.getShareableLink(item, writeAccess)
  }

  async itemMove(item, destPath){
    await mscp.move(item.id, this.path, destPath)
    this.refreshContent()
  }
}

var entity = new Entity();
entity.init();
$(() => entity.run());

function getUrlVar( name ){
    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
    var regexS = "[\\?&]"+name+"=([^&#]*)";
    var regex = new RegExp( regexS );
    var results = regex.exec( window.location.href );
    if( results == null )
        return undefined;
    else
        return decodeURIComponent(results[1]);
}
<commit_msg>Misc fixes<commit_after>"use strict"

class Entity{
  init(){
    this.nextId = 1
    this.views = {}

    $(document).keyup((e) => {
      if (e.keyCode == 27) { // escape key maps to keycode `27`
        $(".toolbarbutton").removeClass("open")
        $(".itemaction").removeClass("clicked")
      }
    });
  }

  async run(){
    await mscp.ready;
    this.types = await mscp.types()
    this.addView(getUrlVar("folder") || "/")
  }

  addView(folder){
    let id = `folderview${this.nextId}`
    this.nextId++

    let view = new FolderView(id)
    view.create()
    view.showFolder(folder)

    this.views[id] = view
  }
}

class FolderView{
  constructor(elementId){
    this.elementId = elementId
  }

  create(){
    this.typeHandler = new TypeHandler(this)

    let html = `

            <button class="backbutton">Back</button>

              <button>Add new</button>

                <select name="type" value="folder" size="${Object.keys(this.typeHandler.types).length}">${this.typeHandler.typesSelectValues}</select>
                <input type="text" name="title" placeholder="Title"></input>

                <button>Add</button>

              <button>Add existing</button>

                <select name="type" value="folder" size="${Object.keys(this.typeHandler.types).length-1}">${this.typeHandler.typesSelectValuesNoFolder}</select>
                <input type="text" name="identifier" placeholder="Identifier"></input>
                <input type="text" name="title" placeholder="Title"></input>

                <button>Add</button>

`

    this.element = $(html)
    $("#content").append(this.element)
    this.element.find(".toolbarbutton > button").click((e) => {
      let isOpen = $(e.target).parent().is(".open")
      this.element.find(".toolbarbutton").removeClass("open")
      $(e.target).parent().toggleClass('open', !isOpen).find('select').focus().val('folder');
      e.stopPropagation();
    })
    this.element.find("button.backbutton").click((e) => this.back($(e.target)))
    this.element.find("span.addnewcontainer typeselct").change((e) => this.typeHandler.addNewTypeChanged($(e.target)))
    this.element.find("span.addnewcontainer button").click((e) => this.typeHandler.addNewExecute($(e.target)))
    this.element.find("span.addexistingcontainer button").click((e) => this.typeHandler.addExistingExecute($(e.target)))
  }

  async showFolder(path){
    path = path.toLowerCase()

    let folder = await mscp.folder(path)
    if(folder == null){
      alert("Unknown folder")
      return;
    }

    this.path = path
    this.element.find(".backbutton").prop("disabled",this.path == "/")
    this.element.find("span.folderpath").html(folder.path)

    let container = this.element.find(".foldercontent")
    container.empty()

    folder.content = folder.content.sort((a, b) => {
      if(a.properties.type == "folder" && b.properties.type != "folder") return -1
      else if(a.properties.type != "folder" && b.properties.type == "folder") return 1
      else return a.properties.title.toLowerCase() > b.properties.title.toLowerCase() ? 1 : -1
    })

    for(let e of folder.content){
      let folderItem = $("
", {class: "folderitem"})

      let title = e.properties.title || e.id
      folderItem.append($("", {src: this.typeHandler.types[e.properties.type].icon || "/mscp/libs/img/help.png"}))
      $("", {class: "itemname", html: title}).appendTo(folderItem).click((e) => {this.itemClicked($(e.target).parent()); e.stopPropagation();})
      folderItem.data("item", e)
      folderItem.click((e) => {
        let selected = $(e.currentTarget).is(".selected")
        $(e.currentTarget).parents(".foldercontent").find(".folderitem").removeClass("selected");
        $(e.currentTarget).toggleClass("selected", !selected)
      })

      let itemActions = $(`<span class="itemactions"/>`)

      // DELETE BUTTON
      let deleteActionHTML = `

Are you sure?

                                  Yes
                                  No

                              </`

      let deleteAction = $(deleteActionHTML)
      deleteAction.find(".ok").click((e) => {this.itemDelete($(e.target).parents(".folderitem").data("item")); e.stopPropagation();})
      itemActions.append(deleteAction)

      // RENAME BUTTON
      if(e.properties.type != "folder"){
        let editActionHTML = `

                                    <input name="title" placeholder="Title" value="${title}"/>
                                    Ok
                                    Cancel

                                </`

        let editAction = $(editActionHTML)
        editAction.find(".ok").click((e) => {this.itemRename($(e.target).parents(".folderitem").data("item"), $(e.target).parent().find("input[name=title]").val()); e.stopPropagation();})
        itemActions.append(editAction)

        // MOVE BUTTON
        let moveActionHTML = `

                                    <input name="dest" placeholder="Destination path" value="${this.path}"/>
                                    Ok
                                    Cancel

                                </`

        let moveAction = $(moveActionHTML)
        moveAction.find(".ok").click((e) => {this.itemMove($(e.target).parents(".folderitem").data("item"), $(e.target).parent().find("input[name=dest]").val()); e.stopPropagation();})
        itemActions.append(moveAction)
      }

      // SHARE BUTTON
      if(this.typeHandler.types[e.properties.type].allowShare){
        let shareActionHTML = `

                                    <input type="checkbox" name="writeaccess"/>Write access
                                    <input style="display: none;" type="text" name="generatedlink"/>
                                    Generate
                                    Close

                                </`

        let shareAction = $(shareActionHTML)
        shareAction.find(".generate").click(async (e) => {
          let writeAccess = $(e.target).parents(".folderitem").find("input[name=writeaccess]").is(":checked")
          $(e.target).parents(".folderitem").find("input[name=generatedlink]").val(await this.itemShare($(e.target).parents(".folderitem").data("item"), writeAccess)).show().focus().select();
          e.stopPropagation();
        })
        itemActions.append(shareAction)
      }

      folderItem.append(itemActions)
      container.append(folderItem)
    }

    container.find(".itemaction").click((e) => {
      if(!$(e.target).is("img"))
        return;
      let clicked = $(e.currentTarget).is(".clicked");
      $(".folderitem .itemaction").removeClass("clicked");
      $(e.currentTarget).toggleClass("clicked", !clicked);
      if(!clicked) {
        $(e.currentTarget).find("input:first").focus().select();
        $(e.currentTarget).find("input").keyup((e)=>{if(e.keyCode == 13) $(e.target).parents(".itemaction").find(".ok").click(); e.stopPropagation();});
      }
      e.stopPropagation();
    })
    container.find(".itemaction .cancel").click((e) => {$(e.target).parents(".itemaction").removeClass("clicked"); e.stopPropagation()})
  }

  refreshContent(){
    this.showFolder(this.path)
  }

  itemClicked(itemElement){
    let item = itemElement.data("item")

    if(item.properties.type == "folder"){
      this.showFolder(this.path + item.properties.title)
    } else {
      this.typeHandler.openItem(item)
    }
  }

  back(){
    let idx = this.path.substring(0, this.path.length - 1).lastIndexOf("/")
    if(idx < 0)
      this.showFolder("/")
    else
      this.showFolder(this.path.substring(0, idx+1))
  }

  async itemDelete(item){
    await mscp.remove(this.path, item.id)
    this.refreshContent()
  }

  async itemRename(item, newName){
    await mscp.setProperty(item.id, "title", newName)
    this.refreshContent()
  }

  async itemShare(item, writeAccess){
    return this.typeHandler.getShareableLink(item, writeAccess)
  }

  async itemMove(item, destPath){
    await mscp.move(item.id, this.path, destPath)
    this.refreshContent()
  }
}

var entity = new Entity();
entity.init();
$(() => entity.run());

function getUrlVar( name ){
    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
    var regexS = "[\\?&]"+name+"=([^&#]*)";
    var regex = new RegExp( regexS );
    var results = regex.exec( window.location.href );
    if( results == null )
        return undefined;
    else
        return decodeURIComponent(results[1]);
}
<|endoftext|>


<commit_before>// angular.module('matches.services', [])

// .factory('MatchesFact', function(){

//   var matches = [
  // {
  //   id: 0,
  //   name: 'Ben Sparrow',
  //   lastText: 'You on your way?',
  //   face: 'https://pbs.twimg.com/profile_images/514549811765211136/9SgAuHeY.png',
  //   phone: '530.635.4095'
  // }, {
  //   id: 1,
  //   name: 'Max Lynx',
  //   lastText: 'Hey, it\'s me',
  //   face: 'https://avatars3.githubusercontent.com/u/11214?v=3&s=460',
  //   phone: '530.635.4095'
  // }, {
  //   id: 2,
  //   name: 'Andrew Jostlin',
  //   lastText: 'Did you get the ice cream?',
  //   face: 'https://pbs.twimg.com/profile_images/491274378181488640/Tti0fFVJ.jpeg',
  //   phone: '530.635.4095'
  // }, {
  //   id: 3,
  //   name: 'Adam Bradleyson',
  //   lastText: 'I should buy a boat',
  //   face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg',
  //   phone: '530.635.4095'
  // }, {
  //   id: 4,
  //   name: 'Perry Governor',
  //   lastText: 'Look at my mukluks!',
  //   face: 'https://pbs.twimg.com/profile_images/491995398135767040/ie2Z_V6e.jpeg',
  //   phone: '530.635.4095'
  // }
  ];

  return {
    all: function() {
     return matches;
    },
    remove: function(match) {
      matches.splice(matches.indexOf(match), 1);
    },
    get: function(matchId) {
      for (var i = 0; i < matches.length; i++) {
        if (matches[i].id === parseInt(matchId)) {
          return matches[i];
        }
      }
      return null;
    },
    add: function(match){
      matches.push(match);
    }
  };

})<commit_msg>(fix) Fix syntax error for travis<commit_after>// angular.module('matches.services', [])

// .factory('MatchesFact', function(){

//   var matches = [
  // {
  //   id: 0,
  //   name: 'Ben Sparrow',
  //   lastText: 'You on your way?',
  //   face: 'https://pbs.twimg.com/profile_images/514549811765211136/9SgAuHeY.png',
  //   phone: '530.635.4095'
  // }, {
  //   id: 1,
  //   name: 'Max Lynx',
  //   lastText: 'Hey, it\'s me',
  //   face: 'https://avatars3.githubusercontent.com/u/11214?v=3&s=460',
  //   phone: '530.635.4095'
  // }, {
  //   id: 2,
  //   name: 'Andrew Jostlin',
  //   lastText: 'Did you get the ice cream?',
  //   face: 'https://pbs.twimg.com/profile_images/491274378181488640/Tti0fFVJ.jpeg',
  //   phone: '530.635.4095'
  // }, {
  //   id: 3,
  //   name: 'Adam Bradleyson',
  //   lastText: 'I should buy a boat',
  //   face: 'https://pbs.twimg.com/profile_images/479090794058379264/84TKj_qa.jpeg',
  //   phone: '530.635.4095'
  // }, {
  //   id: 4,
  //   name: 'Perry Governor',
  //   lastText: 'Look at my mukluks!',
  //   face: 'https://pbs.twimg.com/profile_images/491995398135767040/ie2Z_V6e.jpeg',
  //   phone: '530.635.4095'
  // }
  // ];

  return {
    all: function() {
     return matches;
    },
    remove: function(match) {
      matches.splice(matches.indexOf(match), 1);
    },
    get: function(matchId) {
      for (var i = 0; i < matches.length; i++) {
        if (matches[i].id === parseInt(matchId)) {
          return matches[i];
        }
      }
      return null;
    },
    add: function(match){
      matches.push(match);
    }
  };

})<|endoftext|>