<commit_before>import React from 'react';
import Helmet from 'react-helmet';
import { graphql } from 'gatsby';
import { MDXRenderer } from 'gatsby-plugin-mdx';

import Layout from '../../../../src/components/Layout';
import Sidebar from './Sidebar';
import DocFooter from '../../../../src/components/DocFooter';

import Link from '../../../../src/components/Link';

import isAesPage from './isAesPage';
import isApiGatewayPage from './isApiGatewayPage';

import template from '../../../../src/utils/template';

import docLinks from './doc-links.yml';
import versions from './versions.yml';

function removeDoubleSlashes(str) {
  return str.replace(/\/{2,}/g, '/');
}

function getPathFromSlug(str) {
  return removeDoubleSlashes(`/${str}/`);
}

function relativeToAbsUrl(url) {
  if (url.startsWith('http') || url.startsWith('mailto')) {
    return url;
  } else
    return 'https://www.getambassador.io' + removeDoubleSlashes(`/${url}/`);
}

const getDocPageSchema = ({
  slug,
  // an array of { title, slug } relative to parent pages (only if applicable)
  // This doesn't include the root docs page nor the page itself
  breadcrumbs = [],
  // the doc page title (required)
  title,
  // the current docs version (required)
  version,
  // the current sidebar section (only if applicable)
  section,
  isFAQ,
  isLatest,
}) => ({
  '@context': 'http://schema.org',
  '@type': isFAQ ? 'FAQPage' : 'WebPage',
  '@id': relativeToAbsUrl(slug),
  // Not every search engine has assemblyVersion figured out (see below),
  // we want to separate this doc page from others of different versions 😉
  version,
  breadcrumb: {
    '@type': 'BreadcrumbList',
    itemListElement: [
      // Every doc page will have this as the root
      {
        '@type': 'ListItem',
        position: 1,
        item: {
          // be sure to update this /latest with the current version
          '@id': isLatest
            ? relativeToAbsUrl('/docs/latest/')
            : relativeToAbsUrl(`/docs/${version}/`),
          name: 'Ambassador Docs',
        },
      },
      ...breadcrumbs.map((crumb, i) => ({
        '@type': 'ListItem',
        // start at position 2
        position: i + 2,
        item: {
          '@id': relativeToAbsUrl(crumb.slug),
          name: crumb.title,
        },
      })),
      {
        '@type': 'ListItem',
        position: 1 + breadcrumbs.length + 1,
        item: {
          '@id': relativeToAbsUrl(slug),
          name: title,
        },
      },
    ],
  },
  mainEntity: {
    '@type': 'APIReference',
    headline: title,
    inLanguage: 'en',
    isPartOf: 'https://www.getambassador.io/#software',
    // the current docs version
    assemblyVersion: version,
    // the sidebar section, if applicable,
    articleSection: section,
    // @TODO: check this license
    license: 'Apache-2.0',
    // @TODO: check this programmingModel
    programmingModel: 'unmanaged',
    // @TODO: adding keywords related to this doc page would be optimal
    keywords:
      'Kubernertes,API Gateway,Edge Stack,Envoy Proxy,Kubernetes Ingress,Load Balancer,Identity Aware Proxy,Developer Portal, microservices, open source',
  },
});

// Used to get a flat array of *all* links with their corresponding parents
function flatAllLinks(links, parent) {
  return links.reduce((acc, cur) => {
    let link = cur;
    if (parent) {
      link = { ...cur, parent };
    }
    if (!link.items) {
      return [...acc, link];
    }
    return [...acc, link, ...flatAllLinks(link.items, link)];
  }, []);
}

export default ({ data, location }) => {
  const page = data.mdx || {};
  const title =
    page.headings && page.headings[0] ? page.headings[0].value : 'Docs';

  const aesPage = isAesPage(page.fields.slug);
  const apiGatewayPage = isApiGatewayPage(page.fields.slug);

  const metaDescription = page.frontmatter
    ? page.frontmatter.description
    : null;

  // docs/version/path/to/page
  const slug = data.mdx.fields.slug || location.pathname;

  // we don't need the version, which is the first element of the array
  const [, ...rest] = slug
    // remove the docs part
    .replace(/(\/docs\/)|(docs\/)/, '')
    // get the parts of the path by splitting it
    .split('/');

  // Finally, build the canonical URL: we know the initial part (docs/latest)
  // and need to append the rest of the original slug to it
  const canonicalUrl = `https://www.getambassador.io/docs/latest${removeDoubleSlashes(
    // Also, we can add a trailing slash to make sure we're pointing to the right URL
    `/${rest.join('/')}/`,
  )}`;

  // For Schema purposes, we want to make the relationship between pages and their parents explicit
  // So we flat all links (see flatAllLinks above)
  const flatLinks = flatAllLinks(docLinks);
  // Find the current expanded link
  const expandedLink = flatLinks.find(
    (l) => getPathFromSlug(l.link) === getPathFromSlug(slug),
  );
  let breadcrumbs = [];
  let section;
  // And check to see if it has any parent
  if (expandedLink && expandedLink.parent) {
    if (expandedLink.parent.link) {
      // If it does, that's the Schema section and part of the breadcrumbs
      section = expandedLink.parent.title;
      breadcrumbs.push({
        title: expandedLink.parent.title,
        slug: expandedLink.parent.link,
      });
    }
    // If the parent also has a parent, then that's also part of the breadcrumbs
    if (expandedLink.parent.parent && expandedLink.parent.parent.link) {
      breadcrumbs = [
        {
          title: expandedLink.parent.parent.title,
          slug: expandedLink.parent.parent.link,
        },
        ...breadcrumbs,
      ];
    }
  }
  return (
    <React.Fragment>
      <Helmet>
        <title>{title} | Ambassador</title>
        <meta name="og:title" content={`${title} | Ambassador`} />
        <meta name="og:type" content="article" />
        <link rel="canonical" href={canonicalUrl} />
        {metaDescription && (
          <meta name="description" content={metaDescription} />
        )}

      </Helmet>
      <Layout location={location}>
        <Sidebar location={location} prefix="" items={docLinks} />

              {aesPage && (
                <Link className="doc-tag aes" to="/editions">
                  Ambassador Edge Stack
                </Link>
              )}
              {apiGatewayPage && (
                <Link className="doc-tag api" to="/editions/">
                  Ambassador API Gateway
                </Link>
              )}

            <MDXRenderer slug={page.fields.slug}>
              {template(page.body, versions)}
            </MDXRenderer>

Questions?

                We’re here to help. If you have questions,{' '}
                join our Slack,{' '}
                contact us, or{' '}
                request a demo.

        <DocFooter page={page} branch="master" />
      </Layout>
    </React.Fragment>
  );
};

export const query = graphql`
  query($slug: String!) {
    mdx(fields: { slug: { eq: $slug } }) {
      body
      fields {
        slug
      }
      headings(depth: h1) {
        value
      }
      frontmatter {
        description
      }
      parent {
        ... on File {
          relativePath
        }
      }
    }
  }
`;
<commit_msg>Updating Schema to the latest version<commit_after>import React from 'react';
import Helmet from 'react-helmet';
import { graphql } from 'gatsby';
import { MDXRenderer } from 'gatsby-plugin-mdx';

import Layout from '../../../../src/components/Layout';
import Sidebar from './Sidebar';
import DocFooter from '../../../../src/components/DocFooter';

import Link from '../../../../src/components/Link';

import isAesPage from './isAesPage';
import isApiGatewayPage from './isApiGatewayPage';

import template from '../../../../src/utils/template';

import docLinks from './doc-links.yml';
import versions from './versions.yml';

function removeDoubleSlashes(str) {
  return str.replace(/\/{2,}/g, '/');
}

function getPathFromSlug(str) {
  return removeDoubleSlashes(`/${str}/`);
}

function relativeToAbsUrl(slug) {
  return 'https://www.getambassador.io' + getPathFromSlug(slug);
}

function getMainDocsUrl(slug) {
  // All doc pages slugs follow the pattern /docs/{VERSION}/{PATH}
  // This regex extracts the /docs/{VERSION}/ part to find the current page's main docs slug
  const mainDocsSlug = getPathFromSlug(slug).match(/\/docs\/[\d\.(latest)]*/)
  // If, for some reason, we can't find this part (regex matches nothing in the slug string), we assume /docs/latest/
  return relativeToAbsUrl(mainDocsSlug ? mainDocsSlug[0] : '/docs/latest/')
}

// Used to get a flat array of *all* links with their corresponding parents
function flattenLinks(links, parent) {
  return links.reduce((acc, cur) => {
    let link = cur;
    if (parent) {
      link = { ...cur, parent };
    }
    if (!link.items) {
      return [...acc, link];
    }
    return [...acc, link, ...flattenLinks(link.items, link)];
  }, []);
}

const getDocPageSchema = ({
  slug,
  // an array of { title, slug } relative to parent pages (only if applicable)
  // This doesn't include the root docs page nor the page itself
  breadcrumbs = [],
  // the doc page title (required)
  title,
  // the current docs version (required)
  version,
  // the current sidebar section (only if applicable)
  section,
  isFAQ,
}) => ({
  '@context': 'http://schema.org',
  '@type': isFAQ ? 'FAQPage' : 'WebPage',
  '@id': relativeToAbsUrl(slug),
  // Search engines normally penalize sites for duplicating content.
  // We want to communicate to the search engine "we're hosting multiple versions of the docs, please don't penalize us for having content that is duplicated in multiple versions".
  // Principally, we do that with assemblyVersion (below), but some search engines don't have assemblyVersion (the version of the software being described) figured out, so we set version (the version of the web page describing the software) too.
  version,
  breadcrumb: {
    '@type': 'BreadcrumbList',
    itemListElement: [
      // Every page (except the main docs pages) will have this as the root
      {
        '@type': 'ListItem',
        position: 1,
        item: {
          '@id': getMainDocsUrl(slug),
          name: 'Ambassador Docs',
        },
      },
      ...breadcrumbs.map((crumb, i) => ({
        '@type': 'ListItem',
        // start at position 2
        position: i + 2,
        item: {
          '@id': relativeToAbsUrl(crumb.slug),
          name: crumb.title,
        },
      })),
    ],
  },
  mainEntity: {
    '@type': 'APIReference',
    headline: title,
    inLanguage: 'en',
    isPartOf: 'https://www.getambassador.io/#software',
    // the currently selected docs version
    assemblyVersion: version,
    // the sidebar section / parent link, if applicable,
    articleSection: section,
    license: 'Apache-2.0',
    keywords:
      'Kubernertes,API Gateway,Edge Stack,Envoy Proxy,Kubernetes Ingress,Load Balancer,Identity Aware Proxy,Developer Portal, microservices, open source',
  },
});

function useDocSEO({ slug, title }) {
  // we don't need the version, which is the first element of the array
  const [, ...rest] = slug
    // remove the docs part
    .replace(/(\/docs\/)|(docs\/)/, '')
    // get the parts of the path by splitting it
    .split('/');

  // Finally, build the canonical URL: we know the initial part (docs/latest)
  // and need to append the rest of the original slug to it
  const canonicalUrl = `https://www.getambassador.io/docs/latest${removeDoubleSlashes(
    // Also, we can add a trailing slash to make sure we're pointing to the right URL
    `/${rest.join('/')}/`,
  )}`;

  // For Schema purposes, we want to make the relationship between pages and their parents explicit
  // So we flatten all links (see flattenLinks above)
  const flatLinks = flattenLinks(docLinks);
  // Find the current expanded link
  const expandedLink = flatLinks.find(
    (l) => getPathFromSlug(l.link) === getPathFromSlug(slug),
  );

  // We also need a list of parent links to display in the Schema as breadcrumbs
  let breadcrumbs = [];
  // And if this page is inside a given sidebar section, we'll also include it in the Schema (as an articleSection property)
  let section;

  function parseBreadcrumbs(menuEntry) {
    if (!menuEntry) {
      return
    }
    // We'll only add a menu entry to the breadcrumbs array if it has a link
    if (menuEntry.link) {
      breadcrumbs = [
        { title: menuEntry.title, slug: menuEntry.link },
        ...breadcrumbs,
      ];
    }
    // If it has a parent, we'll have to process it as well
    if (menuEntry.parent) {
      // The section is a textual representation of where in the docs the current page is found
      // If it's already defined, it means we have more than one parent-level, so we separate each of them with a " > "
      section = section
        ? `${menuEntry.parent.title} > ${section}`
        : menuEntry.parent.title;
      // This process is recursive as, theoretically, we could have infinitely nested links in the docs sidebar
      parseBreadcrumbs(menuEntry.parent);
    }
  }
  if (getMainDocsUrl(slug) === relativeToAbsUrl(slug)) {
    // If the current slug is that of the main page for the current docs version (/docs/latest, /docs/1.4/, etc.), then we don't want to parse breadcrumbs for it.
    // If we did, we'd have duplicate breadcrumbs in the getDocPageSchema func()
  } else {
    parseBreadcrumbs(expandedLink);
  }

  // We only want the major and minor versions as the docs doesn't differentiate between fixes (1.5.0 and 1.5.4 have the same docs, for example)
  // 1.5.2 => [1, 5, 2] => [1, 5] => 1.5
  const docsVersion = versions.version.split('.').slice(0, 2).join('.');

  const schema = getDocPageSchema({
    slug,
    title,
    version: docsVersion,
    isFAQ: slug.includes('about/faq/'),
    breadcrumbs,
    section,
  });

  return {
    canonicalUrl,
    schema,
  };
}

export default ({ data, location }) => {
  const page = data.mdx || {};
  const title =
    page.headings && page.headings[0] ? page.headings[0].value : 'Docs';

  const aesPage = isAesPage(page.fields.slug);
  const apiGatewayPage = isApiGatewayPage(page.fields.slug);

  const metaDescription = page.frontmatter
    ? page.frontmatter.description
    : page.excerpt;

  // docs/version/path/to/page
  const slug = data.mdx.fields.slug || location.pathname;

  const { canonicalUrl, schema } = useDocSEO({ slug, title });

  return (
    <React.Fragment>
      <Helmet>
        <title>{title} | Ambassador</title>
        <meta name="og:title" content={`${title} | Ambassador`} />
        <meta name="og:type" content="article" />
        <link rel="canonical" href={canonicalUrl} />
        {metaDescription && (
          <meta name="description" content={metaDescription} />
        )}

      </Helmet>
      <Layout location={location}>
        <Sidebar location={location} prefix="" items={docLinks} />

              {aesPage && (
                <Link className="doc-tag aes" to="/editions">
                  Ambassador Edge Stack
                </Link>
              )}
              {apiGatewayPage && (
                <Link className="doc-tag api" to="/editions/">
                  Ambassador API Gateway
                </Link>
              )}

            <MDXRenderer slug={page.fields.slug}>
              {template(page.body, versions)}
            </MDXRenderer>

Questions?

                We’re here to help. If you have questions,{' '}
                join our Slack,{' '}
                contact us, or{' '}
                request a demo.

        <DocFooter page={page} branch="master" />
      </Layout>
    </React.Fragment>
  );
};

export const query = graphql`
  query($slug: String!) {
    mdx(fields: { slug: { eq: $slug } }) {
      body
      fields {
        slug
      }
      excerpt(pruneLength: 150, truncate: true)
      headings(depth: h1) {
        value
      }
      frontmatter {
        description
      }
      parent {
        ... on File {
          relativePath
        }
      }
    }
  }
`;
<|endoftext|>


<commit_before>function AutoFillTodaysDate(day, month, year, checkboxId, dayId, monthId, yearId) {
    var dod_elm = document.getElementById(checkboxId);
    var dod_day = document.getElementById(dayId);
    var dod_month = document.getElementById(monthId);
    var dod_year = document.getElementById(yearId);

    if (dod_elm.checked === false) {
        dod_day.value = '';
        dod_month.value = '';
        dod_year.value = '';
    } else {
        dod_day.value = day;
        dod_month.value = month;
        dod_year.value = year;
    }
}<commit_msg>remove unnecessary js<commit_after><|endoftext|>


<commit_before>/**
 * Khan's Boots
 * ============
 * A simple game based on the classic "Rocky's Boots", created for the Khan
 * Academy Computer Science platform.
 *
 * Currently a work in progress.
 *
 * This is released to the public domain. Feel free to use it as you please.
 */

/*************
 ** Objects **
 *************/

//
// $
//
// Global object, used to store all sort of things from the game
//
var $ = {};

//
// Configuration
//
$.cfg = {
	accel    : 1,          // acceleration, in pixels/frame^2
	speedMax : 15,         // maximum speed, in pixels/frame
	u        : width / 32  // basic "length" unit in pixels
};

//
// Colors, based on the Tango Icon Theme Guidelines
//
$.colors = {
	yellow : [ 0xfce94f, 0xedd400, 0xc4a000 ],
	orange : [ 0xfcaf3e, 0xf57900, 0xce5c00 ],
	brown  : [ 0xe9b96e, 0xc17d11, 0x8f5902 ],
	green  : [ 0x8ae234, 0x73d216, 0x4e9a06 ],
	blue   : [ 0x729fcf, 0x3465a4, 0x204a87 ],
	purple : [ 0xad7fa8, 0x75507b, 0x5c3566 ],
	red    : [ 0xef2929, 0xcc0000, 0xa40000 ]
};

//
// Objects that are able to listen to different events
//
$.callbacks = {
	frame       : [],
	draw        : [],
	keyPressed  : [],
	keyReleased : []
};

//
// A room
//
$.room = [];

/*************
 ** Classes **
 *************/

//
// KhanObject
//
// The basic class from which most other objects inherit.
//
var KhanObject = function() {};
KhanObject.prototype = {
	x : 0, y : 0
};

//
// Hand
//
// The "cursor" with which you interact in the world
//
var Hand = function() {};
Hand.prototype = {
	vx : 0, vy : 0,
	ax : 0, ay : 0,

	w : 0, h : 0,

	onInit : function() {
		this.w = this.h = $.cfg.u * 2;
		this.x = (width - this.w) / 2;
		this.y = (height - this.h) / 2;
		this.kol = $.colors.red[0] | 0xdd000000;
	},

	onFrame : function() {
		if (this.ax !== 0) { this.vx += this.ax; }
		if (this.ay !== 0) { this.vy += this.ay; }

		this.vx = constrain(this.vx, -$.cfg.speedMax, $.cfg.speedMax);
		this.vy = constrain(this.vy, -$.cfg.speedMax, $.cfg.speedMax);

		this.x += this.vx;
		this.y += this.vy;

		this.x = constrain(this.x, 0, width - this.w);
		this.y = constrain(this.y, 0, height - this.h);
	},

	onDraw : function() {
		noStroke();
		fill(this.kol);
		rect(this.x, this.y, this.w, this.h);
	},

	onKeyPressed : function(k, kc) {
		if (kc === RIGHT) { this.ax = $.cfg.accel; }
		else if (kc === LEFT) { this.ax = -$.cfg.accel; }
		else if (kc === UP) { this.ay = -$.cfg.accel; }
		else if (kc === DOWN) { this.ay = $.cfg.accel; }
	},

	onKeyReleased : function(k, kc) {
		if (kc === RIGHT || kc === LEFT) {
			this.ax = 0; this.vx = 0;
		}
		else if (kc === UP || kc === DOWN) {
			this.ay = 0; this.vy = 0;
		}
	}
};

//
// Boot
//
// A boot. It kicks things.
//
var Boot = function() {};
Boot.prototype = {

};

/***************
 ** Functions **
 ***************/

$.main = function() {
	$.room.push(new Hand());

	$.room.forEach(function(obj) {
		if (typeof(obj.onInit) === 'function') { obj.onInit(); }
		if (typeof(obj.onFrame) === 'function') {
			$.callbacks.frame.push(obj);
		}
		if (typeof(obj.onDraw) === 'function') {
			$.callbacks.draw.push(obj);
		}
		if (typeof(obj.onKeyPressed) === 'function') {
			$.callbacks.keyPressed.push(obj);
		}
		if (typeof(obj.onKeyReleased) === 'function') {
			$.callbacks.keyReleased.push(obj);
		}
	});
};

var draw = function() {
	$.callbacks.frame.forEach(function(obj) { obj.onFrame(); });

	background(255, 255, 255);

	$.callbacks.draw.forEach(function(obj) { obj.onDraw(); });
};

var keyPressed = function() {
	$.callbacks.keyPressed.forEach(function(obj) {
		obj.onKeyPressed(key, keyCode);
	});

};

var keyReleased = function() {
	$.callbacks.keyReleased.forEach(function(obj) {
		obj.onKeyReleased(key, keyCode);
	});
};

$.main();
<commit_msg>Added basic drawing of boot<commit_after>/**
 * Khan's Boots
 * ============
 * A simple game based on the classic "Rocky's Boots", created for the Khan
 * Academy Computer Science platform.
 *
 * Currently a work in progress.
 *
 * This is released to the public domain. Feel free to use it as you please.
 */

/*************
 ** Objects **
 *************/

//
// $
//
// Global object, used to store all sort of things for the game
//
var $ = {};

//
// Configuration
//
$.cfg = {
	accel    : 1,          // acceleration, in pixels/frame^2
	speedMax : 15,         // maximum speed, in pixels/frame
	u        : width / 32  // basic "length" unit in pixels
};

//
// Colors, based on the Tango Icon Theme Guidelines
//
$.colors = {
	yellow : [ 0xfce94f, 0xedd400, 0xc4a000 ],
	orange : [ 0xfcaf3e, 0xf57900, 0xce5c00 ],
	brown  : [ 0xe9b96e, 0xc17d11, 0x8f5902 ],
	green  : [ 0x8ae234, 0x73d216, 0x4e9a06 ],
	blue   : [ 0x729fcf, 0x3465a4, 0x204a87 ],
	purple : [ 0xad7fa8, 0x75507b, 0x5c3566 ],
	red    : [ 0xef2929, 0xcc0000, 0xa40000 ]
};

//
// Objects that are able to listen to different events
//
$.callbacks = {
	frame       : [],
	draw        : [],
	keyPressed  : [],
	keyReleased : []
};

//
// A room
//
$.room = [];

/*************
 ** Classes **
 *************/

//
// Utility function to implement inheritance
//
$.extend = function(obj, from) {
	for (var p in from) { obj[p] = from[p]; }
};

//
// KhanObject
//
// The basic class from which most other objects inherit.
//
var KhanObject = function() {};
$.extend(KhanObject.prototype, {
	x : 0, y : 0
});

//
// Hand
//
// The "cursor" with which you interact in the world
//
var Hand = function() {};
Hand.prototype = new KhanObject();
Hand.prototype.constructor = Hand;

$.extend(Hand.prototype, {
	vx : 0, vy : 0,
	ax : 0, ay : 0,

	w : 0, h : 0
});

Hand.prototype.onInit = function() {
	this.w = this.h = $.cfg.u * 2;
	this.x = (width - this.w) / 2;
	this.y = (height - this.h) / 2;
	this.kol = $.colors.red[0] | 0xaa000000;
};

Hand.prototype.onFrame = function() {
	if (this.ax !== 0) { this.vx += this.ax; }
	if (this.ay !== 0) { this.vy += this.ay; }

	this.vx = constrain(this.vx, -$.cfg.speedMax, $.cfg.speedMax);
	this.vy = constrain(this.vy, -$.cfg.speedMax, $.cfg.speedMax);

	this.x += this.vx;
	this.y += this.vy;

	this.x = constrain(this.x, 0, width - this.w);
	this.y = constrain(this.y, 0, height - this.h);
};

Hand.prototype.onDraw = function() {
	noStroke();
	fill(this.kol);
	rect(this.x, this.y, this.w, this.h);
};

Hand.prototype.onKeyPressed = function(k, kc) {
	if (kc === RIGHT) { this.ax = $.cfg.accel; }
	else if (kc === LEFT) { this.ax = -$.cfg.accel; }
	else if (kc === UP) { this.ay = -$.cfg.accel; }
	else if (kc === DOWN) { this.ay = $.cfg.accel; }
};

Hand.prototype.onKeyReleased = function(k, kc) {
	if (kc === RIGHT || kc === LEFT) {
		this.ax = 0; this.vx = 0;
	}
	else if (kc === UP || kc === DOWN) {
		this.ay = 0; this.vy = 0;
	}
};

//
// Boot
//
// A boot. It kicks things.
//
var Boot = function() {};
Boot.prototype = new KhanObject();
Boot.prototype.constructor = Boot;

Boot.prototype.onInit = function() {
	this.x = width / 3;
	this.y = height / 2;

	this.kol = $.colors.brown[0] | 0xff000000;
};

Boot.prototype.onDraw = function() {
	noStroke();
	fill(this.kol);
	rect(this.x, this.y, $.cfg.u * 2, $.cfg.u * 3);
	arc(this.x + $.cfg.u * 2.5, this.y + $.cfg.u * 3,
	    $.cfg.u * 3, $.cfg.u * 3, 180, 360);
};

/***************
 ** Functions **
 ***************/

//
// Entry point for the program
//
$.kickIt = function() {
	$.room.push(new Boot(), new Hand());

	$.room.forEach(function(obj) {
		if (typeof(obj.onInit) === 'function') { obj.onInit(); }
		if (typeof(obj.onFrame) === 'function') {
			$.callbacks.frame.push(obj);
		}
		if (typeof(obj.onDraw) === 'function') {
			$.callbacks.draw.push(obj);
		}
		if (typeof(obj.onKeyPressed) === 'function') {
			$.callbacks.keyPressed.push(obj);
		}
		if (typeof(obj.onKeyReleased) === 'function') {
			$.callbacks.keyReleased.push(obj);
		}
	});
};

//
// Processing.JS callback for "draw" event
//
var draw = function() {
	$.callbacks.frame.forEach(function(obj) { obj.onFrame(); });

	background(255, 255, 255);

	$.callbacks.draw.forEach(function(obj) { obj.onDraw(); });
};

//
// Processing.JS callback for "keyPressed" event
//
var keyPressed = function() {
	$.callbacks.keyPressed.forEach(function(obj) {
		obj.onKeyPressed(key, keyCode);
	});

};

//
// Processing.JS callback for "keyReleased" event
//
var keyReleased = function() {
	$.callbacks.keyReleased.forEach(function(obj) {
		obj.onKeyReleased(key, keyCode);
	});
};

//
// Let's start this party...
//
$.kickIt();
<|endoftext|>


<commit_before>const pkg = require('./package.json');

const fs = require('fs');
const path = require('path');

const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const SassLintPlugin = require('sasslint-webpack-plugin');
const UnminifiedWebpackPlugin = require('unminified-webpack-plugin');
const customLoader = require('custom-loader');

const archiver = require('archiver');

const extractSrc = new ExtractTextPlugin('vizabi.css');

const __PROD__ = process.env.NODE_ENV === 'production';
const timestamp = new Date();

const stats = {
  colors: true,
  hash: false,
  version: false,
  timings: true,
  assets: false,
  chunks: false,
  modules: false,
  reasons: true,
  children: false,
  source: false,
  errors: true,
  errorDetails: true,
  warnings: true,
  publicPath: false
};

function AfterBuildPlugin(callback) {
  this.callback = callback;
}
AfterBuildPlugin.prototype.apply = function(compiler) {
  compiler.plugin('done', this.callback);
};

customLoader.loaders = {
  ['config-loader'](source) {
    this.cacheable && this.cacheable();

    const value = typeof source === 'string' ? JSON.parse(source) : source;
    this.value = [value];
    return `var VIZABI_MODEL = ${JSON.stringify(value, undefined, '  ')};`;
  }
};

const loaders = [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loaders: [
      {
        loader: 'babel-loader',
        query: {
          cacheDirectory: !__PROD__,
          presets: ['es2015']
        }
      }
    ]
  },
  {
    test: /\.scss$/,
    include: [
      path.resolve(__dirname, 'src')
    ],
    loader: extractSrc.extract([
      {
        loader: 'css-loader',
        options: {
          minimize: __PROD__,
          sourceMap: true
        }
      },
      {
        loader: 'postcss-loader'
      },
      {
        loader: 'sass-loader'
      }
    ])
  },
  {
    test: /\.cur$/,
    loader: 'file-loader',
    query: {
      publicPath: path => path.split('/').slice(1).join('/'),
      name: 'preview/assets/cursors/[name].[ext]'
    }
  },
  {
    test: /\.html$/,
    include: [path.resolve(__dirname, 'src')],
    loader: 'html-loader'
  },
];

module.exports = output => {
  const plugins = [
    new CleanWebpackPlugin(['build']),
    extractSrc,
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, 'src', 'assets', 'translation'),
        to: path.resolve(output || path.resolve(__dirname, 'build'), 'assets', 'translation'),
      }
    ]),
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, 'src', 'assets', 'cursors'),
        to: path.resolve(output || path.resolve(__dirname, 'build'), 'assets', 'cursors')
      }
    ]),
    new SassLintPlugin({
      quiet: false,
      syntax: 'scss',
      glob: 'src/**/*.s?(a|c)ss',
      ignorePlugins: ['extract-text-webpack-plugin']
    }),
    new webpack.DefinePlugin({
      __VERSION: JSON.stringify(pkg.version),
      __BUILD: +timestamp
    }),
    new webpack.BannerPlugin({
      banner: "((function(){})({version: '" + JSON.stringify(pkg.version) + "'}));",
      raw: true,
      test: /\.js$/
    })
  ];

  if (__PROD__) {
    plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        compressor: {
          screw_ie8: true,
          warnings: false
        },
        mangle: {
          screw_ie8: true
        },
        output: {
          comments: false,
          screw_ie8: true
        }
      }),
      new UnminifiedWebpackPlugin(),
      new AfterBuildPlugin(() => {
        const archive = archiver('zip');
        const files = [
          'vizabi.css',
          'vizabi.min.js',
          'vizabi.js'
        ];

        files.forEach(name =>
          archive.append(
            fs.createReadStream(path.resolve('build', name)),
            { name }
          )
        );

        archive.pipe(
          fs.createWriteStream(path.resolve('build', 'vizabi.zip'))
        );
        archive.glob('**/*', { cwd: 'src/assets/cursors', dot: true }, { prefix: 'assets/cursors' });
        archive.glob('en.json', { cwd: 'src/assets/translation', dot: true }, { prefix: 'assets/translation' });
        archive.finalize();
      }),
      new webpack.BannerPlugin({
        banner: [
          '/**',
          ' * ' + pkg.name + ' - ' + pkg.description,
          ' * @version v' + pkg.version,
          ' * @build timestamp ' + timestamp,
          ' * @link ' + pkg.homepage,
          ' * @license ' + pkg.license,
          ' */',
          ''
        ].join('\n'),
        raw: true
      })
    )
  }

  return {

    devtool: 'source-map',

    entry: {
      'vizabi': path.resolve(__dirname, 'src', 'vizabi-gapminder'),
    },

    output: {
      path: output || path.resolve(__dirname, 'build'),
      filename: __PROD__ ? '[name].min.js' : '[name].js',
      library: 'Vizabi',
      libraryTarget: 'umd',
      umdNamedDefine: true
    },

    resolveLoader: {
      modules: [
        'web_loaders',
        'web_modules',
        'node_loaders',
        'node_modules',
        path.resolve(__dirname, 'node_modules'),
      ],
    },
    resolve: {
      modules: [
        path.resolve(__dirname, 'src'),
        'node_modules'
      ]
    },

    module: {
      loaders,
    },

    plugins,

  };
};
<commit_msg>Specify absolute path to sass lint config for scss webpack plugin to make it work correctly in vizabi-preview<commit_after>const pkg = require('./package.json');

const fs = require('fs');
const path = require('path');

const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const SassLintPlugin = require('sasslint-webpack-plugin');
const UnminifiedWebpackPlugin = require('unminified-webpack-plugin');
const customLoader = require('custom-loader');

const archiver = require('archiver');

const extractSrc = new ExtractTextPlugin('vizabi.css');

const __PROD__ = process.env.NODE_ENV === 'production';
const timestamp = new Date();

const stats = {
  colors: true,
  hash: false,
  version: false,
  timings: true,
  assets: false,
  chunks: false,
  modules: false,
  reasons: true,
  children: false,
  source: false,
  errors: true,
  errorDetails: true,
  warnings: true,
  publicPath: false
};

function AfterBuildPlugin(callback) {
  this.callback = callback;
}
AfterBuildPlugin.prototype.apply = function(compiler) {
  compiler.plugin('done', this.callback);
};

customLoader.loaders = {
  ['config-loader'](source) {
    this.cacheable && this.cacheable();

    const value = typeof source === 'string' ? JSON.parse(source) : source;
    this.value = [value];
    return `var VIZABI_MODEL = ${JSON.stringify(value, undefined, '  ')};`;
  }
};

const loaders = [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loaders: [
      {
        loader: 'babel-loader',
        query: {
          cacheDirectory: !__PROD__,
          presets: ['es2015']
        }
      }
    ]
  },
  {
    test: /\.scss$/,
    include: [
      path.resolve(__dirname, 'src')
    ],
    loader: extractSrc.extract([
      {
        loader: 'css-loader',
        options: {
          minimize: __PROD__,
          sourceMap: true
        }
      },
      {
        loader: 'postcss-loader'
      },
      {
        loader: 'sass-loader'
      }
    ])
  },
  {
    test: /\.cur$/,
    loader: 'file-loader',
    query: {
      publicPath: path => path.split('/').slice(1).join('/'),
      name: 'preview/assets/cursors/[name].[ext]'
    }
  },
  {
    test: /\.html$/,
    include: [path.resolve(__dirname, 'src')],
    loader: 'html-loader'
  },
];

module.exports = output => {
  const plugins = [
    new CleanWebpackPlugin(['build']),
    extractSrc,
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, 'src', 'assets', 'translation'),
        to: path.resolve(output || path.resolve(__dirname, 'build'), 'assets', 'translation'),
      }
    ]),
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, 'src', 'assets', 'cursors'),
        to: path.resolve(output || path.resolve(__dirname, 'build'), 'assets', 'cursors')
      }
    ]),
    new SassLintPlugin({
      configFile: path.resolve(__dirname, '.sass-lint.yml'),
      quiet: false,
      syntax: 'scss',
      glob: 'src/**/*.s?(a|c)ss',
      ignorePlugins: ['extract-text-webpack-plugin']
    }),
    new webpack.DefinePlugin({
      __VERSION: JSON.stringify(pkg.version),
      __BUILD: +timestamp
    }),
    new webpack.BannerPlugin({
      banner: "((function(){})({version: '" + JSON.stringify(pkg.version) + "'}));",
      raw: true,
      test: /\.js$/
    })
  ];

  if (__PROD__) {
    plugins.push(
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        compressor: {
          screw_ie8: true,
          warnings: false
        },
        mangle: {
          screw_ie8: true
        },
        output: {
          comments: false,
          screw_ie8: true
        }
      }),
      new UnminifiedWebpackPlugin(),
      new AfterBuildPlugin(() => {
        const archive = archiver('zip');
        const files = [
          'vizabi.css',
          'vizabi.min.js',
          'vizabi.js'
        ];

        files.forEach(name =>
          archive.append(
            fs.createReadStream(path.resolve('build', name)),
            { name }
          )
        );

        archive.pipe(
          fs.createWriteStream(path.resolve('build', 'vizabi.zip'))
        );
        archive.glob('**/*', { cwd: 'src/assets/cursors', dot: true }, { prefix: 'assets/cursors' });
        archive.glob('en.json', { cwd: 'src/assets/translation', dot: true }, { prefix: 'assets/translation' });
        archive.finalize();
      }),
      new webpack.BannerPlugin({
        banner: [
          '/**',
          ' * ' + pkg.name + ' - ' + pkg.description,
          ' * @version v' + pkg.version,
          ' * @build timestamp ' + timestamp,
          ' * @link ' + pkg.homepage,
          ' * @license ' + pkg.license,
          ' */',
          ''
        ].join('\n'),
        raw: true
      })
    )
  }

  return {

    devtool: 'source-map',

    entry: {
      'vizabi': path.resolve(__dirname, 'src', 'vizabi-gapminder'),
    },

    output: {
      path: output || path.resolve(__dirname, 'build'),
      filename: __PROD__ ? '[name].min.js' : '[name].js',
      library: 'Vizabi',
      libraryTarget: 'umd',
      umdNamedDefine: true
    },

    resolveLoader: {
      modules: [
        'web_loaders',
        'web_modules',
        'node_loaders',
        'node_modules',
        path.resolve(__dirname, 'node_modules'),
      ],
    },
    resolve: {
      modules: [
        path.resolve(__dirname, 'src'),
        'node_modules'
      ]
    },

    module: {
      loaders,
    },

    plugins,

  };
};
<|endoftext|>


<commit_before>// Logic of the usergroup editor interface. It's used by "new" and "edit" pages.
//

'use strict';

var _  = require('lodash');
var ko = require('knockout');

ko.extenders.trackable = function (target) {
  var savedValue = ko.observable(target());

  target.isModified = ko.computed(function () {
    return savedValue() !== target();
  });

  target.markSaved = function () {
    savedValue(target());
  };

  return target;
};

// Single setting of a usergroup.
//
// form (Form): Root form object. See below for Form class.
// name (String): Unique identofier of the setting.
// schema (Object): N.config.setting_schemas.usergroup[name]
// config (Object): Must contain: `group`, `overriden`, `forced`, and `value`.
//
function Setting(form, name, schema, config) {
  var tName = 'admin.setting.' + name
    , tHelp = 'admin.setting.' + name + '_help';

  // Read-only slots.
  //
  this.elementId     = 'setting_' + name; // HTML id attribute.
  this.name          = name;
  this.defaultValue  = schema['default'];
  this.valueType     = schema.type;
  this.categoryKey   = schema.category_key;
  this.priority      = schema.priority;
  this.ownerGroup    = config.group;
  this.localizedName = N.runtime.t(tName);
  this.localizedHelp = N.runtime.t.exists(tHelp) ? N.runtime.t(tHelp) : null;

  // Setting model of `ownerGroup` from which the current setting should inherit
  // the value when it isn't overriden.
  this.parentSetting = ko.computed(function () {
    if (this.ownerGroup && this.ownerGroup.parentGroup()) {
      return this.ownerGroup.parentGroup().settingsByName[this.name];
    } else {
      return null;
    }
  }, this);

  // Private writable slots.
  //
  this._overriden = ko.observable(Boolean(config.overriden));
  this._forced    = ko.observable(Boolean(config.forced));
  this._value     = ko.observable('number' === schema.type ? Number(config.value) : config.value);

  // Public proxy slots. These allows dynamically recompute _shown_ data on
  // parent group change or overriden flag unmark AND keep user's own input
  // at the same time.
  //
  this.overriden = ko.computed({
    read:  function () { return this._overriden() || !this.ownerGroup.parentGroup(); }
  , write: this._overriden
  , owner: this
  }).extend({ trackable: true });

  this.inherited = ko.computed(function () { return !this.overriden(); }, this);

  this.forced = ko.computed({
    read:  function () { return this.overriden() && this._forced(); }
  , write: this._forced
  , owner: this
  }).extend({ trackable: true });

  this.value = ko.computed({
    read: function () {
      if (this.overriden()) {
        return 'number' === this.valueType ? Number(this._value()) : this._value();

      } else if (this.parentSetting()) {
        return this.parentSetting().value();

      } else {
        return this.defaultValue;
      }
    }
  , write: function (newValue) {
      this.overriden(true);
      this._value(newValue);
    }
  , owner: this
  }).extend({ trackable: true });

  // Helpers.
  //
  this.visible = ko.computed(function () {
    var filter = form.filter();

    if ('overriden' === filter) {
      return this.overriden();

    } else if ('inherited' === filter) {
      return this.inherited();

    } else if ('forced' === filter) {
      return this.forced();

    } else {
      return true;
    }
  }, this);

  this.isModified = ko.computed(function () {
    if (this.overriden.isModified()) {
      return true;
    }

    if (this.overriden()) {
      if (this.value.isModified()) {
        return true;
      }
      if (this.forced.isModified()) {
        return true;
      }
    }

    return false;
  }, this);
}

// Marks all trackable data slots as saved.
//
Setting.prototype.markSaved = function markSaved() {
  this.overriden.markSaved();
  this.forced.markSaved();
  this.value.markSaved();
};

// Returns data suitable for the server.
//
Setting.prototype.getOutputData = function getOutputData() {
  return {
    value:  this.value()
  , forced: this.forced()
  };
};

// Named group of settings. (visible interface element)
//
// form (Form): See below for Form class.
// name (String): Title translation key.
// settings (Array): List of related settings.
//
function SettingCategory(form, name, settings) {
  this.name          = name;
  this.localizedName = N.runtime.t('admin.setting.category.' + name);

  this.settings = _.sortBy(settings, 'priority');
  this.priority = _(settings).pluck('priority').reduce(function (a, b) { return a + b; });
}

// Single known user group. Used either for displayed group and for groups in
// the "inherits" list.
//
function UserGroup(form, data) {
  data = data || {};

  var rawSettings;

  if (data.raw_settings) {
    rawSettings = data.raw_settings.usergroup || {};
  } else {
    rawSettings = {};
  }

  // Read-only slots.
  //
  this.objectId    = data._id || null;
  this.isProtected = data.is_protected || false;

  // Writable and savable slots.
  //
  this.name     = ko.observable(data.short_name || '').extend({ trackable: true });
  this.parentId = ko.observable(data.parent_group || null).extend({ trackable: true });

  // Computed values.
  //
  this.localizedName = ko.computed(function () {
    return this.name() ? N.runtime.t('users.usergroup.' + this.name()) : null;
  }, this);

  this.parentGroup = ko.computed({
    read:  function () { return form.groupsById[this.parentId()]; }
  , write: function (group) { this.parentId(group ? group.objectId : null); }
  , owner: this
  });

  // Related settings and categories lists.
  // See Setting and SettingCategory classes for details.
  //
  this.settings         = [];
  this.settingsByName   = {};
  this.categories       = [];
  this.categoriesByName = {};

  // Collect setting models.
  _.forEach(form.setting_schemas, function (schema, name) {
    var setting, overriden = _.has(rawSettings, name);

    setting = new Setting(form, name, schema, {
      group:     this
    , overriden: overriden
    , forced:    overriden ? rawSettings[name].force : false
    , value:     overriden ? rawSettings[name].value : schema['default']
    });

    this.settings.push(setting);
    this.settingsByName[name] = setting;
  }, this);

  this.settings = _.sortBy(this.settings, 'priority');

  // Collect category models.
  _(form.setting_schemas).pluck('category_key').unique().forEach(function (name) {
    var category = new SettingCategory(form, name, _.select(this.settings, { categoryKey: name }));

    this.categories.push(category);
    this.categoriesByName[name] = category;
  }, this);

  this.categories = _.sortBy(this.categories, 'priority');

  // Helpers.
  //
  this.isModified = ko.computed(function () {
    return this.name.isModified()     ||
           this.parentId.isModified() ||
           _(this.settings).invoke('isModified').any();
  }, this);
}

// Marks all trackable data slots and related settings as saved.
//
UserGroup.prototype.markSaved = function markSaved() {
  this.name.markSaved();
  this.parentId.markSaved();
  _.invoke(this.settings, 'markSaved');
};

// Returns data suitable for the server.
//
UserGroup.prototype.getOutputData = function getOutputData() {
  var result = {
    short_name:   this.name()
  , parent_group: this.parentId()
  , raw_settings: {}
  };

  // Add `_id` property only when `this` is a persistent (i.e. saved) group.
  if (this.objectId) {
    result._id = this.objectId;
  }

  _.forEach(this.settings, function (setting) {
    if (setting.overriden()) {
      result.raw_settings[setting.name] = setting.getOutputData();
    }
  });

  return result;
};

// Root view model of the page. It has two modes: 'create' and 'update'.
//
// page_data.setting_schemas (Object): N.config.setting_schemas.usergroup
// page_data.groups_data (Array): List of all existent user groups.
// page_data.current_group_id (String, Optional): ObjectID of a group for edit.
// If this identifier is provided, the form will use 'update' mode.
//
function Form(page_data) {
  this.setting_schemas = page_data.setting_schemas;

  this.groups     = [];
  this.groupsById = {};

  this.filter = ko.observable('');

  this.createMode   = !_.has(page_data, 'current_group_id');
  this.currentGroup = null;
  this.otherGroups  = [];

  if (this.createMode) {
    this.currentGroup = new UserGroup(this);
  }

  _.forEach(page_data.groups_data, function (data) {
    var group = new UserGroup(this, data);

    this.groups.push(group);
    this.groupsById[group.objectId] = group;

    if (!this.createMode && group.objectId === page_data.current_group_id) {
      this.currentGroup = group;
    } else {
      this.otherGroups.push(group);
    }
  }, this);
}

// Sends 'create' request for `currentGroup`.
//
Form.prototype.create = function create() {
  var self = this;

  N.io.rpc('admin.users.usergroups.create', this.currentGroup.getOutputData(), function (err) {
    if (err) {
      N.wire.emit('notify', {
        type: 'error'
      , message: N.runtime.t(N.io.BAD_REQUEST === err.code ?
                             'admin.users.usergroups.form.error.bad_request' :
                             'admin.users.usergroups.form.error.unknown')
      });
      return;
    }

    self.currentGroup.markSaved();

    N.wire.emit('notify', {
      type: 'info'
    , message: N.runtime.t('admin.users.usergroups.form.created')
    });

    // TODO: Replace this with the navigate.js when it will be ported for ACP.
    window.location = N.runtime.router.linkTo('admin.users.usergroups.show');
  });
};

// Sends 'update' request for `currentGroup`.
//
Form.prototype.update = function update() {
  var self = this;

  N.io.rpc('admin.users.usergroups.update', this.currentGroup.getOutputData(), function (err) {
    if (err) {
      N.wire.emit('notify', {
        type: 'error'
      , message: N.runtime.t(N.io.BAD_REQUEST === err.code ?
                             'admin.users.usergroups.form.error.bad_request' :
                             'admin.users.usergroups.form.error.unknown')
      });
      return;
    }

    self.currentGroup.markSaved();

    N.wire.emit('notify', {
      type: 'info'
    , message: N.runtime.t('admin.users.usergroups.form.updated')
    });
  });
};

// Sends save request to the server.
//
Form.prototype.submit = function submit() {
  if (this.createMode) {
    this.create();
  } else {
    this.update();
  }
};

module.exports = Form;
<commit_msg>Fix setting output data format.<commit_after>// Logic of the usergroup editor interface. It's used by "new" and "edit" pages.
//

'use strict';

var _  = require('lodash');
var ko = require('knockout');

ko.extenders.trackable = function (target) {
  var savedValue = ko.observable(target());

  target.isModified = ko.computed(function () {
    return savedValue() !== target();
  });

  target.markSaved = function () {
    savedValue(target());
  };

  return target;
};

// Single setting of a usergroup.
//
// form (Form): Root form object. See below for Form class.
// name (String): Unique identofier of the setting.
// schema (Object): N.config.setting_schemas.usergroup[name]
// config (Object): Must contain: `group`, `overriden`, `forced`, and `value`.
//
function Setting(form, name, schema, config) {
  var tName = 'admin.setting.' + name
    , tHelp = 'admin.setting.' + name + '_help';

  // Read-only slots.
  //
  this.elementId     = 'setting_' + name; // HTML id attribute.
  this.name          = name;
  this.defaultValue  = schema['default'];
  this.valueType     = schema.type;
  this.categoryKey   = schema.category_key;
  this.priority      = schema.priority;
  this.ownerGroup    = config.group;
  this.localizedName = N.runtime.t(tName);
  this.localizedHelp = N.runtime.t.exists(tHelp) ? N.runtime.t(tHelp) : null;

  // Setting model of `ownerGroup` from which the current setting should inherit
  // the value when it isn't overriden.
  this.parentSetting = ko.computed(function () {
    if (this.ownerGroup && this.ownerGroup.parentGroup()) {
      return this.ownerGroup.parentGroup().settingsByName[this.name];
    } else {
      return null;
    }
  }, this);

  // Private writable slots.
  //
  this._overriden = ko.observable(Boolean(config.overriden));
  this._forced    = ko.observable(Boolean(config.forced));
  this._value     = ko.observable('number' === schema.type ? Number(config.value) : config.value);

  // Public proxy slots. These allows dynamically recompute _shown_ data on
  // parent group change or overriden flag unmark AND keep user's own input
  // at the same time.
  //
  this.overriden = ko.computed({
    read:  function () { return this._overriden() || !this.ownerGroup.parentGroup(); }
  , write: this._overriden
  , owner: this
  }).extend({ trackable: true });

  this.inherited = ko.computed(function () { return !this.overriden(); }, this);

  this.forced = ko.computed({
    read:  function () { return this.overriden() && this._forced(); }
  , write: this._forced
  , owner: this
  }).extend({ trackable: true });

  this.value = ko.computed({
    read: function () {
      if (this.overriden()) {
        return 'number' === this.valueType ? Number(this._value()) : this._value();

      } else if (this.parentSetting()) {
        return this.parentSetting().value();

      } else {
        return this.defaultValue;
      }
    }
  , write: function (newValue) {
      this.overriden(true);
      this._value(newValue);
    }
  , owner: this
  }).extend({ trackable: true });

  // Helpers.
  //
  this.visible = ko.computed(function () {
    var filter = form.filter();

    if ('overriden' === filter) {
      return this.overriden();

    } else if ('inherited' === filter) {
      return this.inherited();

    } else if ('forced' === filter) {
      return this.forced();

    } else {
      return true;
    }
  }, this);

  this.isModified = ko.computed(function () {
    if (this.overriden.isModified()) {
      return true;
    }

    if (this.overriden()) {
      if (this.value.isModified()) {
        return true;
      }
      if (this.forced.isModified()) {
        return true;
      }
    }

    return false;
  }, this);
}

// Marks all trackable data slots as saved.
//
Setting.prototype.markSaved = function markSaved() {
  this.overriden.markSaved();
  this.forced.markSaved();
  this.value.markSaved();
};

// Returns data suitable for the server.
//
Setting.prototype.getOutputData = function getOutputData() {
  return {
    value: this.value()
  , force: this.forced()
  };
};

// Named group of settings. (visible interface element)
//
// form (Form): See below for Form class.
// name (String): Title translation key.
// settings (Array): List of related settings.
//
function SettingCategory(form, name, settings) {
  this.name          = name;
  this.localizedName = N.runtime.t('admin.setting.category.' + name);

  this.settings = _.sortBy(settings, 'priority');
  this.priority = _(settings).pluck('priority').reduce(function (a, b) { return a + b; });
}

// Single known user group. Used either for displayed group and for groups in
// the "inherits" list.
//
function UserGroup(form, data) {
  data = data || {};

  var rawSettings;

  if (data.raw_settings) {
    rawSettings = data.raw_settings.usergroup || {};
  } else {
    rawSettings = {};
  }

  // Read-only slots.
  //
  this.objectId    = data._id || null;
  this.isProtected = data.is_protected || false;

  // Writable and savable slots.
  //
  this.name     = ko.observable(data.short_name || '').extend({ trackable: true });
  this.parentId = ko.observable(data.parent_group || null).extend({ trackable: true });

  // Computed values.
  //
  this.localizedName = ko.computed(function () {
    return this.name() ? N.runtime.t('users.usergroup.' + this.name()) : null;
  }, this);

  this.parentGroup = ko.computed({
    read:  function () { return form.groupsById[this.parentId()]; }
  , write: function (group) { this.parentId(group ? group.objectId : null); }
  , owner: this
  });

  // Related settings and categories lists.
  // See Setting and SettingCategory classes for details.
  //
  this.settings         = [];
  this.settingsByName   = {};
  this.categories       = [];
  this.categoriesByName = {};

  // Collect setting models.
  _.forEach(form.setting_schemas, function (schema, name) {
    var setting, overriden = _.has(rawSettings, name);

    setting = new Setting(form, name, schema, {
      group:     this
    , overriden: overriden
    , forced:    overriden ? rawSettings[name].force : false
    , value:     overriden ? rawSettings[name].value : schema['default']
    });

    this.settings.push(setting);
    this.settingsByName[name] = setting;
  }, this);

  this.settings = _.sortBy(this.settings, 'priority');

  // Collect category models.
  _(form.setting_schemas).pluck('category_key').unique().forEach(function (name) {
    var category = new SettingCategory(form, name, _.select(this.settings, { categoryKey: name }));

    this.categories.push(category);
    this.categoriesByName[name] = category;
  }, this);

  this.categories = _.sortBy(this.categories, 'priority');

  // Helpers.
  //
  this.isModified = ko.computed(function () {
    return this.name.isModified()     ||
           this.parentId.isModified() ||
           _(this.settings).invoke('isModified').any();
  }, this);
}

// Marks all trackable data slots and related settings as saved.
//
UserGroup.prototype.markSaved = function markSaved() {
  this.name.markSaved();
  this.parentId.markSaved();
  _.invoke(this.settings, 'markSaved');
};

// Returns data suitable for the server.
//
UserGroup.prototype.getOutputData = function getOutputData() {
  var result = {
    short_name:   this.name()
  , parent_group: this.parentId()
  , raw_settings: {}
  };

  // Add `_id` property only when `this` is a persistent (i.e. saved) group.
  if (this.objectId) {
    result._id = this.objectId;
  }

  _.forEach(this.settings, function (setting) {
    if (setting.overriden()) {
      result.raw_settings[setting.name] = setting.getOutputData();
    }
  });

  return result;
};

// Root view model of the page. It has two modes: 'create' and 'update'.
//
// page_data.setting_schemas (Object): N.config.setting_schemas.usergroup
// page_data.groups_data (Array): List of all existent user groups.
// page_data.current_group_id (String, Optional): ObjectID of a group for edit.
// If this identifier is provided, the form will use 'update' mode.
//
function Form(page_data) {
  this.setting_schemas = page_data.setting_schemas;

  this.groups     = [];
  this.groupsById = {};

  this.filter = ko.observable('');

  this.createMode   = !_.has(page_data, 'current_group_id');
  this.currentGroup = null;
  this.otherGroups  = [];

  if (this.createMode) {
    this.currentGroup = new UserGroup(this);
  }

  _.forEach(page_data.groups_data, function (data) {
    var group = new UserGroup(this, data);

    this.groups.push(group);
    this.groupsById[group.objectId] = group;

    if (!this.createMode && group.objectId === page_data.current_group_id) {
      this.currentGroup = group;
    } else {
      this.otherGroups.push(group);
    }
  }, this);
}

// Sends 'create' request for `currentGroup`.
//
Form.prototype.create = function create() {
  var self = this;

  N.io.rpc('admin.users.usergroups.create', this.currentGroup.getOutputData(), function (err) {
    if (err) {
      N.wire.emit('notify', {
        type: 'error'
      , message: N.runtime.t(N.io.BAD_REQUEST === err.code ?
                             'admin.users.usergroups.form.error.bad_request' :
                             'admin.users.usergroups.form.error.unknown')
      });
      return;
    }

    self.currentGroup.markSaved();

    N.wire.emit('notify', {
      type: 'info'
    , message: N.runtime.t('admin.users.usergroups.form.created')
    });

    // TODO: Replace this with the navigate.js when it will be ported for ACP.
    window.location = N.runtime.router.linkTo('admin.users.usergroups.show');
  });
};

// Sends 'update' request for `currentGroup`.
//
Form.prototype.update = function update() {
  var self = this;

  N.io.rpc('admin.users.usergroups.update', this.currentGroup.getOutputData(), function (err) {
    if (err) {
      N.wire.emit('notify', {
        type: 'error'
      , message: N.runtime.t(N.io.BAD_REQUEST === err.code ?
                             'admin.users.usergroups.form.error.bad_request' :
                             'admin.users.usergroups.form.error.unknown')
      });
      return;
    }

    self.currentGroup.markSaved();

    N.wire.emit('notify', {
      type: 'info'
    , message: N.runtime.t('admin.users.usergroups.form.updated')
    });
  });
};

// Sends save request to the server.
//
Form.prototype.submit = function submit() {
  if (this.createMode) {
    this.create();
  } else {
    this.update();
  }
};

module.exports = Form;
<|endoftext|>


<commit_before>// add/remove dynamic fields
var Carnival = {}
String.prototype.unescapeHtml = function () {
    var temp = document.createElement("div");
    temp.innerHTML = this;
    var result = temp.childNodes[0].nodeValue;
    temp.removeChild(temp.firstChild);
    return result;
}

Carnival.remoteFunction = function(url, successCallback, errorCallback, method, data){
  if(!data)
    data = {};
  $.ajax({
    url: url,
    type: method,
    data: data,
    success: function(data, status, jqXHR){
      Carnival.callFunc(successCallback, data);
    },
    error: function(jqXHR, status, error){
      Carnival.callFunc(errorCallback, data);
    }
  })
}

Carnival.callFunc = function(functionName, data){
  var func = window[functionName];
  if(func)
  {
    if(typeof func === 'function')
    {
      func(data);
    }
  }else{
    if(console && console.warn)
      console.warn('The funcion ' + functionName + ' was not implemented')
  }
  Carnival.reloadIndexPage();
}

Carnival.setIndexPageParam = function(name, value){
  var form = $('.carnival-index-form').find('form')
  form.find('input[name='+name+']').val(value);
}

Carnival.getIndexPageParam = function(name){
  var form = $('.carnival-index-form').find('form')
  return form.find('input[name='+name+']').val();
}

Carnival.removeAdvancedSearch = function(key){
  var values = Carnival.getIndexPageParam('advanced_search');
  if(!values)
    return;

  values = JSON.parse(values);

  var new_value = {};

  for(var prop in values){
    if(prop != key){
      new_value[prop] = values[prop]
    }
  }

  Carnival.setIndexPageParamAndReload('advanced_search', JSON.stringify(new_value));
}

Carnival.reloadIndexPage = function(){
  Carnival.setIndexPageParam('page', 1);
  var form = $('.carnival-index-form').find('form')
  form.submit();
}

Carnival.setIndexPageParamAndReload = function(name, value){
  Carnival.setIndexPageParam(name, value);
  Carnival.reloadIndexPage();
}

Carnival.sortColumn = function(column, direction){
  Carnival.setIndexPageParam('sort_column', column);
  Carnival.setIndexPageParam('sort_direction', direction);
  Carnival.reloadIndexPage();
}

Carnival.goToPage = function(page){
  Carnival.setIndexPageParam('page', page);
  var form = $('.carnival-index-form').find('form')
  form.submit();
}

Carnival.sortIndexList = function(elem){
  var selectedOption = $(elem).find('option:selected');
  var columnName = $(selectedOption).data('columnName');
  var sortDir = $(selectedOption).data('sortDir');
  Carnival.sortColumn(columnName, sortDir);
}

function removeFields(link) {
  $(link).prev("input[type=hidden]").val("1");
  $(link).closest(".fields").slideToggle("show");
}

function addFields(link, association, content) {
  var numItems = $('.fields').length
  var new_id = numItems
  var regexp = new RegExp("new_" + association, "g")
  $(link).parent().before(content.unescapeHtml().replace(regexp, new_id));
  formLoad();
  return false;
}

function openPopUp(url){
  $.colorbox({href:url, opacity:0.5, width:"90%"});
}

function markActive(){
  $('.dropdown_main_menu_sublevel a.actived').closest('.dropdown_main_menu_sublevel').show();
}

// page load functions

var pageLoad = function(){

  width = 0;

  $('.advanced-search-tag').each(function(){
    width += $(this).outerWidth();
    if($('.advanced-search-tags').width() < width){
      $('.advanced-search-tags').addClass('explode');
    }
  })

  $('ul.menu').clone().appendTo('div.menu.short');

  $('.dropdown_main_menu_sublevel').hide(0);

  $('.menu.full .sublevel').click(function(){
    $(this).next().slideToggle(200)
    return false
  })

  $('.menu.short .sublevel').parent().mouseover(function(){
    $(this).children().next().fadeIn(0)
    return false
  })

  $('.menu.short .sublevel').parent().mouseleave(function(){
    $(this).children().next().fadeOut(0)
    return false
  })

  $(".carnival-select").select2({width: '100%'});
  $(".popup").click(function(e){
    e.preventDefault()
    var url = $(this).attr('href')
    abrirPopUp(url)
  })

  markActive()

  $('div.menu.short').show(0);
  $('div.menu.short .dropdown_main_menu_sublevel').hide();
  $('#content').toggleClass('menu-opened');
  $('.short ul.dropdown_main_menu li ul li a.actived').parent().parent().parent().addClass('active');
  $('.full ul.dropdown_main_menu li ul li a.actived').parent().parent().parent().addClass('active');

  if($('ul.menu li.active a').html())
    $('#header').append("
"+$('ul.menu li.active a').html()+" » "+$('ul.menu a.actived').html()+"
")

  $('.full ul.dropdown_main_menu li:has(ul)').each(function( index ) {
    $('.short ul.dropdown_main_menu li:has(ul) > ul').eq(index).prepend('
'+$('.full ul.dropdown_main_menu li:has(ul) > a').eq(index).html()+'
')
  });

  var $lefty = $('div.menu.full');
  $lefty.animate({
    marginLeft: '-20%'
  }, 100);

  $('.minify').on("click", function(){
    var $lefty = $('div.menu.full');
    $lefty.animate({
      marginLeft: parseInt($lefty.css('margin-left'),10) == 0 ?
       -$lefty.outerWidth()-2:
        0
    }, 100);
    setTimeout("$('div.menu.short').fadeToggle(100)", 0)
    setTimeout("$('#content').toggleClass('menu-opened')", 0)
  })
};

// form load functions

function setupDateFields(){
  var dateOptions = {
    format: 'Y/m/d',
    mask: true,
    timepicker: false
  };
  var dateTimeOptions = $.extend({}, dateOptions, { timepicker: true, format: 'Y/m/d H:i'})

  $(".datepicker").datetimepicker(dateOptions);
  $(".datetimepicker").datetimepicker(dateTimeOptions);
}

var formLoad = function(){
  setupDateFields();
  $('select').select2({width: '100%'});
  $('input.previewable').change(function() {
    var that = $( this );
    var reader = new FileReader();
    var img = $(this).siblings('img.previewable');

    reader.onload = function(e) {
      var val = e.target.result;
      img.attr('src', val);
    }

    if (this.files && this.files[0]) {
      reader.readAsDataURL(this.files[0]);
    } else {
      img.attr('src', '');
    }
  });
  $('.carnival-select').select2({width: '100%'});
  selectRemote();
}

$(document).ready(function(){
  pageLoad();
  formLoad();

  $('a').each(function(){this_=$(this);if(this_.hasClass() == false){this_.addClass('link')}})

});
<commit_msg>Dont automatically reload page on remoteFunction Callback<commit_after>// add/remove dynamic fields
var Carnival = {}
String.prototype.unescapeHtml = function () {
    var temp = document.createElement("div");
    temp.innerHTML = this;
    var result = temp.childNodes[0].nodeValue;
    temp.removeChild(temp.firstChild);
    return result;
}

Carnival.remoteFunction = function(url, successCallback, errorCallback, method, data){
  if(!data)
    data = {};
  $.ajax({
    url: url,
    type: method,
    data: data,
    success: function(data, status, jqXHR){
      Carnival.callFunc(successCallback, data);
    },
    error: function(jqXHR, status, error){
      Carnival.callFunc(errorCallback, data);
    }
  })
}

Carnival.callFunc = function(functionName, data){
  var func = window[functionName];
  if(func)
  {
    if(typeof func === 'function')
    {
      func(data);
    }
  }else{
    if(console && console.warn)
      console.warn('The funcion ' + functionName + ' was not implemented')
  }
}

Carnival.setIndexPageParam = function(name, value){
  var form = $('.carnival-index-form').find('form')
  form.find('input[name='+name+']').val(value);
}

Carnival.getIndexPageParam = function(name){
  var form = $('.carnival-index-form').find('form')
  return form.find('input[name='+name+']').val();
}

Carnival.removeAdvancedSearch = function(key){
  var values = Carnival.getIndexPageParam('advanced_search');
  if(!values)
    return;

  values = JSON.parse(values);

  var new_value = {};

  for(var prop in values){
    if(prop != key){
      new_value[prop] = values[prop]
    }
  }

  Carnival.setIndexPageParamAndReload('advanced_search', JSON.stringify(new_value));
}

Carnival.reloadIndexPage = function(){
  Carnival.setIndexPageParam('page', 1);
  var form = $('.carnival-index-form').find('form')
  form.submit();
}

Carnival.setIndexPageParamAndReload = function(name, value){
  Carnival.setIndexPageParam(name, value);
  Carnival.reloadIndexPage();
}

Carnival.sortColumn = function(column, direction){
  Carnival.setIndexPageParam('sort_column', column);
  Carnival.setIndexPageParam('sort_direction', direction);
  Carnival.reloadIndexPage();
}

Carnival.goToPage = function(page){
  Carnival.setIndexPageParam('page', page);
  var form = $('.carnival-index-form').find('form')
  form.submit();
}

Carnival.sortIndexList = function(elem){
  var selectedOption = $(elem).find('option:selected');
  var columnName = $(selectedOption).data('columnName');
  var sortDir = $(selectedOption).data('sortDir');
  Carnival.sortColumn(columnName, sortDir);
}

function removeFields(link) {
  $(link).prev("input[type=hidden]").val("1");
  $(link).closest(".fields").slideToggle("show");
}

function addFields(link, association, content) {
  var numItems = $('.fields').length
  var new_id = numItems
  var regexp = new RegExp("new_" + association, "g")
  $(link).parent().before(content.unescapeHtml().replace(regexp, new_id));
  formLoad();
  return false;
}

function openPopUp(url){
  $.colorbox({href:url, opacity:0.5, width:"90%"});
}

function markActive(){
  $('.dropdown_main_menu_sublevel a.actived').closest('.dropdown_main_menu_sublevel').show();
}

// page load functions

var pageLoad = function(){

  width = 0;

  $('.advanced-search-tag').each(function(){
    width += $(this).outerWidth();
    if($('.advanced-search-tags').width() < width){
      $('.advanced-search-tags').addClass('explode');
    }
  })

  $('ul.menu').clone().appendTo('div.menu.short');

  $('.dropdown_main_menu_sublevel').hide(0);

  $('.menu.full .sublevel').click(function(){
    $(this).next().slideToggle(200)
    return false
  })

  $('.menu.short .sublevel').parent().mouseover(function(){
    $(this).children().next().fadeIn(0)
    return false
  })

  $('.menu.short .sublevel').parent().mouseleave(function(){
    $(this).children().next().fadeOut(0)
    return false
  })

  $(".carnival-select").select2({width: '100%'});
  $(".popup").click(function(e){
    e.preventDefault()
    var url = $(this).attr('href')
    abrirPopUp(url)
  })

  markActive()

  $('div.menu.short').show(0);
  $('div.menu.short .dropdown_main_menu_sublevel').hide();
  $('#content').toggleClass('menu-opened');
  $('.short ul.dropdown_main_menu li ul li a.actived').parent().parent().parent().addClass('active');
  $('.full ul.dropdown_main_menu li ul li a.actived').parent().parent().parent().addClass('active');

  if($('ul.menu li.active a').html())
    $('#header').append("
"+$('ul.menu li.active a').html()+" » "+$('ul.menu a.actived').html()+"
")

  $('.full ul.dropdown_main_menu li:has(ul)').each(function( index ) {
    $('.short ul.dropdown_main_menu li:has(ul) > ul').eq(index).prepend('
'+$('.full ul.dropdown_main_menu li:has(ul) > a').eq(index).html()+'
')
  });

  var $lefty = $('div.menu.full');
  $lefty.animate({
    marginLeft: '-20%'
  }, 100);

  $('.minify').on("click", function(){
    var $lefty = $('div.menu.full');
    $lefty.animate({
      marginLeft: parseInt($lefty.css('margin-left'),10) == 0 ?
       -$lefty.outerWidth()-2:
        0
    }, 100);
    setTimeout("$('div.menu.short').fadeToggle(100)", 0)
    setTimeout("$('#content').toggleClass('menu-opened')", 0)
  })
};

// form load functions

function setupDateFields(){
  var dateOptions = {
    format: 'Y/m/d',
    mask: true,
    timepicker: false
  };
  var dateTimeOptions = $.extend({}, dateOptions, { timepicker: true, format: 'Y/m/d H:i'})

  $(".datepicker").datetimepicker(dateOptions);
  $(".datetimepicker").datetimepicker(dateTimeOptions);
}

var formLoad = function(){
  setupDateFields();
  $('select').select2({width: '100%'});
  $('input.previewable').change(function() {
    var that = $( this );
    var reader = new FileReader();
    var img = $(this).siblings('img.previewable');

    reader.onload = function(e) {
      var val = e.target.result;
      img.attr('src', val);
    }

    if (this.files && this.files[0]) {
      reader.readAsDataURL(this.files[0]);
    } else {
      img.attr('src', '');
    }
  });
  $('.carnival-select').select2({width: '100%'});
  selectRemote();
}

$(document).ready(function(){
  pageLoad();
  formLoad();

  $('a').each(function(){this_=$(this);if(this_.hasClass() == false){this_.addClass('link')}})

});
<|endoftext|>


<commit_before>"use strict";

/*global module, require*/

var helpers = require("../helpers.js"),
    noop = helpers.noop,
    jsonData = require("./json.js"),
    serialize = jsonData.serialize,
    serializeNode = jsonData.serializeNode,
    serializeEdge = jsonData.serializeEdge;

/*
 Watches the node graph and layout. Makes operations out of changes to them.

 Watched the context and alters the node graph and layout based on the operations it sees.

 TODO subscribe to events.
 TODO examine layout changes.
 */
module.exports = function(getContext, onContextChanged, getNodeCollection, getLayout, onNodeCollectionChanged) {
    var hook = function(o, makePath, serialize, prop) {
	if (o[prop]) {
	    var wrapped = o[prop];
	    o[prop] = function() {
		var args = arguments;

		if (arguments.length) {
		    var oldVal = wrapped.apply(o),
			returnVal = wrapped.apply(o, arguments),
			newVal = wrapped.apply(o);

		    getContext().submitOp(
			[{
			    p: makePath().concat([prop]),
			    od: oldVal,
			    oi: newVal
			}],
			noop
		    );

		    return returnVal;
		} else {
		    return wrapped();
		}
	    };
	}
    };

    var hookNode = function(node) {
	/*
	 I've chosen not to hook up the chooseType function in here. This means that a node changes identity when it changes type, which is probably ok since it has no interesting properties on it.
	 */
	var makePath = function() {
	    return ["nodes", node.id];
	};

	["name", "localEvidence", "dependence", "settled", "support"]
	    .forEach(function(p) {
		hook(node, makePath, serializeNode, p);
	    });

	// TODO description should use the text interface
    };

    var hookEdge = function(edge) {
	var makePath = function() {
	    return ["nodes", edge.parent().id, "edges", edge.node().id];
	};

	["necessity", "sufficiency"]
	    .forEach(function(p) {
		hook(edge, makePath, serializeEdge, p);
	    });
    };

    onNodeCollectionChanged(function() {
	var coll = getNodeCollection(),
	    layout = getLayout();

	getContext().submitOp(
	    [{
		p: [],
		oi: serialize(coll, layout)
	    }],
	    noop
	);

	coll.onNodeCreate(function(node) {
	    hookNode(node);
	    getContext().submitOp(
		[{
		    p: ["nodes", node.id],
		    oi: serializeNode(node)
		}],
		noop
	    );
	});

	coll.onNodeDelete(function(node) {
	    getContext().submitOp(
		[{
		    p: ["nodes", node.id],
		    od: node
		}],
		noop
	    );
	});

	coll.onEdgeCreate(function(edge) {
	    getContext().submitOp(
		[{
		    p: ["nodes", edge.parent().id, "edges", edge.node().id],
		    oi: serializeEdge(edge)
		}],
		noop
	    );
	    hookEdge(edge);
	});

	coll.onEdgeDelete(function(edge) {
	    getContext().submitOp(
		[{
		    p: ["nodes", edge.parent().id, "edges", edge.node().id],
		    od: serializeEdge(edge)
		}],
		noop
	    );
	});
    });
};
<commit_msg>Hooked up all the existing nodes and edges in a collection.<commit_after>"use strict";

/*global module, require*/

var helpers = require("../helpers.js"),
    noop = helpers.noop,
    jsonData = require("./json.js"),
    serialize = jsonData.serialize,
    serializeNode = jsonData.serializeNode,
    serializeEdge = jsonData.serializeEdge;

/*
 Watches the node graph and layout. Makes operations out of changes to them.

 Watched the context and alters the node graph and layout based on the operations it sees.

 TODO subscribe to events.
 TODO examine layout changes.
 */
module.exports = function(getContext, onContextChanged, getNodeCollection, getLayout, onNodeCollectionChanged) {
    var hook = function(o, makePath, serialize, prop) {
	if (o[prop]) {
	    var wrapped = o[prop];
	    o[prop] = function() {
		var args = arguments;

		if (arguments.length) {
		    var oldVal = wrapped.apply(o),
			returnVal = wrapped.apply(o, arguments),
			newVal = wrapped.apply(o);

		    getContext().submitOp(
			[{
			    p: makePath().concat([prop]),
			    od: oldVal,
			    oi: newVal
			}],
			noop
		    );

		    return returnVal;
		} else {
		    return wrapped();
		}
	    };
	}
    };

    var hookNode = function(node) {
	/*
	 I've chosen not to hook up the chooseType function in here. This means that a node changes identity when it changes type, which is probably ok since it has no interesting properties on it.
	 */
	var makePath = function() {
	    return ["nodes", node.id];
	};

	["name", "localEvidence", "dependence", "settled", "support"]
	    .forEach(function(p) {
		hook(node, makePath, serializeNode, p);
	    });

	// TODO description should use the text interface
    };

    var hookEdge = function(edge) {
	var makePath = function() {
	    return ["nodes", edge.parent().id, "edges", edge.node().id];
	};

	["necessity", "sufficiency"]
	    .forEach(function(p) {
		hook(edge, makePath, serializeEdge, p);
	    });
    };

    onNodeCollectionChanged(function() {
	var coll = getNodeCollection(),
	    layout = getLayout();

	getContext().submitOp(
	    [{
		p: [],
		oi: serialize(coll, layout)
	    }],
	    noop
	);

	coll.all().forEach(function(n) {
	    hookNode(n);
	    n.edges().forEach(function(e) {
		hookEdge(e);
	    });
	});

	coll.onNodeCreate(function(node) {
	    hookNode(node);
	    getContext().submitOp(
		[{
		    p: ["nodes", node.id],
		    oi: serializeNode(node)
		}],
		noop
	    );
	});

	coll.onNodeDelete(function(node) {
	    getContext().submitOp(
		[{
		    p: ["nodes", node.id],
		    od: node
		}],
		noop
	    );
	});

	coll.onEdgeCreate(function(edge) {
	    getContext().submitOp(
		[{
		    p: ["nodes", edge.parent().id, "edges", edge.node().id],
		    oi: serializeEdge(edge)
		}],
		noop
	    );
	    hookEdge(edge);
	});

	coll.onEdgeDelete(function(edge) {
	    getContext().submitOp(
		[{
		    p: ["nodes", edge.parent().id, "edges", edge.node().id],
		    od: serializeEdge(edge)
		}],
		noop
	    );
	});
    });
};
<|endoftext|>


<commit_before>/* eslint no-undef: "off" */
angular
  .module('adminApp')
  .factory('AuthFactory', function ($http, $q, $rootScope, $location, StorageFactory, jwtHelper, cfg) {
    function login (credentials) {
      console.log('Login Factory')
      return $http.post(cfg.urlAuth, credentials)
        .then(response => response.data.token)
        .then(token => {
          console.log('token')
          console.log(token)
          StorageFactory.saveToken(token)
          return token
        })
    }

    // function register (credentials) {
    //   const url = '/api/register'
    //   return $http.post(url, credentials)
    //     .then($location.path('/login'))
    // }

    function logout () {
      delete $rootScope.loggedUser
      StorageFactory.removeToken()
      $rootScope.$broadcast('eventLogin', false)
    }

    function isLoggedIn () {
      const token = StorageFactory.readToken()
      if (!token) return false
      const tokenPayload = jwtHelper.decodeToken(token)// eslint-disable-line no-unused-vars
      return !(jwtHelper.isTokenExpired(token))
    }

    function setCredentials (token) {
      var tokenPayload = jwtHelper.decodeToken(token)
      $rootScope.loggedUser = tokenPayload
      $rootScope.$broadcast('eventLogin', true)
    }

    return { login, logout, isLoggedIn, setCredentials }
  })
<commit_msg>Removed console.log from auth.factory<commit_after>/* eslint no-undef: "off" */
angular
  .module('adminApp')
  .factory('AuthFactory', function ($http, $q, $rootScope, $location, StorageFactory, jwtHelper, cfg) {
    function login (credentials) {
      console.log('Login Factory')
      return $http.post(cfg.urlAuth, credentials)
        .then(response => response.data.token)
        .then(token => {
          StorageFactory.saveToken(token)
          return token
        })
    }

    // function register (credentials) {
    //   const url = '/api/register'
    //   return $http.post(url, credentials)
    //     .then($location.path('/login'))
    // }

    function logout () {
      delete $rootScope.loggedUser
      StorageFactory.removeToken()
      $rootScope.$broadcast('eventLogin', false)
    }

    function isLoggedIn () {
      const token = StorageFactory.readToken()
      if (!token) return false
      const tokenPayload = jwtHelper.decodeToken(token)// eslint-disable-line no-unused-vars
      return !(jwtHelper.isTokenExpired(token))
    }

    function setCredentials (token) {
      var tokenPayload = jwtHelper.decodeToken(token)
      $rootScope.loggedUser = tokenPayload
      $rootScope.$broadcast('eventLogin', true)
    }

    return { login, logout, isLoggedIn, setCredentials }
  })
<|endoftext|>


<commit_before>ds.menu = (function(keyboard, openClass, closedClass){
    var scope = {};

    this.addEventListener('blur', function (event) {
        event.target.dispatchEvent(new Event('focusout', {
            bubbles: true,
            cancelable: true
        }));
    }, true);

    var prefix = ds.prefix + '-menu';
    var selectors = {
        menuDropdownClass: prefix,
        triggerClass: prefix + '-trigger',
        subMenuClass: prefix + '-items',
        menuItemClass: prefix + '-item',
        closedClass: closedClass,
        openClass: openClass
    };

    scope.closeAllSubMenus = function(){
        var subMenus = document.querySelectorAll('.' + selectors.subMenuClass);
        for(var i=0; i < subMenus.length; i++){
            scope.closeSubMenu(subMenus[i]);
        }
    };

    scope.respondToKeyboard = function(e) {
        if(keyboard.tab) {
            scope.closeAllSubMenus();
            if(e.currentTarget.parentNode.classList.contains(selectors.subMenuClass)){
                scope.openSubMenu(e.currentTarget.parentNode);
            } else if (e.currentTarget.parentNode.classList.contains(selectors.menuDropdownClass)){
                var parentDropdown = e.currentTarget.parentNode;
                var subMenu = parentDropdown.querySelector('.' + selectors.subMenuClass);
                scope.openSubMenu(subMenu);
            }
        }
    };

    scope.closeSubMenu = function(subMenu){
        subMenu.classList.remove(selectors.openClass);
        subMenu.classList.add(selectors.closedClass);
        subMenu.setAttribute('aria-hidden', 'true');
        subMenu.parentNode.classList.remove(selectors.openClass);
        subMenu.parentNode.classList.add(selectors.closedClass);
    };

    scope.openSubMenu = function(subMenu){
        subMenu.classList.remove(selectors.closedClass);
        subMenu.classList.add(selectors.openClass);
        subMenu.removeAttribute('aria-hidden');
        subMenu.parentNode.classList.remove(selectors.closedClass);
        subMenu.parentNode.classList.add(selectors.openClass);
    };

    scope.toggleSubMenu = function(e) {
        var subMenuID = '#' + e.currentTarget.getAttribute('aria-controls');
        var subMenu = document.querySelector(subMenuID);
        subMenu.classList.contains(selectors.openClass) ? scope.closeSubMenu(subMenu) : scope.openSubMenu(subMenu);
    };

    scope.setupEventHandlersOn = function(trigger, subMenu){
        trigger.onclick = function(e){
            scope.toggleSubMenu(e);
            e.preventDefault();
        };
        trigger.onkeyup = subMenu.onkeyup = function(e){ scope.respondToKeyboard(e); };
    };

    scope.setupLoseFocusHandlersOn = function(menu, subMenu){
        //menu.addEventListener('DOMFocusIn', function(e){ scope.openSubMenu(subMenu); });
        //menu.addEventListener('DOMFocusOut', function(e){ scope.closeSubMenu(subMenu); });

        // IE fallbacks
        subMenu.addEventListener('focusin', function(e){ scope.openSubMenu(subMenu); });
        menu.addEventListener('focusout', function(e){ scope.closeSubMenu(subMenu); });
    };

    scope.setAccessibilityAttributesOn = function(trigger, subMenu, subMenuItems, dropDownSequenceNumber){
        // Show that there is a dropdown to non-visual devices
        trigger.setAttribute('aria-haspopup', 'true');
        subMenu.setAttribute('role', 'menu'); // Marks it as a sub-menu

        // Show which dropdown the trigger controls
        subMenu.setAttribute('id', 'ds-sub-menu-' + dropDownSequenceNumber);
        trigger.setAttribute('aria-controls', 'ds-sub-menu-' + dropDownSequenceNumber);

        // Set trigger to be the label for the dropdown
        trigger.setAttribute('id', 'ds-menu-trigger-' + dropDownSequenceNumber);
        subMenu.setAttribute('aria-labelledby', 'ds-menu-trigger-' + dropDownSequenceNumber);

        for (var j=0; j < subMenuItems.length; j++) {
            subMenuItems[j].setAttribute('role', 'menuitem');
        }
    };

    scope.setup = function(){
        var dropdowns = document.querySelectorAll('.' + selectors.menuDropdownClass);
        for(var i=0; i < dropdowns.length; i++){
            var menu = dropdowns[i];
            menu.setAttribute('tabIndex', '-1');
            var trigger = menu.querySelector('.' + selectors.triggerClass);
            var subMenu = menu.querySelector('.' + selectors.subMenuClass);
            var subMenuItems = subMenu.querySelectorAll('.' + selectors.menuItemClass);

            scope.closeAllSubMenus();
            scope.setAccessibilityAttributesOn(trigger, subMenu, subMenuItems, i);
            scope.setupEventHandlersOn(trigger, subMenu);
            scope.setupLoseFocusHandlersOn(menu, subMenu);
        }
    };

    return scope;
})(ds.keyboard, ds.prefix + '-open', ds.prefix + '-closed');

window.addEventListener("load", function () {
    ds.menu.setup();
});
<commit_msg>C1844: removed the polyfil<commit_after>ds.menu = (function(keyboard, openClass, closedClass){
    var scope = {};

    var prefix = ds.prefix + '-menu';
    var selectors = {
        menuDropdownClass: prefix,
        triggerClass: prefix + '-trigger',
        subMenuClass: prefix + '-items',
        menuItemClass: prefix + '-item',
        closedClass: closedClass,
        openClass: openClass
    };

    scope.closeAllSubMenus = function(){
        var subMenus = document.querySelectorAll('.' + selectors.subMenuClass);
        for(var i=0; i < subMenus.length; i++){
            scope.closeSubMenu(subMenus[i]);
        }
    };

    scope.respondToKeyboard = function(e) {
        if(keyboard.tab) {
            scope.closeAllSubMenus();
            if(e.currentTarget.parentNode.classList.contains(selectors.subMenuClass)){
                scope.openSubMenu(e.currentTarget.parentNode);
            } else if (e.currentTarget.parentNode.classList.contains(selectors.menuDropdownClass)){
                var parentDropdown = e.currentTarget.parentNode;
                var subMenu = parentDropdown.querySelector('.' + selectors.subMenuClass);
                scope.openSubMenu(subMenu);
            }
        }
    };

    scope.closeSubMenu = function(subMenu){
        subMenu.classList.remove(selectors.openClass);
        subMenu.classList.add(selectors.closedClass);
        subMenu.setAttribute('aria-hidden', 'true');
        subMenu.parentNode.classList.remove(selectors.openClass);
        subMenu.parentNode.classList.add(selectors.closedClass);
    };

    scope.openSubMenu = function(subMenu){
        subMenu.classList.remove(selectors.closedClass);
        subMenu.classList.add(selectors.openClass);
        subMenu.removeAttribute('aria-hidden');
        subMenu.parentNode.classList.remove(selectors.closedClass);
        subMenu.parentNode.classList.add(selectors.openClass);
    };

    scope.toggleSubMenu = function(e) {
        var subMenuID = '#' + e.currentTarget.getAttribute('aria-controls');
        var subMenu = document.querySelector(subMenuID);
        subMenu.classList.contains(selectors.openClass) ? scope.closeSubMenu(subMenu) : scope.openSubMenu(subMenu);
    };

    scope.setupEventHandlersOn = function(trigger, subMenu){
        trigger.onclick = function(e){
            scope.toggleSubMenu(e);
            e.preventDefault();
        };
        trigger.onkeyup = subMenu.onkeyup = function(e){ scope.respondToKeyboard(e); };
    };

    scope.setupLoseFocusHandlersOn = function(menu, subMenu){
        //menu.addEventListener('DOMFocusIn', function(e){ scope.openSubMenu(subMenu); });
        //menu.addEventListener('DOMFocusOut', function(e){ scope.closeSubMenu(subMenu); });

        // IE fallbacks
        subMenu.addEventListener('focusin', function(e){ scope.openSubMenu(subMenu); });
        menu.addEventListener('focusout', function(e){ scope.closeSubMenu(subMenu); });
    };

    scope.setAccessibilityAttributesOn = function(trigger, subMenu, subMenuItems, dropDownSequenceNumber){
        // Show that there is a dropdown to non-visual devices
        trigger.setAttribute('aria-haspopup', 'true');
        subMenu.setAttribute('role', 'menu'); // Marks it as a sub-menu

        // Show which dropdown the trigger controls
        subMenu.setAttribute('id', 'ds-sub-menu-' + dropDownSequenceNumber);
        trigger.setAttribute('aria-controls', 'ds-sub-menu-' + dropDownSequenceNumber);

        // Set trigger to be the label for the dropdown
        trigger.setAttribute('id', 'ds-menu-trigger-' + dropDownSequenceNumber);
        subMenu.setAttribute('aria-labelledby', 'ds-menu-trigger-' + dropDownSequenceNumber);

        for (var j=0; j < subMenuItems.length; j++) {
            subMenuItems[j].setAttribute('role', 'menuitem');
        }
    };

    scope.setup = function(){
        var dropdowns = document.querySelectorAll('.' + selectors.menuDropdownClass);
        for(var i=0; i < dropdowns.length; i++){
            var menu = dropdowns[i];
            menu.setAttribute('tabIndex', '-1');
            var trigger = menu.querySelector('.' + selectors.triggerClass);
            var subMenu = menu.querySelector('.' + selectors.subMenuClass);
            var subMenuItems = subMenu.querySelectorAll('.' + selectors.menuItemClass);

            scope.closeAllSubMenus();
            scope.setAccessibilityAttributesOn(trigger, subMenu, subMenuItems, i);
            scope.setupEventHandlersOn(trigger, subMenu);
            scope.setupLoseFocusHandlersOn(menu, subMenu);
        }
    };

    return scope;
})(ds.keyboard, ds.prefix + '-open', ds.prefix + '-closed');

window.addEventListener("load", function () {
    ds.menu.setup();
});
<|endoftext|>


<commit_before>// config
var show = 'drinkTimerShow';
var hide = 'drinkTimerHide';
// var timeoutMultiplier = 1000;
// var hideTimeoutMultiplier = 2000;
// chrome.storage.local.clear();
var timeoutMultiplier = 60*60*1000;
var hideTimeoutMultiplier = 60*1000;
var timeout = timeoutMultiplier*1;
var hideTimeout = hideTimeoutMultiplier*1;
var intervalTimeout = 1000;
var counterInterval;
var quotes = [
  "In wine there is wisdom, in beer there is freedom, in water there is bacteria.",
  "It seems difficult to drink 8 glasses of water a day but easy to drink 8 mugs of beer in 2 hours",
  "Water solves all your problems... Need to loose weight, drink water. Need to clear you mind, drink water. Tired of someone, drown him",
  "Pssst... Time to drink some water",
  "Millions have lived with love. Not one has lived without water",
  "Suprise your liver today.. Drink some water",
  "Drink plenty of water. Dehydration can get ugly",
  "Your body is more around 60% water. Be more than half full"
];
var buttonQuotes = [
  "I promise, I drank water",
  "Pinky swear, I drank water",
  "I know, just go now"
];

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

function buildOverlay() {

  var overlay = document.createElement('div');
  overlay.id = 'water';
  overlay.style = 'display: none';

  var dialog = document.createElement('div');
  dialog.classList = 'water-dialog-box';
  dialog.style = 'background-image:url('+ chrome.extension.getURL('water.jpg')+')';

  var heading = document.createElement('div');
  var quoteIndex = getRandomInt(0, (quotes.length - 1));
  heading.innerHTML = quotes[quoteIndex];
  heading.id ='waterText';

  var button = document.createElement('button');
  button.id = 'okay';
  button.innerHTML = 'I promise, I drank water!';

  var timer = document.createElement('div');
  timer.id = 'timer';

  dialog.appendChild(heading);

  overlay.appendChild(dialog);
  overlay.appendChild(button);

  document.querySelector('body').appendChild(overlay);
}

function showOverlay() {
  document.getElementById('waterText').innerHTML = quotes[getRandomInt(0, (quotes.length - 1))];
  document.getElementById('water').style.display = 'flex';
}

function hideOverlay() {
  document.getElementById('water').style.display = 'none';
}

function zeroPad(val) {
  val = Number(val);
  return (val>9 ? val : '0'+val).toString();
}

function hideButton(time) {
  var temptime = (new Date(time)).getTime();
  counterInterval = setInterval(function() {
    var now = new Date();
    var timer = temptime-now;
    if (timer < 0) {
      clearInterval(counterInterval);
      return;
    }
    var timerArr = (timer/1000).toString().split('.');
    document.getElementById('okay').innerHTML = zeroPad(timerArr[0])+':'+zeroPad(timerArr[1]);
  }, 10);
}

function showButton(callback) {
  clearInterval(counterInterval);
  if (!overlayShown) {
    callback();
  }

  function handler(e) {
    hideOverlay();
    callback();
  }
  var button = document.getElementById('okay');
  button.innerHTML = buttonQuotes[getRandomInt(0, buttonQuotes.length-1)];
  button.removeEventListener('click', handler);
  button.addEventListener('click', handler);
}

function setTime()  {
  var now = Date.now();
  intervalTimeout = timeout;

  var storeShow = {};
  storeShow[show] = now + timeout;
  chrome.storage.local.set(storeShow);

  var storeHide = {};
  storeHide[hide] = now + timeout + hideTimeout
  chrome.storage.local.set(storeHide);

  init();
}

function setSettings(callback) {
  chrome.storage.local.get('settings', function(settingsObj) {
    if (settingsObj.hasOwnProperty('settings')) {
      timeout = Number(settingsObj.settings.triggerInterval) * timeoutMultiplier;
      hideTimeout = Number(settingsObj.settings.blockDuration) * hideTimeoutMultiplier;
      callback();
    } else {
      var settings = {
        triggerInterval: 1,
        blockDuration: 1
      }
      chrome.storage.local.set({'settings': settings}, callback);
    }
  });
}
var loop;

var overlayShown = false;

function init() {
  clearTimeout(loop);

  setSettings(function() {

    loop = setTimeout(function() {

      console.log('i am running');

      chrome.storage.local.get(show, function(showObj) {

        if (showObj.hasOwnProperty(show)) {
          var now = Date.now();

          if (showObj[show] < now) {
            chrome.storage.local.get(hide, function(hideObj) {

              if (hideObj[hide] > now) {
                if (!overlayShown) {
                  hideButton(hideObj[hide]);
                  showOverlay();
                  overlayShown = true;
                }
                intervalTimeout = 1000;
                return init();
              } else {
                return showButton(function() {
                  overlayShown = false;
                  setTime();
                });
              }

            })
          } else {
            intervalTimeout = showObj[show] - now;
            if (overlayShown) {
              showButton(function() {
                overlayShown = false;
                return init();
              });
            }
          }
        } else {
          return setTime();
        }

      });

    }, intervalTimeout);

  });

}

buildOverlay();
init();
<commit_msg>temporary commit, fix later<commit_after>// config
var show = 'drinkTimerShow';
var hide = 'drinkTimerHide';
// var timeoutMultiplier = 1000;
// var hideTimeoutMultiplier = 5000;
// chrome.storage.local.clear();
var timeoutMultiplier = 60*60*1000;
var hideTimeoutMultiplier = 60*1000;
var timeout = timeoutMultiplier*1;
var hideTimeout = hideTimeoutMultiplier*1;
var intervalTimeout = 1000;
var counterInterval;
var quotes = [
  "In wine there is wisdom, in beer there is freedom, in water there is bacteria.",
  "It seems difficult to drink 8 glasses of water a day but easy to drink 8 mugs of beer in 2 hours",
  "Water solves all your problems... Need to loose weight, drink water. Need to clear you mind, drink water. Tired of someone, drown him",
  "Pssst... Time to drink some water",
  "Millions have lived with love. Not one has lived without water",
  "Suprise your liver today.. Drink some water",
  "Drink plenty of water. Dehydration can get ugly",
  "Your body is more around 60% water. Be more than half full"
];
var buttonQuotes = [
  "I promise, I drank water",
  "Pinky swear, I drank water",
  "I know, just go now"
];

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

function buildOverlay() {

  var overlay = document.createElement('div');
  overlay.id = 'water';
  overlay.style = 'display: none';

  var dialog = document.createElement('div');
  dialog.classList = 'water-dialog-box';
  dialog.style = 'background-image:url('+ chrome.extension.getURL('water.jpg')+')';

  var heading = document.createElement('div');
  var quoteIndex = getRandomInt(0, (quotes.length - 1));
  heading.innerHTML = quotes[quoteIndex];
  heading.id ='waterText';

  var button = document.createElement('button');
  button.id = 'okay';
  button.innerHTML = 'I promise, I drank water!';

  var timer = document.createElement('div');
  timer.id = 'timer';

  dialog.appendChild(heading);

  overlay.appendChild(dialog);
  overlay.appendChild(button);

  document.querySelector('body').appendChild(overlay);
}

function showOverlay() {
  document.getElementById('waterText').innerHTML = quotes[getRandomInt(0, (quotes.length - 1))];
  document.getElementById('water').style.display = 'flex';
}

function hideOverlay() {
  document.getElementById('water').style.display = 'none';
}

function zeroPad(val) {
  val = Number(val);
  return (val>9 ? val : '0'+val).toString();
}

function hideButton(time) {
  var temptime = (new Date(time)).getTime();
  counterInterval = setInterval(function() {
    var now = new Date();
    var timer = temptime-now;
    if (timer < 0) {
      clearInterval(counterInterval);
      return;
    }
    timer = parseInt(timer/1000);
    var minutes = parseInt(timer/60);
    var seconds = parseInt(timer%60);
    document.getElementById('okay').innerHTML = zeroPad(minutes)+':'+zeroPad(seconds);
  }, 10);
}

function showButton(callback) {
  clearInterval(counterInterval);
  if (!overlayShown) {
    callback();
  }

  function handler(e) {
    hideOverlay();
    callback();
  }
  var button = document.getElementById('okay');
  button.innerHTML = buttonQuotes[getRandomInt(0, buttonQuotes.length-1)];
  button.removeEventListener('click', handler);
  button.addEventListener('click', handler);
}

function setTime()  {
  var now = Date.now();
  intervalTimeout = Math.min(timeout, 1000);

  var storeShow = {};
  storeShow[show] = now + timeout;
  chrome.storage.local.set(storeShow);

  var storeHide = {};
  storeHide[hide] = now + timeout + hideTimeout
  chrome.storage.local.set(storeHide);

  init();
}

function setSettings(callback) {
  chrome.storage.local.get('settings', function(settingsObj) {
    if (settingsObj.hasOwnProperty('settings')) {
      timeout = Number(settingsObj.settings.triggerInterval) * timeoutMultiplier;
      hideTimeout = Number(settingsObj.settings.blockDuration) * hideTimeoutMultiplier;
      callback();
    } else {
      var settings = {
        triggerInterval: 1,
        blockDuration: 1
      }
      chrome.storage.local.set({'settings': settings}, callback);
    }
  });
}
var loop;

var overlayShown = false;

function init() {
  clearTimeout(loop);

  setSettings(function() {

    loop = setTimeout(function() {
      chrome.storage.local.get(show, function(showObj) {
        // console.log('i am running', new Date(showObj[show]));

        if (showObj.hasOwnProperty(show)) {
          var now = Date.now();

          if (showObj[show] < now) {
            chrome.storage.local.get(hide, function(hideObj) {

              if (hideObj[hide] > now) {
                if (!overlayShown) {
                  hideButton(hideObj[hide]);
                  showOverlay();
                  overlayShown = true;
                }
                intervalTimeout = 1000;
                return init();
              } else {
                return showButton(function() {
                  overlayShown = false;
                  setTime();
                });
              }

            })
          } else {
            intervalTimeout = Math.min((showObj[show] - now), 1000);
            showButton(function() {
              if (overlayShown) {
                  overlayShown = false;
                  return init();
              }
            });
          }
        } else {
          return setTime();
        }

      });

    }, intervalTimeout);

  });

}

buildOverlay();
init();
<|endoftext|>