<commit_before>/*@pjs preload="data/images/logo1.png";*/

var sketchProc=function(processingInstance){ with (processingInstance){

//Setup
var wi = window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth;
var he = window.innerHeight ||
         document.documentElement.clientHeight ||
         document.body.clientHeight;
size(wi*0.9,he*0.9);
frameRate(60);

setup = function() {
	mainfont = createFont("Times New Roman");
	logo = loadImage("data/images/logo1.png");
	ismobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

	keys = [];
	pages = [];
	page = 0;

	chapter1 = [];
	chapter1pages = [];
	chapter1length = 6;

	chapter2 = [];
	chapter2pages = [];

	m = false;
	md = false;
	flevel = 255;
	bw = width/6;
	bh = width/12;
	prim = color(15,15,15);
	sec = color(100,30,30);
	tert = color(150,150,150);
	backg = color(55,55,55);

	// Standard fade in.
	fade = function() {
		flevel -= 10;
		fill(55,55,55,flevel);
		noStroke();
		rectMode(CORNER);
		rect(-1,-1,width+1,height+1);
	};

	// Loads all panels in the named folder into the target array.
	loadpanels = function(name,number,target) {
		for (i = 0; i < number;) {
			target[i] = loadImage("data/images/panels/"+name+i+".png");
			i ++;
		}
	};

	// The array of data for buttons used.
	buttons = {
		start:{x:width*(3/4),y:height/2,w:bw,h:bh,text:"Enter"},
		next:{x:width*(8/9),y:height*(1/2),w:bw,h:bh,text:"Next"},
		prev:{x:width*(1/9),y:height*(1/2),w:bw,h:bh,text:"Previous"},
	};

	// The hefty button function.  Works on all platforms tested.  Needs an exterior click call.
	button = function(con) {
		bux = con.x
		buy = con.y
		buw = con.w
		buh = con.h
		butext = con.text
		con.pressed = false;
		mouseover = false;

		rectMode(CENTER);

		if (mouseX>bux-buw/2&&mouseX<bux+buw/2 && mouseY>buy-buh/2&&mouseY<buy+buh/2) {
			mouseover = true;
		}

		if (mouseover) {
			fill(prim);
		} else {
			fill(sec);
		}
		stroke(prim);
		strokeWeight(buh/10);
		rect(bux,buy,buw,buh,buh/2.5);

		if (mouseover) {
			fill(sec);
		} else {
			fill(prim);
		}
		textFont(mainfont,buh/2);
		if (ismobile) {
			textSize(buh/3);
		}
		textAlign(CENTER,CENTER);
		text(butext,bux,buy);

		if (ismobile && mouseover) {
			con.pressed = true;
			return con.pressed;
		}

		if (mouseover && m) {
			con.pressed = true;
			return con.pressed;
		}
		return con.pressed;
	};

	// Standard button layout
	standardbuttons = function() {
		button(buttons.next);
		if (buttons.next.pressed) {
			if (ismobile) {
				if (flevel < 0) {
					page += 1;
					flevel = 255;
				}
			} else if (flevel < 80) {
				page += 1;
				flevel = 255;
			}
		};

		button(buttons.prev);
		if (buttons.prev.pressed) {
			if (ismobile) {
				if (flevel < 0) {
					page -= 1;
					flevel = 255;
				}
			} else if (flevel < 80) {
				page -= 1;
				flevel = 255;
			}

		};
	};

	// Displays an image properly.
	displaypanel = function(img,x,y) {
		imageMode(CENTER);
		pushMatrix();
		translate(x,y);
		scale(0.001*height,0.001*height);
			image(img,0,0);
		popMatrix();
	};

	// Creates a full page
	displaypage = function(chap,number) {
		background(backg);
		displaypanel(chap[number],width/2,height/2);
		standardbuttons();
		fade();
	};
	// Loads an array with full pages
	loadpages = function(cha,targ) {
		for (i = 0; i < cha.length; i ++) {
			targ.push(function() {displaypage("chap1/",page-1)});
		};
		targ[cha.length] = function() {
			background(backg);
			textSize(height/5);
			fill(sec);
			text("Under Construction",width/2,height/2);
		};
	};

	loadpanels("chap1/",chapter1length,chapter1);

	pages = [
		function() {
			background(backg)

			displaypanel(logo,width/4,height/2)

			button(buttons.start)
			if (buttons.start.pressed==true) {
				page += 1
			}
		},

	];
	loadpages(chapter1,pages);
};

draw = function() {
	pages[page]();
	textSize(17);
	text(page,width/2,height/2);
};

keyPressed = function() {
	keys[keyCode] = true;
};
keyReleased = function() {
	keys[keyCode] = false;
};
mousePressed = function() {
	m = true;
};
mouseReleased = function() {
	m = false;
};
}};
<commit_msg>Update main.js<commit_after>/*@pjs preload="data/images/logo1.png";*/

var sketchProc=function(processingInstance){ with (processingInstance){

//Setup
var wi = window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth;
var he = window.innerHeight ||
         document.documentElement.clientHeight ||
         document.body.clientHeight;
size(wi*0.9,he*0.9);
frameRate(60);

setup = function() {
	mainfont = createFont("Times New Roman");
	logo = loadImage("data/images/logo1.png");
	ismobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

	keys = [];
	pages = [];
	page = 0;

	chapter1 = [];
	chapter1pages = [];
	chapter1length = 6;

	chapter2 = [];
	chapter2pages = [];

	m = false;
	md = false;
	flevel = 255;
	bw = width/6;
	bh = width/12;
	prim = color(15,15,15);
	sec = color(100,30,30);
	tert = color(150,150,150);
	backg = color(55,55,55);

	// Standard fade in.
	fade = function() {
		flevel -= 10;
		fill(55,55,55,flevel);
		noStroke();
		rectMode(CORNER);
		rect(-1,-1,width+1,height+1);
	};

	// Loads all panels in the named folder into the target array.
	loadpanels = function(name,number,target) {
		for (i = 0; i < number;) {
			target[i] = loadImage("data/images/panels/"+name+i+".png");
			i ++;
		}
	};
	loadpanels("chap1/",chapter1length,chapter1);

	// The array of data for buttons used.
	buttons = {
		start:{x:width*(3/4),y:height/2,w:bw,h:bh,text:"Enter"},
		next:{x:width*(8/9),y:height*(1/2),w:bw,h:bh,text:"Next"},
		prev:{x:width*(1/9),y:height*(1/2),w:bw,h:bh,text:"Previous"},
	};

	// The hefty button function.  Works on all platforms tested.  Needs an exterior click call.
	button = function(con) {
		bux = con.x
		buy = con.y
		buw = con.w
		buh = con.h
		butext = con.text
		con.pressed = false;
		mouseover = false;

		rectMode(CENTER);

		if (mouseX>bux-buw/2&&mouseX<bux+buw/2 && mouseY>buy-buh/2&&mouseY<buy+buh/2) {
			mouseover = true;
		}

		if (mouseover) {
			fill(prim);
		} else {
			fill(sec);
		}
		stroke(prim);
		strokeWeight(buh/10);
		rect(bux,buy,buw,buh,buh/2.5);

		if (mouseover) {
			fill(sec);
		} else {
			fill(prim);
		}
		textFont(mainfont,buh/2);
		if (ismobile) {
			textSize(buh/3);
		}
		textAlign(CENTER,CENTER);
		text(butext,bux,buy);

		if (ismobile && mouseover) {
			con.pressed = true;
			return con.pressed;
		}

		if (mouseover && m) {
			con.pressed = true;
			return con.pressed;
		}
		return con.pressed;
	};

	// Standard button layout
	standardbuttons = function() {
		button(buttons.next);
		if (buttons.next.pressed) {
			if (ismobile) {
				if (flevel < 0) {
					page += 1;
					flevel = 255;
				}
			} else if (flevel < 80) {
				page += 1;
				flevel = 255;
			}
		};

		button(buttons.prev);
		if (buttons.prev.pressed) {
			if (ismobile) {
				if (flevel < 0) {
					page -= 1;
					flevel = 255;
				}
			} else if (flevel < 80) {
				page -= 1;
				flevel = 255;
			}

		};
	};

	// Displays an image properly.
	displaypanel = function(img,x,y) {
		imageMode(CENTER);
		pushMatrix();
		translate(x,y);
		scale(0.001*height,0.001*height);
			image(img,0,0);
		popMatrix();
	};

	// Creates a full page
	displaypage = function(chap,number) {
		background(backg);
		displaypanel(chap[number],width/2,height/2);
		standardbuttons();
		fade();
	};
	// Loads an array with full pages
	loadpages = function(cha,targ) {
		for (i = 0; i < cha.length; i ++) {
			targ.push(function() {displaypage("chap1/",page-1)});
		};
		targ[cha.length] = function() {
			background(backg);
			textSize(height/5);
			fill(sec);
			text("Under Construction",width/2,height/2);
		};
	};

	pages = [
		function() {
			background(backg)

			displaypanel(logo,width/4,height/2)

			button(buttons.start)
			if (buttons.start.pressed==true) {
				page += 1
			}
		},

	];
	loadpages(chapter1,pages);
};

draw = function() {
	pages[page]();
	textSize(17);
	text(page,width/2,height/2);
};

keyPressed = function() {
	keys[keyCode] = true;
};
keyReleased = function() {
	keys[keyCode] = false;
};
mousePressed = function() {
	m = true;
};
mouseReleased = function() {
	m = false;
};
}};
<|endoftext|>


<commit_before>/** @jsx React.DOM */
var React = require('react/addons');
var cx = React.addons.classSet;

/**
 * Used to cancel events.
 */
var preventDefault = (ev) => ev.preventDefault();

var ListButton = React.createClass({

  render() {
    return (

        {this.props.children}

    );
  }

});

/**
 * Pagination component.
 */
var Pagination = React.createClass({

  mixins: [ React.addons.PureRenderMixin ],

  propTypes: {
    /**
     * Event to trigger. Receives the page number.
     */
    onChangePage: React.PropTypes.func.isRequired,

    /**
     * Total number of pages.
     */
    totalPages: React.PropTypes.number.isRequired,

    /**
     * Current page being displayed.
     */
    currentPage: React.PropTypes.number.isRequired,

    /**
     * The number of pages to show. 5 by default.
     */
    showPages: React.PropTypes.number
  },

  getDefaultProps() {
    return {
      showPages: 5
    };
  },

  onChangePage(pageNumber, event) {
    event.preventDefault();
    this.props.onChangePage(pageNumber);
  },

  render() {
    var {totalPages, showPages, currentPage} = this.props;
    var diff = Math.floor(showPages / 2),
        start = currentPage - diff,
        end = currentPage + diff + 1;

    // Edge cases
    if (totalPages < showPages) {
      start = 0;
      end = totalPages;
    } else if (start <= 0) {
      start = 0;
      end = showPages;
    } else if (end >= totalPages) {
      start = totalPages - showPages;
      end = totalPages;
    }

    var buttons = [], btnClass, btnEvent;
    for (var i = start; i < end; i++) {
      // If the button is for the current page then disable the event.
      if (currentPage === i) {
        btnClass = 'active';
        btnEvent = preventDefault;
      } else {
        btnClass = null;
        btnEvent = this.onChangePage.bind(this, i);
      }
      buttons.push(
        <ListButton
          key={i}
          className={btnClass}
          event={btnEvent}>
          {i + 1}
        </ListButton>
      );
    }

    // First and Prev button handlers and class
    var isFirst = currentPage === 0;
    var firstHandler = isFirst ? preventDefault : this.onChangePage.bind(this, 0);
    var firstClass = cx({
      'first': true,
      'disabled': isFirst
    });
    var prevHandler = isFirst ? preventDefault : this.onChangePage.bind(this, currentPage - 1);
    var prevClass = cx({
      'prev': true,
      'disabled': isFirst
    });

    // Next and Last button handlers and class
    var isLast = currentPage === (totalPages - 1);
    var nextHandler = isLast ? preventDefault : this.onChangePage.bind(this, currentPage + 1);
    var nextClass = cx({
      'next': true,
      'disabled': isLast
    });
    var lastHandler = isLast ? preventDefault : this.onChangePage.bind(this, totalPages - 1);
    var lastClass = cx({
      'last': true,
      'disabled': isLast
    });

    return (

        <ListButton
          className={firstClass}
          event={firstHandler}
        />
        <ListButton
          className={prevClass}
          event={prevHandler}
        />
        {buttons}
        <ListButton
          className={nextClass}
          event={nextHandler}
        />
        <ListButton
          className={lastClass}
          event={lastHandler}
        />

    );
  }
});

module.exports = Pagination;
<commit_msg>Hide pagination if no pages<commit_after>/** @jsx React.DOM */
var React = require('react/addons');
var cx = React.addons.classSet;

/**
 * Used to cancel events.
 */
var preventDefault = (ev) => ev.preventDefault();

var ListButton = React.createClass({

  render() {
    return (

        {this.props.children}

    );
  }

});

/**
 * Pagination component.
 */
var Pagination = React.createClass({

  mixins: [ React.addons.PureRenderMixin ],

  propTypes: {
    /**
     * Event to trigger. Receives the page number.
     */
    onChangePage: React.PropTypes.func.isRequired,

    /**
     * Total number of pages.
     */
    totalPages: React.PropTypes.number.isRequired,

    /**
     * Current page being displayed.
     */
    currentPage: React.PropTypes.number.isRequired,

    /**
     * The number of pages to show. 5 by default.
     */
    showPages: React.PropTypes.number
  },

  getDefaultProps() {
    return {
      showPages: 5
    };
  },

  onChangePage(pageNumber, event) {
    event.preventDefault();
    this.props.onChangePage(pageNumber);
  },

  render() {
    var {totalPages, showPages, currentPage} = this.props;

    if (totalPages === 0) {
      return null;
    }

    var diff = Math.floor(showPages / 2),
        start = currentPage - diff,
        end = currentPage + diff + 1;

    // Edge cases
    if (totalPages < showPages) {
      start = 0;
      end = totalPages;
    } else if (start <= 0) {
      start = 0;
      end = showPages;
    } else if (end >= totalPages) {
      start = totalPages - showPages;
      end = totalPages;
    }

    var buttons = [], btnClass, btnEvent;
    for (var i = start; i < end; i++) {
      // If the button is for the current page then disable the event.
      if (currentPage === i) {
        btnClass = 'active';
        btnEvent = preventDefault;
      } else {
        btnClass = null;
        btnEvent = this.onChangePage.bind(this, i);
      }
      buttons.push(
        <ListButton
          key={i}
          className={btnClass}
          event={btnEvent}>
          {i + 1}
        </ListButton>
      );
    }

    // First and Prev button handlers and class
    var isFirst = currentPage === 0;
    var firstHandler = isFirst ? preventDefault : this.onChangePage.bind(this, 0);
    var firstClass = cx({
      'first': true,
      'disabled': isFirst
    });
    var prevHandler = isFirst ? preventDefault : this.onChangePage.bind(this, currentPage - 1);
    var prevClass = cx({
      'prev': true,
      'disabled': isFirst
    });

    // Next and Last button handlers and class
    var isLast = currentPage === (totalPages - 1);
    var nextHandler = isLast ? preventDefault : this.onChangePage.bind(this, currentPage + 1);
    var nextClass = cx({
      'next': true,
      'disabled': isLast
    });
    var lastHandler = isLast ? preventDefault : this.onChangePage.bind(this, totalPages - 1);
    var lastClass = cx({
      'last': true,
      'disabled': isLast
    });

    return (

        <ListButton
          className={firstClass}
          event={firstHandler}
        />
        <ListButton
          className={prevClass}
          event={prevHandler}
        />
        {buttons}
        <ListButton
          className={nextClass}
          event={nextHandler}
        />
        <ListButton
          className={lastClass}
          event={lastHandler}
        />

    );
  }
});

module.exports = Pagination;
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import Icon from './Icon';
import PaginationButton from './PaginationButton';

class Pagination extends Component {
  constructor (props) {
    super(props);
    const { activePage, items } = props;

    this.state = {
      activePage: activePage > 0 && activePage <= items
        ? activePage : 1
    };

    this.renderButtons = this.renderButtons.bind(this);
    this._onClick = this._onClick.bind(this);
  }

  _onClick (i) {
    const { items, onSelect } = this.props;

    return () => {
      if (i > 0 && i <= items) {
        if (onSelect) { onSelect(i); }
        this.setState({ activePage: i });
      }
    };
  }

  renderButtons () {
    const { items, children, maxButtons = items } = this.props;
    const { activePage } = this.state;

    if (children) return children;

    const buttonsCount = Math.min(maxButtons, items);

    const maxPos = items - buttonsCount;
    const halfButtons = parseInt(buttonsCount / 2, 10);

    let hiddenPagesBefore = (activePage - halfButtons);
    if (hiddenPagesBefore > maxPos) {
      hiddenPagesBefore = maxPos + 1;
    }

    let from = Math.max(hiddenPagesBefore, 1);
    let to = Math.min(items, from + maxButtons - 1);

    const buttons = [
      <PaginationButton
        disabled={activePage === 1}
        key={'pagination-0'}
        onSelect={this._onClick(activePage - 1)}
      >
        <Icon>chevron_left</Icon>
      </PaginationButton>
    ];

    for (let i = from; i <= to; i++) {
      buttons.push(
        <PaginationButton
          active={i === activePage}
          key={`pagination-${i}`}
          onSelect={this._onClick(i)}
        >
          {i}
        </PaginationButton>
      );
    }

    buttons.push(
      <PaginationButton
        key={`pagination-${items + 1}`}
        disabled={activePage === items}
        onSelect={this._onClick(activePage + 1)}
      >
        <Icon>chevron_right</Icon>
      </PaginationButton>
    );

    return buttons;
  }

  render () {
    return (

{ this.renderButtons() }

    );
  }
}

Pagination.propTypes = {
  /**
   * Number of items in the component
   */
  items: PropTypes.number.isRequired,
  /**
   * The initial activePage
   */
  activePage: PropTypes.number,
  children: PropTypes.node,
  className: PropTypes.string,
  maxButtons: PropTypes.number,
  onSelect: PropTypes.func
};

Pagination.defaultProps = {
  activePage: 1,
  items: 10
};

export default Pagination;
<commit_msg>Allow pagination to support controlled operation (#278)<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import Icon from './Icon';
import PaginationButton from './PaginationButton';

class Pagination extends Component {
  constructor (props) {
    super(props);
    const { activePage, items } = props;

    this.state = {
      activePage: activePage > 0 && activePage <= items
        ? activePage : 1
    };

    this.renderButtons = this.renderButtons.bind(this);
    this._onClick = this._onClick.bind(this);
  }

  componentWillReceiveProps (nextProps) {
    if (nextProps.activePage !== this.props.activePage) {
      this.setState({activePage: nextProps.activePage});
    }
  }

  _onClick (i) {
    const { items, onSelect } = this.props;

    return () => {
      if (i > 0 && i <= items) {
        if (onSelect) { onSelect(i); }
        this.setState({ activePage: i });
      }
    };
  }

  renderButtons () {
    const { items, children, maxButtons = items } = this.props;
    const { activePage } = this.state;

    if (children) return children;

    const buttonsCount = Math.min(maxButtons, items);

    const maxPos = items - buttonsCount;
    const halfButtons = parseInt(buttonsCount / 2, 10);

    let hiddenPagesBefore = (activePage - halfButtons);
    if (hiddenPagesBefore > maxPos) {
      hiddenPagesBefore = maxPos + 1;
    }

    let from = Math.max(hiddenPagesBefore, 1);
    let to = Math.min(items, from + maxButtons - 1);

    const buttons = [
      <PaginationButton
        disabled={activePage === 1}
        key={'pagination-0'}
        onSelect={this._onClick(activePage - 1)}
      >
        <Icon>chevron_left</Icon>
      </PaginationButton>
    ];

    for (let i = from; i <= to; i++) {
      buttons.push(
        <PaginationButton
          active={i === activePage}
          key={`pagination-${i}`}
          onSelect={this._onClick(i)}
        >
          {i}
        </PaginationButton>
      );
    }

    buttons.push(
      <PaginationButton
        key={`pagination-${items + 1}`}
        disabled={activePage === items}
        onSelect={this._onClick(activePage + 1)}
      >
        <Icon>chevron_right</Icon>
      </PaginationButton>
    );

    return buttons;
  }

  render () {
    return (

{ this.renderButtons() }

    );
  }
}

Pagination.propTypes = {
  /**
   * Number of items in the component
   */
  items: PropTypes.number.isRequired,
  /**
   * The initial activePage
   */
  activePage: PropTypes.number,
  children: PropTypes.node,
  className: PropTypes.string,
  maxButtons: PropTypes.number,
  onSelect: PropTypes.func
};

Pagination.defaultProps = {
  activePage: 1,
  items: 10
};

export default Pagination;
<|endoftext|>


<commit_before>/*jslint indent: 2 */
/*global window: false, XMLHttpRequest: false, chrome: false, btoa: false */
"use strict";
var TogglButton = {
  $user: null,
  $apiUrl: "https://www.toggl.com/api/v7",
  $newApiUrl: "https://new.toggl.com/api/v8",
  $sites: new RegExp([
    'asana\\.com',
    'podio\\.com',
    'trello\\.com',
    'github\\.com',
    'bitbucket\\.org',
    'gitlab\\.com',
    'redbooth\\.com',
    'teamweek\\.com',
    'basecamp\\.com',
    'unfuddle\\.com',
    'worksection\\.com',
    'pivotaltracker\\.com',
    'producteev\\.com'].join('|')),
  $curEntryId: null,

  checkUrl: function (tabId, changeInfo, tab) {
    if (changeInfo.status === 'complete') {
      if (TogglButton.$sites.test(tab.url)) {
        TogglButton.setPageAction(tabId);
      } else if (/toggl\.com\/track/.test(tab.url)) {
        TogglButton.fetchUser(TogglButton.$apiUrl);
      } else if (/toggl\.com\/app/.test(tab.url)) {
        TogglButton.fetchUser(TogglButton.$newApiUrl);
      }
    }
  },

  fetchUser: function (apiUrl) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", apiUrl + "/me?with_related_data=true", true);
    xhr.onload = function () {
      if (xhr.status === 200) {
        var projectMap = {}, resp = JSON.parse(xhr.responseText);
        if (resp.data.projects) {
          resp.data.projects.forEach(function (project) {
            projectMap[project.name] = project.id;
          });
        }
        TogglButton.$user = resp.data;
        TogglButton.$user.projectMap = projectMap;
      } else if (apiUrl === TogglButton.$apiUrl) {
        TogglButton.fetchUser(TogglButton.$newApiUrl);
      }
    };
    xhr.send();
  },

  createTimeEntry: function (timeEntry) {

    var start = new Date(),
      xhr = new XMLHttpRequest(),
      entry = {
        time_entry: {
          start: start.toISOString(),
          description: timeEntry.description,
          wid: TogglButton.$user.default_wid,
          pid: timeEntry.projectId || null,
          billable: timeEntry.billable || false,
          duration: -(start.getTime() / 1000),
          created_with: timeEntry.createdWith || 'TogglButton'
        }
      };

    if(timeEntry.projectName !== undefined) {
      entry.time_entry.pid = TogglButton.$user.projectMap[timeEntry.projectName];
    }

		//Create a new Project incase the projects map array doesn't already contain the requested project
		if(timeEntry.projectName !== undefined && timeEntry.projectName != "" && (entry.time_entry.pid == null || entry.time_entry.pid == undefined)) {
			TogglButton.createNewProject(timeEntry.projectName,timeEntry);
			return false; //stop here until the new project is created
		}

    xhr.open("POST", TogglButton.$newApiUrl + "/time_entries", true);
    xhr.setRequestHeader('Authorization', 'Basic ' + btoa(TogglButton.$user.api_token + ':api_token'));

		// handle response
    xhr.addEventListener('load', function (e) {
      var responseData, entryId;
      responseData = JSON.parse(xhr.responseText);
      entryId = responseData && responseData.data && responseData.data.id;
      TogglButton.$curEntryId = entryId;
    });
    xhr.send(JSON.stringify(entry));
  },

  stopTimeEntry: function (entryId) {
    entryId = entryId || TogglButton.$curEntryId;
    if (!entryId) {
      return;
    }
    var xhr = new XMLHttpRequest();

    // PUT https://www.toggl.com/api/v8/time_entries/{time_entry_id}/stop
    xhr.open("PUT", TogglButton.$newApiUrl + "/time_entries/" + entryId + "/stop", true);
    xhr.setRequestHeader('Authorization', 'Basic ' + btoa(TogglButton.$user.api_token + ':api_token'));
    xhr.send();
  },

	//Create a New Project
	createNewProject: function (projectName,timeEntry) {

  	var xhr = new XMLHttpRequest();
		var project_data = {
		      project: {
		        name: projectName,
		        wid: TogglButton.$user.default_wid
		      }
    };

		//POST https://www.toggl.com/api/v8/projects
    xhr.open("POST", TogglButton.$newApiUrl + "/projects", true);
    xhr.setRequestHeader('Authorization', 'Basic ' + btoa(TogglButton.$user.api_token + ':api_token'));

		// handle response
    xhr.addEventListener('load', function (e) {
      var responseData, projectId;
      responseData = JSON.parse(xhr.responseText);
      projectId = responseData && responseData.data && responseData.data.id;

			if(projectId == null || projectId == undefined){
				projectId = 0;
			}

			TogglButton.$user.projectMap[projectName] = projectId;

			TogglButton.createTimeEntry(timeEntry);

    });
    xhr.send(JSON.stringify(project_data));
	},

  setPageAction: function (tabId) {
    var imagePath = 'images/inactive-19.png';
    if (TogglButton.$user !== null) {
      imagePath = 'images/active-19.png';
    }
    chrome.pageAction.setIcon({
      tabId: tabId,
      path: imagePath
    });
    chrome.pageAction.show(tabId);
  },

  newMessage: function (request, sender, sendResponse) {
    if (request.type === 'activate') {
      TogglButton.setPageAction(sender.tab.id);
      sendResponse({success: TogglButton.$user !== null, user: TogglButton.$user});
    } else if (request.type === 'timeEntry') {
      TogglButton.createTimeEntry(request);
    } else if (request.type === 'stop') {
      TogglButton.stopTimeEntry();
    }
  }

};

chrome.pageAction.onClicked.addListener(function (tab) {
  if (TogglButton.$user === null) {
    chrome.tabs.create({url: 'https://new.toggl.com/#login'});
  }
});

TogglButton.fetchUser(TogglButton.$apiUrl);
chrome.tabs.onUpdated.addListener(TogglButton.checkUrl);
chrome.extension.onMessage.addListener(TogglButton.newMessage);
<commit_msg>Upon @tambet recommendation of preventing secret project adding to toggl I added a user prompt of this action first<commit_after>/*jslint indent: 2 */
/*global window: false, XMLHttpRequest: false, chrome: false, btoa: false */
"use strict";
var TogglButton = {
  $user: null,
  $apiUrl: "https://www.toggl.com/api/v7",
  $newApiUrl: "https://new.toggl.com/api/v8",
  $sites: new RegExp([
    'asana\\.com',
    'podio\\.com',
    'trello\\.com',
    'github\\.com',
    'bitbucket\\.org',
    'gitlab\\.com',
    'redbooth\\.com',
    'teamweek\\.com',
    'basecamp\\.com',
    'unfuddle\\.com',
    'worksection\\.com',
    'pivotaltracker\\.com',
    'producteev\\.com'].join('|')),
  $curEntryId: null,

  checkUrl: function (tabId, changeInfo, tab) {
    if (changeInfo.status === 'complete') {
      if (TogglButton.$sites.test(tab.url)) {
        TogglButton.setPageAction(tabId);
      } else if (/toggl\.com\/track/.test(tab.url)) {
        TogglButton.fetchUser(TogglButton.$apiUrl);
      } else if (/toggl\.com\/app/.test(tab.url)) {
        TogglButton.fetchUser(TogglButton.$newApiUrl);
      }
    }
  },

  fetchUser: function (apiUrl) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", apiUrl + "/me?with_related_data=true", true);
    xhr.onload = function () {
      if (xhr.status === 200) {
        var projectMap = {}, resp = JSON.parse(xhr.responseText);
        if (resp.data.projects) {
          resp.data.projects.forEach(function (project) {
            projectMap[project.name] = project.id;
          });
        }
        TogglButton.$user = resp.data;
        TogglButton.$user.projectMap = projectMap;
      } else if (apiUrl === TogglButton.$apiUrl) {
        TogglButton.fetchUser(TogglButton.$newApiUrl);
      }
    };
    xhr.send();
  },

  createTimeEntry: function (timeEntry) {

    var start = new Date(),
      xhr = new XMLHttpRequest(),
      entry = {
        time_entry: {
          start: start.toISOString(),
          description: timeEntry.description,
          wid: TogglButton.$user.default_wid,
          pid: timeEntry.projectId || null,
          billable: timeEntry.billable || false,
          duration: -(start.getTime() / 1000),
          created_with: timeEntry.createdWith || 'TogglButton'
        }
      };

    if(timeEntry.projectName !== undefined) {
      entry.time_entry.pid = TogglButton.$user.projectMap[timeEntry.projectName];
    }

		//Create a new Project incase the projects map array doesn't already contain the requested project
		if(timeEntry.projectName !== undefined && timeEntry.projectName != "" && (entry.time_entry.pid == null || entry.time_entry.pid == undefined)) {
			if(confirm('Toggl couldn\'t find a project called "' + timeEntry.projectName + '". Would you like to create one now ?')){
				TogglButton.createNewProject(timeEntry.projectName,timeEntry);
				return false; //stop here until the new project is created
			}
		}

    xhr.open("POST", TogglButton.$newApiUrl + "/time_entries", true);
    xhr.setRequestHeader('Authorization', 'Basic ' + btoa(TogglButton.$user.api_token + ':api_token'));

		// handle response
    xhr.addEventListener('load', function (e) {
      var responseData, entryId;
      responseData = JSON.parse(xhr.responseText);
      entryId = responseData && responseData.data && responseData.data.id;
      TogglButton.$curEntryId = entryId;
    });
    xhr.send(JSON.stringify(entry));
  },

  stopTimeEntry: function (entryId) {
    entryId = entryId || TogglButton.$curEntryId;
    if (!entryId) {
      return;
    }
    var xhr = new XMLHttpRequest();

    // PUT https://www.toggl.com/api/v8/time_entries/{time_entry_id}/stop
    xhr.open("PUT", TogglButton.$newApiUrl + "/time_entries/" + entryId + "/stop", true);
    xhr.setRequestHeader('Authorization', 'Basic ' + btoa(TogglButton.$user.api_token + ':api_token'));
    xhr.send();
  },

	//Create a New Project
	createNewProject: function (projectName,timeEntry) {

  	var xhr = new XMLHttpRequest();
		var project_data = {
		      project: {
		        name: projectName,
		        wid: TogglButton.$user.default_wid
		      }
    };

		//POST https://www.toggl.com/api/v8/projects
    xhr.open("POST", TogglButton.$newApiUrl + "/projects", true);
    xhr.setRequestHeader('Authorization', 'Basic ' + btoa(TogglButton.$user.api_token + ':api_token'));

		// handle response
    xhr.addEventListener('load', function (e) {
      var responseData, projectId;
      responseData = JSON.parse(xhr.responseText);
      projectId = responseData && responseData.data && responseData.data.id;

			if(projectId == null || projectId == undefined){
				projectId = 0;
			}

			TogglButton.$user.projectMap[projectName] = projectId;

			TogglButton.createTimeEntry(timeEntry);

    });
    xhr.send(JSON.stringify(project_data));
	},

  setPageAction: function (tabId) {
    var imagePath = 'images/inactive-19.png';
    if (TogglButton.$user !== null) {
      imagePath = 'images/active-19.png';
    }
    chrome.pageAction.setIcon({
      tabId: tabId,
      path: imagePath
    });
    chrome.pageAction.show(tabId);
  },

  newMessage: function (request, sender, sendResponse) {
    if (request.type === 'activate') {
      TogglButton.setPageAction(sender.tab.id);
      sendResponse({success: TogglButton.$user !== null, user: TogglButton.$user});
    } else if (request.type === 'timeEntry') {
      TogglButton.createTimeEntry(request);
    } else if (request.type === 'stop') {
      TogglButton.stopTimeEntry();
    }
  }

};

chrome.pageAction.onClicked.addListener(function (tab) {
  if (TogglButton.$user === null) {
    chrome.tabs.create({url: 'https://new.toggl.com/#login'});
  }
});

TogglButton.fetchUser(TogglButton.$apiUrl);
chrome.tabs.onUpdated.addListener(TogglButton.checkUrl);
chrome.extension.onMessage.addListener(TogglButton.newMessage);
<|endoftext|>


<commit_before>/*
Copyright 2015 Johannes Filter, Rosario Raulin

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var request = require('request');
var async = require('async');

var QUERY_PATH_BASE = 'http://reiseauskunft.insa.de/bin/query.exe/dny?performLocating=2&tpl=stop2json&look_maxno=20';
var QUERY_JOURNEYS_PATH_BASE = 'http://reiseauskunft.insa.de/bin/stboard.exe/dn?L=.vs_stb&L=.vs_stb.vs_stb&boardType=dep&selectDate=today&productsFilter=0000011111&additionalTime=0&start=yes&requestType=0&outputMode=undefined&maxJourneys=30';

var getFormatedCoordinate = function(coordinate) {
  // The geolocations are requiered in a specific format
  // without points and only 8 digits
  var formattedCoordinate = coordinate.replace('.', '');

  while ( formattedCoordinate.length < 8 ) {
    formattedCoordinate += '0';
  }

  // cut of last
  formattedCoordinate = formattedCoordinate.substring(0, 8);

  return formattedCoordinate;
};

var getQueryPath = function(longitude, latitude) {
  var formattedLongitude = getFormatedCoordinate(longitude);
  var formattedLatitude = getFormatedCoordinate(latitude);

  return QUERY_PATH_BASE + '&look_x=' + formattedLongitude + '&look_y=' + formattedLatitude;
};

// Filter out stations for IC/RB/RE/S-Bahn/U-Bahn
var getFilteredStations = function(stations) {
  var stationsWithId = [];

  for(i = 0; i < stations.length; i++) {
    if ( parseInt(stations[i].prodclass) > 31 ) {
      stationsWithId.push( {id: stations[i].extId, name: stations[i].name} );
    }
  }

  return stationsWithId;
};

var getRequestCallback = function(callback){
  return function (err, resp, body) {

      if (err) {
        callback(err, null);

      } else {
        try {
          var bodyJSON = JSON.parse(body);
          var stations = bodyJSON.stops;
          var stationsWithId = getFilteredStations(stations);

          // look for journeys of each stations
          async.map ( stationsWithId,
            // for each id
            getJourneys,
            // results saved here
            function(err, times){
              callback(null, times);
            });
        } catch (e) {
          callback(err, []); // return empty error
        }
      }
  };
};

var getDepartureTimes = function (long, lat, callback) {
  var path = getQueryPath(long, lat);

  //TODO-Moezalez refactor callbacks. Maybe Q Library?
  request(path, {encoding: null}, getRequestCallback(callback));
};

var getJourneyQueryPath = function(stationID) {
  var current_date = new Date();
  var string_date = current_date.getHours() + ':' + current_date.getMinutes();

  return QUERY_JOURNEYS_PATH_BASE + '&input='+ stationID + '&time=' + string_date;
};

var parseHtmlBodyToJSON = function(body) {
  var bodyString = body.toString('utf-8');
  var bodyStringDecoded = decodeHtmlEntity(bodyString).replace('journeysObj = ','');

  return JSON.parse(bodyStringDecoded);
}

var getJourneyRequestCallback = function(name, callback) {
  return function (err, resp, body) {
    if (err) {
      callback(err, null);

    } else {

      var bodyJSON = parseHtmlBodyToJSON(body);

      times = [];

      // return if no journeys are present
      if( !bodyJSON.hasOwnProperty('journey') )
      {
        callback(null, times);
      }
      else
      {
        var journeys = bodyJSON.journey;
        for ( i = 0; i < journeys.length; i++ ) {
          var row = journeys[i];

          // taking care of wrongly inserted journeys
          if ( row.pr !== "" && row.st !== "" && row.ti !== "" ) {

            // INSA format of Date
            var insaDate = row.ti;

            var obj = {
              "line": row.pr,
              "direction": removeCityNames(row.st),
            };

            if (! row.rt === false) {
              obj['delay'] = {};

              if ( row.rt.dlm != null) {
                obj['delay']['minutes'] = row.rt.dlm;
              }

              if ( row.rt.status != null) {
                obj['delay']['status'] = row.rt.status;
              }

              // override original departure
              if ( row.rt.dlt != null) {
                insaDate = row.rt.dlt;
              }
            }

            // convert to Date
            var currentDate = new Date();
            var departureDate = new Date();
            var splittedDateInput = insaDate.split(':');

            departureDate.setMinutes(parseInt(splittedDateInput[1]));
            departureDate.setHours(parseInt(splittedDateInput[0]));

            if ( departureDate < currentDate ) {
              departureDate.setDate(departureDate.getDate() + 1); // increment by one day
            }

            obj['departure'] = departureDate.toJSON();

            times.push( obj );
          }
        }

        // Sorting because INSA don't provide it sorted
        // Compare on Dates
        times.sort(function(a, b) {
          return a.departure.localeCompare(b.departure);
        });

        callback(null, { station_info: name, departure_times: times });
      }
    }
  };
};

// get journeys of one station
// productFilter= masking out ICE/IC/RE/RB/S/U
var getJourneys = function (station, callback) {
  var name = removeCityNames(station.name);
  var path = getJourneyQueryPath(station.id);

  request(path, {encoding: null}, getJourneyRequestCallback(name, callback));
};

var decodeHtmlEntity = function(str) {
  return str.replace(/&#(\d+);/g, function(match, dec) {
    return String.fromCharCode(dec);
  });
};

var removeCityNames = function(str) {
  return str.replace('Magdeburg, ','').replace('Halle (Saale), ', '').replace('Leipzig, ','');
};

exports.get_departure_times = getDepartureTimes;
<commit_msg>Some more refactoring. Still some refactoring to do.<commit_after>/*
Copyright 2015 Johannes Filter, Rosario Raulin

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var request = require('request');
var async = require('async');

var QUERY_PATH_BASE = 'http://reiseauskunft.insa.de/bin/query.exe/dny?performLocating=2&tpl=stop2json&look_maxno=20';
var QUERY_JOURNEYS_PATH_BASE = 'http://reiseauskunft.insa.de/bin/stboard.exe/dn?L=.vs_stb&L=.vs_stb.vs_stb&boardType=dep&selectDate=today&productsFilter=0000011111&additionalTime=0&start=yes&requestType=0&outputMode=undefined&maxJourneys=30';

var decodeHtmlEntity = function(str) {
  return str.replace(/&#(\d+);/g, function(match, dec) {
    return String.fromCharCode(dec);
  });
};

var removeCityNames = function(str) {
  return str.replace('Magdeburg, ','').replace('Halle (Saale), ', '').replace('Leipzig, ','');
};

var parseHtmlBodyToJSON = function(body) {
  var bodyString = body.toString('utf-8');
  var bodyStringDecoded = decodeHtmlEntity(bodyString).replace('journeysObj = ','');

  return JSON.parse(bodyStringDecoded);
};

var getDateFromInsaDate = function(insaDate) {
  var currentDate = new Date();
  var departureDate = new Date();
  var splittedDateInput = insaDate.split(':');

  departureDate.setMinutes(parseInt(splittedDateInput[1]));
  departureDate.setHours(parseInt(splittedDateInput[0]));

  if ( departureDate < currentDate ) {
    departureDate.setDate(departureDate.getDate() + 1); // increment by one day
  }

  return departureDate;
};

//TODO refactor
var getJourneyRequestCallback = function(name, callback) {
  return function (err, resp, body) {
    if (err) {
      callback(err, null);

    } else {

      var bodyJSON = parseHtmlBodyToJSON(body);
      var times = [];

      // return if no journeys are present
      if( !bodyJSON.hasOwnProperty('journey') ) {
        callback(null, times);

      } else {
        var journeys = bodyJSON.journey;

        for ( i = 0; i < journeys.length; i++ ) {
          var curRow = journeys[i];

          // taking care of wrongly inserted journeys
          if ( curRow.pr !== "" && curRow.st !== "" && curRow.ti !== "" ) {

            // INSA format of Date
            var insaDate = curRow.ti;

            var obj = {
              "line": curRow.pr,
              "direction": removeCityNames(curRow.st),
            };

            //FIX Confusing use of '!'.
            if (! curRow.rt === false) {
              obj['delay'] = {};

              if ( curRow.rt.dlm != null) {
                obj['delay']['minutes'] = curRow.rt.dlm;
              }

              if ( curRow.rt.status != null) {
                obj['delay']['status'] = curRow.rt.status;
              }

              // override original departure
              if ( curRow.rt.dlt != null) {
                insaDate = curRow.rt.dlt;
              }
            }

            var departureDate = getDateFromInsaDate(insaDate);
            obj['departure'] = departureDate.toJSON();
            times.push( obj );
          }
        }

        // Sorting because INSA don't provide it sorted
        // Compare on Dates
        times.sort(function(a, b) {
          return a.departure.localeCompare(b.departure);
        });

        callback(null, { station_info: name, departure_times: times });
      }
    }
  };
};

var getJourneyQueryPath = function(stationID) {
  var current_date = new Date();
  var string_date = current_date.getHours() + ':' + current_date.getMinutes();

  return QUERY_JOURNEYS_PATH_BASE + '&input='+ stationID + '&time=' + string_date;
};

// get journeys of one station
// productFilter= masking out ICE/IC/RE/RB/S/U
var getJourneys = function (station, callback) {
  var name = removeCityNames(station.name);
  var path = getJourneyQueryPath(station.id);

  //TODO refactor callbacks. Maybe Q Library?
  request(path, {encoding: null}, getJourneyRequestCallback(name, callback));
};

var getFormatedCoordinate = function(coordinate) {
  // The geolocations are requiered in a specific format
  // without points and only 8 digits
  var formattedCoordinate = coordinate.replace('.', '');

  while ( formattedCoordinate.length < 8 ) {
    formattedCoordinate += '0';
  }

  formattedCoordinate = formattedCoordinate.substring(0, 8);

  return formattedCoordinate;
};

// Filter out stations for IC/RB/RE/S-Bahn/U-Bahn
var getFilteredStations = function(stations) {
  var stationsWithId = [];

  for(i = 0; i < stations.length; i++) {
    if ( parseInt(stations[i].prodclass) > 31 ) {
      stationsWithId.push( {id: stations[i].extId, name: stations[i].name} );
    }
  }

  return stationsWithId;
};

var getRequestCallback = function(callback){
  return function (err, resp, body) {

      if (err) {
        callback(err, null);

      } else {
        try {
          var bodyJSON = JSON.parse(body);
          var stations = bodyJSON.stops;
          var stationsWithId = getFilteredStations(stations);

          // look for journeys of each stations
          async.map ( stationsWithId,
            // for each id
            getJourneys,
            // results saved here
            function(err, times){
              callback(null, times);
            });
        } catch (e) {
          callback(err, []); // return empty error
        }
      }
  };
};

var getQueryPath = function(longitude, latitude) {
  var formattedLongitude = getFormatedCoordinate(longitude);
  var formattedLatitude = getFormatedCoordinate(latitude);

  return QUERY_PATH_BASE + '&look_x=' + formattedLongitude + '&look_y=' + formattedLatitude;
};

var getDepartureTimes = function (long, lat, callback) {
  var path = getQueryPath(long, lat);

  //TODO refactor callbacks. Maybe Q Library?
  request(path, {encoding: null}, getRequestCallback(callback));
};

module.exports = {
  get_departure_times: getDepartureTimes
};
<|endoftext|>


<commit_before>/*!
 * Detectizr v1.0
 * http://barisaydinoglu.github.com/Detectizr/
 * https://github.com/barisaydinoglu/Detectizr
 * Written by Baris Aydinoglu (http://baris.aydinoglu.info) - Copyright  2012
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Inspirations:
 *  - Browser selectors in CSS - http://37signals.com/svn/archives2/browser_selectors_in_css.php
 *  - Categorizr - http://www.brettjankord.com/2012/01/16/categorizr-a-modern-device-detection-script/
*/

/*
 * Detecizr, which requires Modernizr, adds some tests to Modernizr.
 * It detects device, device model, screen size, operating system,
 * and browser details.
 * Detection of these sets are optional and can be disabled.
 *
 * Detectable device types are: tv (includes smart tv and game console),
 * mobile, tablet, and desktop. Device models of tv, mobile and tablet
 * are being detected.
 *
 * Author         Baris Aydinoglu
 */

(function (window, navigator) {
    var Modernizr = window.Modernizr,
		options = {
			// option for enabling HTML classes of all features (not only the true features) to be added
            addAllFeaturesAsClass: false,
			// option for enabling detection of device
            detectDevice: true,
			// option for enabling detection of device model
            detectDeviceModel: true,
			// option for enabling detection of screen size
            detectScreen: true,
			// option for enabling detection of operating system type and version
            detectOS: true,
			// option for enabling detection of browser type and version
            detectBrowser: true
        };
    function Detectizr(opt) {
		// Create Global 'extend' method, so Detectizr does not need jQuery.extend
		var extend = function(obj, extObj) {
			if (arguments.length > 2) {
				for (var a = 1; a < arguments.length; a++) {
					extend(obj, arguments[a]);
				}
			} else {
				for (var i in extObj) {
					obj[i] = extObj[i];
				}
			}
			return obj;
		};
	    var that = this, device = Modernizr.Detectizr.device, deviceTypes = ['tv', 'tablet', 'mobile', 'desktop'], i;
		options = extend({}, options, opt || {});
		// simplified and localized indexOf method as one parameter fixed as useragent
        that.is = function (key) {
            return device.userAgent.indexOf(key) > -1;
        };
		// simplified and localized regex test method as one parameter fixed as useragent
        that.test = function (regex) {
            return regex.test(device.userAgent);
        };
		// simplified and localized regex exec method as one parameter fixed as useragent
        that.exec = function (regex) {
            return regex.exec(device.userAgent);
        };
		// convert string to camelcase
        that.toCamel = function (string) {
			if (string === null || string === undefined) {
				return '';
			}
            string = string + '';
            return string.replace(/((\s|\-|\.)+[a-z0-9])/g, function ($1) {
                return $1.toUpperCase().replace(/(\s|\-|\.)/g, '');
            });
        };
		// add version test to Modernizr
        that.addVersionTest = function (mainTest, version, maxLength) {
            if (version !== null && version !== undefined && version !== '') {
                version = that.toCamel(version);
                if (version !== '') {
                    if (maxLength !== undefined && maxLength > 0) {
                        version = version.substr(0, maxLength);
                    }
                    that.addConditionalTest(mainTest + version, true);
                }
            }
        };
		// add test to Modernizr based on a conditi
        that.addConditionalTest = function (feature, test) {
			if (feature === null || feature === undefined || feature === '') {
				return;
			}
            if (options.addAllFeaturesAsClass) {
                Modernizr.addTest(feature, test);
            } else {
                test = typeof test === 'function' ? test() : test;
                if (test) {
                    Modernizr.addTest(feature, true);
                }
            }
        };

        /** Device detection **/
        if (options.detectDevice) {
            if (that.test(/GoogleTV|SmartTV|Internet.TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|CE\-HTML/i)) {
                // Check if user agent is a smart tv
                device.type = deviceTypes[0];
                device.model = "smartTv";
            } else if (that.test(/Xbox|PLAYSTATION.3|Wii/i)) {
                // Check if user agent is a game console
                device.type = deviceTypes[0];
                device.model = "gameConsole";
            } else if (that.test(/iP(a|ro)d/i)) {
                // Check if user agent is a iPad
                device.type = deviceTypes[1];
                device.model = 'ipad';
            } else if ((that.test(/tablet/i) && !that.test(/RX-34/i)) || that.test(/FOLIO/i)) {
                // Check if user agent is a Tablet
                device.type = deviceTypes[1];
            } else if (that.test(/Linux/i) && that.test(/Android/i) && !that.test(/Fennec|mobi|HTC.Magic|HTCX06HT|Nexus.One|SC-02B|fone.945/i)) {
                // Check if user agent is an Android Tablet
                device.type = deviceTypes[1];
                device.model = 'android';
            } else if (that.test(/Kindle/i) || (that.test(/Mac.OS/i) && that.test(/Silk/i))) {
                // Check if user agent is a Kindle or Kindle Fire
                device.type = deviceTypes[1];
                device.model = 'kindle';
            } else if (that.test(/GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC(.Flyer|\_Flyer)|Sprint.ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos.S7|Dell.Streak.7|Advent.Vega|A101IT|A70BHT|MID7015|Next2|nook/i) || (that.test(/MB511/i) && that.test(/RUTEM/i))) {
                // Check if user agent is a pre Android 3.0 Tablet
                device.type = deviceTypes[1];
                device.model = 'android';
            } else {
                // Check if user agent is one of common mobile types
                device.model = that.exec(/iphone|ipod|android|blackberry|opera mini|opera mobi|skyfire|maemo|windows phone|palm|iemobile|symbian|symbianos|fennec|j2me/i);
                if (device.model !== null) {
					device.type = deviceTypes[2];
                    device.model = device.model + "";
				} else {
                    device.model = "";
					if (that.test(/BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google.Wireless.Transcoder/i)) {
						// Check if user agent is unique Mobile User Agent
						device.type = deviceTypes[2];
					} else if (that.test(/Opera/i) && that.test(/Windows.NT.5/i) && that.test(/HTC|Xda|Mini|Vario|SAMSUNG\-GT\-i8000|SAMSUNG\-SGH\-i9/i)) {
						// Check if user agent is an odd Opera User Agent - http://goo.gl/nK90K
						device.type = deviceTypes[2];
					} else if ((that.test(/Windows.(NT|XP|ME|9)/i) && !that.test(/Phone/i)) || that.test(/Win(9|.9|NT)/i)) {
						// Check if user agent is Windows Desktop
						device.type = deviceTypes[3];
					} else if (that.test(/Macintosh|PowerPC/i) && !that.test(/Silk/i)) {
						// Check if agent is Mac Desktop
						device.type = deviceTypes[3];
					} else if (that.test(/Linux/i) && that.test(/X11/i)) {
						// Check if user agent is a Linux Desktop
						device.type = deviceTypes[3];
					} else if (that.test(/Solaris|SunOS|BSD/i)) {
						// Check if user agent is a Solaris, SunOS, BSD Desktop
						device.type = deviceTypes[3];
					} else if (that.test(/Bot|Crawler|Spider|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|TinEye/i) && !that.test(/Mobile/i)) {
						// Check if user agent is a Desktop BOT/Crawler/Spider
						device.type = deviceTypes[3];
						device.model = 'crawler';
					} else {
						// Otherwise assume it is a Mobile Device
						device.type = deviceTypes[2];
					}
				}
            }
			i = deviceTypes.length;
			while (i--) {
				that.addConditionalTest(deviceTypes[i], (device.type === deviceTypes[i]));
			}
			if (options.detectDeviceModel) {
                that.addConditionalTest(that.toCamel(device.model), true);
			}
        }

        /** Screen detection **/
        if (options.detectScreen) {
            that.addConditionalTest('smallScreen', Modernizr.mq('only screen and (max-width: 480px)'));
            that.addConditionalTest('verySmallScreen', Modernizr.mq('only screen and (max-width: 320px)'));
            that.addConditionalTest('veryVerySmallScreen', Modernizr.mq('only screen and (max-width: 240px)'));
        }

        /** OS detection **/
        if (options.detectOS) {
            if (device.model !== '') {
                if (device.model === 'ipad' || device.model === 'iphone' || device.model === 'ipod') {
					device.osVersion = (that.test(/os\s(\d+)_/) ? RegExp.$1 : '');
					device.os = 'ios';
                } else if (device.model === 'android') {
					device.osVersion = (that.test(/os\s(\d+)_/) ? RegExp.$1 : '').substr(0, 2);
					device.os = 'android';
                }
            }
			if (device.os === '') {
				if (that.is('win') || that.is('16bit')) {
					device.os = 'windows';
					if (that.is('windows nt 6.1')) {
						device.osVersion = '7';
					} else if (that.is('windows nt 6.0')) {
						device.osVersion = 'vista';
					} else if (that.is('windows nt 5.2') || that.is('windows nt 5.1') || that.is('windows xp')) {
						device.osVersion = 'xp';
					} else if (that.is('windows nt 5.0') || that.is('windows 2000')) {
						device.osVersion = '2k';
					} else if (that.is('winnt') || that.is('windows nt')) {
						device.osVersion = 'nt';
					} else if (that.is('win98') || that.is('windows 98')) {
						device.osVersion = '98';
					} else if (that.is('win95') || that.is('windows 95')) {
						device.osVersion = '95';
					}
				} else if (that.is('mac') || that.is('darwin')) {
					device.os = 'mac';
					if (that.is('68k') || that.is('68000')) {
						device.osVersion = '68k';
					} else if (that.is('ppc') || that.is('powerpc')) {
						device.osVersion = 'ppc';
					} else if (that.is('os x')) {
						device.osVersion = 'os x';
					}
				} else if (that.is('webtv')) {
					device.os = 'webtv';
				} else if (that.is('x11') || that.is('inux')) {
					device.os = 'linux';
				} else if (that.is('sunos')) {
					device.os = 'sun';
				} else if (that.is('irix')) {
					device.os = 'irix';
				} else if (that.is('freebsd')) {
					device.os = 'freebsd';
				} else if (that.is('bsd')) {
					device.os = 'bsd';
				}
			}
            if (device.os !== '') {
                that.addConditionalTest(device.os, true);
				that.addVersionTest(device.os, device.osVersion);
            }
        }

        /** Browser detection **/
        if (options.detectBrowser) {
            if (!that.test(/opera|webtv/i) && that.test(/msie\s(\d)/)) {
                device.browser = 'ie';
                device.browserVersion = (that.test(/trident\/4\.0/) ? '8' : RegExp.$1);
            } else if (that.is('firefox')) {
                device.browserEngine = 'gecko';
                device.browser = 'firefox';
                device.browserVersion = (that.test(/firefox\/(\d+(\.?\d+)*)/) ? RegExp.$1 : '').substr(0, 2);
            } else if (that.is('gecko/')) {
                device.browserEngine = 'gecko';
            } else if (that.is('opera')) {
                device.browser = 'opera';
                device.browserVersion = (that.test(/version\/(\d+)/) ? RegExp.$1 : (that.test(/opera(\s|\/)(\d+)/) ? RegExp.$2 : ''));
            } else if (that.is('konqueror')) {
                device.browser = 'konqueror';
            } else if (that.is('chrome')) {
                device.browserEngine = 'webkit';
                device.browser = 'chrome';
                device.browserVersion = (that.test(/chrome\/(\d+)/) ? RegExp.$1 : '');
            } else if (that.is('iron')) {
                device.browserEngine = 'webkit';
                device.browser = 'iron';
            } else if (that.is('applewebkit/')) {
                device.browser = 'safari';
                device.browserEngine = 'webkit';
                device.browserVersion = (that.test(/version\/(\d+)/) ? RegExp.$1 : '');
            } else if (that.is('mozilla/')) {
                device.browserEngine = 'gecko';
            }
            if (device.browser !== '') {
                that.addConditionalTest(device.browser, true);
				if (device.browserVersion !== '') {
					that.addVersionTest(device.browser, device.browserVersion);
				}
            }
			that.addConditionalTest(device.browserEngine, true);
        }
    }
	function init (){
	    if (Modernizr !== undefined) {
			Modernizr.Detectizr = Modernizr.Detectizr || {};
			Modernizr.Detectizr.device = {
				type: '',
				model: '',
				browser: '',
				browserEngine: '',
				browserVersion: '',
				os: '',
				osVersion: '',
				userAgent: (navigator.userAgent || navigator.vendor || window.opera).toLowerCase()
			};
			Modernizr.Detectizr.detect = function (settings) {
				Detectizr(settings);
			};
		}
	}
	init();
}(this, navigator));

/** Sample usages **/
// Modernizr.Detectizr.detect();
// Modernizr.Detectizr.detect({detectScreen:false});
<commit_msg>Detectizr beautified<commit_after>/*!
 * Detectizr v1.0
 * http://barisaydinoglu.github.com/Detectizr/
 * https://github.com/barisaydinoglu/Detectizr
 * Written by Baris Aydinoglu (http://baris.aydinoglu.info) - Copyright � 2012
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Inspirations:
 *  - Browser selectors in CSS - http://37signals.com/svn/archives2/browser_selectors_in_css.php
 *  - Categorizr - http://www.brettjankord.com/2012/01/16/categorizr-a-modern-device-detection-script/
*/

/*
 * Detecizr, which requires Modernizr, adds some tests to Modernizr.
 * It detects device, device model, screen size, operating system,
 * and browser details.
 * Detection of these sets are optional and can be disabled.
 *
 * Detectable device types are: tv (includes smart tv and game console),
 * mobile, tablet, and desktop. Device models of tv, mobile and tablet
 * are being detected.
 *
 * Author         Baris Aydinoglu
 */
 ;(function (window, navigator) {
    var Modernizr = window.Modernizr,
        options = {
            // option for enabling HTML classes of all features (not only the true features) to be added
            addAllFeaturesAsClass: false,
            // option for enabling detection of device
            detectDevice: true,
            // option for enabling detection of device model
            detectDeviceModel: true,
            // option for enabling detection of screen size
            detectScreen: true,
            // option for enabling detection of operating system type and version
            detectOS: true,
            // option for enabling detection of browser type and version
            detectBrowser: true
        };
    function Detectizr(opt) {
        // Create Global 'extend' method, so Detectizr does not need jQuery.extend
        var extend = function (obj, extObj) {
                if (arguments.length > 2) {
                    for (var a = 1; a < arguments.length; a++) {
                        extend(obj, arguments[a]);
                    }
                } else {
                    for (var i in extObj) {
                        obj[i] = extObj[i];
                    }
                }
                return obj;
            };
        var that = this,
            device = Modernizr.Detectizr.device,
            deviceTypes = ['tv', 'tablet', 'mobile', 'desktop'],
            i;
        options = extend({}, options, opt || {});
        // simplified and localized indexOf method as one parameter fixed as useragent
        that.is = function (key) {
            return device.userAgent.indexOf(key) > -1;
        };
        // simplified and localized regex test method as one parameter fixed as useragent
        that.test = function (regex) {
            return regex.test(device.userAgent);
        };
        // simplified and localized regex exec method as one parameter fixed as useragent
        that.exec = function (regex) {
            return regex.exec(device.userAgent);
        };
        // convert string to camelcase
        that.toCamel = function (string) {
            if (string === null || string === undefined) {
                return '';
            }
            string = string + '';
            return string.replace(/((\s|\-|\.)+[a-z0-9])/g, function ($1) {
                return $1.toUpperCase().replace(/(\s|\-|\.)/g, '');
            });
        };
        // add version test to Modernizr
        that.addVersionTest = function (mainTest, version, maxLength) {
            if (version !== null && version !== undefined && version !== '') {
                version = that.toCamel(version);
                if (version !== '') {
                    if (maxLength !== undefined && maxLength > 0) {
                        version = version.substr(0, maxLength);
                    }
                    that.addConditionalTest(mainTest + version, true);
                }
            }
        };
        // add test to Modernizr based on a conditi
        that.addConditionalTest = function (feature, test) {
            if (feature === null || feature === undefined || feature === '') {
                return;
            }
            if (options.addAllFeaturesAsClass) {
                Modernizr.addTest(feature, test);
            } else {
                test = typeof test === 'function' ? test() : test;
                if (test) {
                    Modernizr.addTest(feature, true);
                }
            }
        };

        /** Device detection **/
        if (options.detectDevice) {
            if (that.test(/GoogleTV|SmartTV|Internet.TV|NetCast|NETTV|AppleTV|boxee|Kylo|Roku|DLNADOC|CE\-HTML/i)) {
                // Check if user agent is a smart tv
                device.type = deviceTypes[0];
                device.model = "smartTv";
            } else if (that.test(/Xbox|PLAYSTATION.3|Wii/i)) {
                // Check if user agent is a game console
                device.type = deviceTypes[0];
                device.model = "gameConsole";
            } else if (that.test(/iP(a|ro)d/i)) {
                // Check if user agent is a iPad
                device.type = deviceTypes[1];
                device.model = 'ipad';
            } else if ((that.test(/tablet/i) && !that.test(/RX-34/i)) || that.test(/FOLIO/i)) {
                // Check if user agent is a Tablet
                device.type = deviceTypes[1];
            } else if (that.test(/Linux/i) && that.test(/Android/i) && !that.test(/Fennec|mobi|HTC.Magic|HTCX06HT|Nexus.One|SC-02B|fone.945/i)) {
                // Check if user agent is an Android Tablet
                device.type = deviceTypes[1];
                device.model = 'android';
            } else if (that.test(/Kindle/i) || (that.test(/Mac.OS/i) && that.test(/Silk/i))) {
                // Check if user agent is a Kindle or Kindle Fire
                device.type = deviceTypes[1];
                device.model = 'kindle';
            } else if (that.test(/GT-P10|SC-01C|SHW-M180S|SGH-T849|SCH-I800|SHW-M180L|SPH-P100|SGH-I987|zt180|HTC(.Flyer|\_Flyer)|Sprint.ATP51|ViewPad7|pandigital(sprnova|nova)|Ideos.S7|Dell.Streak.7|Advent.Vega|A101IT|A70BHT|MID7015|Next2|nook/i) || (that.test(/MB511/i) && that.test(/RUTEM/i))) {
                // Check if user agent is a pre Android 3.0 Tablet
                device.type = deviceTypes[1];
                device.model = 'android';
            } else {
                // Check if user agent is one of common mobile types
                device.model = that.exec(/iphone|ipod|android|blackberry|opera mini|opera mobi|skyfire|maemo|windows phone|palm|iemobile|symbian|symbianos|fennec|j2me/i);
                if (device.model !== null) {
                    device.type = deviceTypes[2];
                    device.model = device.model + "";
                } else {
                    device.model = "";
                    if (that.test(/BOLT|Fennec|Iris|Maemo|Minimo|Mobi|mowser|NetFront|Novarra|Prism|RX-34|Skyfire|Tear|XV6875|XV6975|Google.Wireless.Transcoder/i)) {
                        // Check if user agent is unique Mobile User Agent
                        device.type = deviceTypes[2];
                    } else if (that.test(/Opera/i) && that.test(/Windows.NT.5/i) && that.test(/HTC|Xda|Mini|Vario|SAMSUNG\-GT\-i8000|SAMSUNG\-SGH\-i9/i)) {
                        // Check if user agent is an odd Opera User Agent - http://goo.gl/nK90K
                        device.type = deviceTypes[2];
                    } else if ((that.test(/Windows.(NT|XP|ME|9)/i) && !that.test(/Phone/i)) || that.test(/Win(9|.9|NT)/i)) {
                        // Check if user agent is Windows Desktop
                        device.type = deviceTypes[3];
                    } else if (that.test(/Macintosh|PowerPC/i) && !that.test(/Silk/i)) {
                        // Check if agent is Mac Desktop
                        device.type = deviceTypes[3];
                    } else if (that.test(/Linux/i) && that.test(/X11/i)) {
                        // Check if user agent is a Linux Desktop
                        device.type = deviceTypes[3];
                    } else if (that.test(/Solaris|SunOS|BSD/i)) {
                        // Check if user agent is a Solaris, SunOS, BSD Desktop
                        device.type = deviceTypes[3];
                    } else if (that.test(/Bot|Crawler|Spider|Yahoo|ia_archiver|Covario-IDS|findlinks|DataparkSearch|larbin|Mediapartners-Google|NG-Search|Snappy|Teoma|Jeeves|TinEye/i) && !that.test(/Mobile/i)) {
                        // Check if user agent is a Desktop BOT/Crawler/Spider
                        device.type = deviceTypes[3];
                        device.model = 'crawler';
                    } else {
                        // Otherwise assume it is a Mobile Device
                        device.type = deviceTypes[2];
                    }
                }
            }
            i = deviceTypes.length;
            while (i--) {
                that.addConditionalTest(deviceTypes[i], (device.type === deviceTypes[i]));
            }
            if (options.detectDeviceModel) {
                that.addConditionalTest(that.toCamel(device.model), true);
            }
        }

        /** Screen detection **/
        if (options.detectScreen) {
            that.addConditionalTest('smallScreen', Modernizr.mq('only screen and (max-width: 480px)'));
            that.addConditionalTest('verySmallScreen', Modernizr.mq('only screen and (max-width: 320px)'));
            that.addConditionalTest('veryVerySmallScreen', Modernizr.mq('only screen and (max-width: 240px)'));
        }

        /** OS detection **/
        if (options.detectOS) {
            if (device.model !== '') {
                if (device.model === 'ipad' || device.model === 'iphone' || device.model === 'ipod') {
                    device.osVersion = (that.test(/os\s(\d+)_/) ? RegExp.$1 : '');
                    device.os = 'ios';
                } else if (device.model === 'android') {
                    device.osVersion = (that.test(/os\s(\d+)_/) ? RegExp.$1 : '').substr(0, 2);
                    device.os = 'android';
                }
            }
            if (device.os === '') {
                if (that.is('win') || that.is('16bit')) {
                    device.os = 'windows';
                    if (that.is('windows nt 6.1')) {
                        device.osVersion = '7';
                    } else if (that.is('windows nt 6.0')) {
                        device.osVersion = 'vista';
                    } else if (that.is('windows nt 5.2') || that.is('windows nt 5.1') || that.is('windows xp')) {
                        device.osVersion = 'xp';
                    } else if (that.is('windows nt 5.0') || that.is('windows 2000')) {
                        device.osVersion = '2k';
                    } else if (that.is('winnt') || that.is('windows nt')) {
                        device.osVersion = 'nt';
                    } else if (that.is('win98') || that.is('windows 98')) {
                        device.osVersion = '98';
                    } else if (that.is('win95') || that.is('windows 95')) {
                        device.osVersion = '95';
                    }
                } else if (that.is('mac') || that.is('darwin')) {
                    device.os = 'mac';
                    if (that.is('68k') || that.is('68000')) {
                        device.osVersion = '68k';
                    } else if (that.is('ppc') || that.is('powerpc')) {
                        device.osVersion = 'ppc';
                    } else if (that.is('os x')) {
                        device.osVersion = 'os x';
                    }
                } else if (that.is('webtv')) {
                    device.os = 'webtv';
                } else if (that.is('x11') || that.is('inux')) {
                    device.os = 'linux';
                } else if (that.is('sunos')) {
                    device.os = 'sun';
                } else if (that.is('irix')) {
                    device.os = 'irix';
                } else if (that.is('freebsd')) {
                    device.os = 'freebsd';
                } else if (that.is('bsd')) {
                    device.os = 'bsd';
                }
            }
            if (device.os !== '') {
                that.addConditionalTest(device.os, true);
                that.addVersionTest(device.os, device.osVersion);
            }
        }

        /** Browser detection **/
        if (options.detectBrowser) {
            if (!that.test(/opera|webtv/i) && that.test(/msie\s(\d)/)) {
                device.browser = 'ie';
                device.browserVersion = (that.test(/trident\/4\.0/) ? '8' : RegExp.$1);
            } else if (that.is('firefox')) {
                device.browserEngine = 'gecko';
                device.browser = 'firefox';
                device.browserVersion = (that.test(/firefox\/(\d+(\.?\d+)*)/) ? RegExp.$1 : '').substr(0, 2);
            } else if (that.is('gecko/')) {
                device.browserEngine = 'gecko';
            } else if (that.is('opera')) {
                device.browser = 'opera';
                device.browserVersion = (that.test(/version\/(\d+)/) ? RegExp.$1 : (that.test(/opera(\s|\/)(\d+)/) ? RegExp.$2 : ''));
            } else if (that.is('konqueror')) {
                device.browser = 'konqueror';
            } else if (that.is('chrome')) {
                device.browserEngine = 'webkit';
                device.browser = 'chrome';
                device.browserVersion = (that.test(/chrome\/(\d+)/) ? RegExp.$1 : '');
            } else if (that.is('iron')) {
                device.browserEngine = 'webkit';
                device.browser = 'iron';
            } else if (that.is('applewebkit/')) {
                device.browser = 'safari';
                device.browserEngine = 'webkit';
                device.browserVersion = (that.test(/version\/(\d+)/) ? RegExp.$1 : '');
            } else if (that.is('mozilla/')) {
                device.browserEngine = 'gecko';
            }
            if (device.browser !== '') {
                that.addConditionalTest(device.browser, true);
                if (device.browserVersion !== '') {
                    that.addVersionTest(device.browser, device.browserVersion);
                }
            }
            that.addConditionalTest(device.browserEngine, true);
        }
    }
    function init() {
        if (Modernizr !== undefined) {
            Modernizr.Detectizr = Modernizr.Detectizr || {};
            Modernizr.Detectizr.device = {
                type: '',
                model: '',
                browser: '',
                browserEngine: '',
                browserVersion: '',
                os: '',
                osVersion: '',
                userAgent: (navigator.userAgent || navigator.vendor || window.opera).toLowerCase()
            };
            Modernizr.Detectizr.detect = function (settings) {
                Detectizr(settings);
            };
        }
    }
    init();
}(this, navigator));

/** Sample usages **/
// Modernizr.Detectizr.detect();
// Modernizr.Detectizr.detect({detectScreen:false});<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var fs = require('fs-extra');
var shortid = require('shortid');
var archiver = require('archiver');
var jsonfile = require('jsonfile');
var del = require('del');
var mkdirp = require('mkdirp');
var commentParser = require('comment-parser');
var Promise = require('bluebird');
var path = require('path');
var express = require('express');
var bodyParser = require('body-parser');
var webpack = require('webpack');
var config = require('./webpack.config.dev');

var copy = Promise.promisify(fs.copy);
var readJson = Promise.promisify(fs.readJson);
var writeJson = Promise.promisify(fs.writeJson);

var app = express();
var compiler = webpack(config);

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'assets')));
app.use(express.static(path.join(__dirname, 'modules')));

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));

app.post('/download', (req, res) => {

  prepare().then((uid) => {
    let framework = req.body.framework;
    let appName = req.body.appName;
    generateFramework(framework, appName, uid).then(() => {

    });
  });

});

app.get('*', function(req, res) {
  res.sendFile(path.join(__dirname, 'index.html'));
});

app.listen(3000, 'localhost', function(err) {
  if (err) {
    console.log(err);
    return;
  }

  console.log('Listening at http://localhost:3000');
});

function generateFramework(framework, appName, uid) {
  return new Promise((resolve, reject) => {
    let dest = path.join(__dirname, 'build', uid);

    switch (framework) {
      case 'express':
        let src = path.join(__dirname, 'modules', 'express');

        copy(src, dest).then(() => {
          let packageJson = path.join(dest, 'package.json');
          readJson(packageJson).then((packageObj) => {
            packageObj.name = appName;
            writeJson(packageJson, packageObj, { spaces: 2 }).then(() => {
              console.log('done');
            });
          });
        });
        break;
      case 'hapi':
        break;
      case 'sails':
        break;
      default:
        reject('Unsupported Framework');
    }
  });
}

function generateTemplateEngine(params) {
  return new Promise(function(resolve, reject) {
    switch (params.templateEngine) {
      case 'jade':
        if (params.framework === 'express') {
          fs.readFile(__dirname + '/modules/express/app.js', function (err, data) {
            if (err) throw err;
            console.log(data);
          });
          // open app.js
          // parse comments
          // open template-engine/jade
          var parsed = commentParser.parse(data);
          console.log(parsed);
        }
        break;
      case 'handlebars':
        break;
      case 'swig':
        break;
      case 'none':
        break;
      default:
        reject('Unsupported template engine');
    }
  });
}

function generateZip(req, res) {
  return new Promise(function(resolve, reject) {
    var archive = archiver('zip');

    archive.on('error', function(err) {
      res.status(500).send(err.message);
    });

    res.on('close', function() {
      console.log('closing...')
      console.log('Archive wrote %d bytes', archive.pointer());
      return res.status(200).send('OK').end();
    });

    res.attachment('megaboilerplate-express.zip');

    archive.pipe(res);

    var files = [
      __dirname + '/modules/express/app.js',
      __dirname + '/modules/express/package.json'
    ];

    for (var i in files) {
      archive.append(fs.createReadStream(files[i]), { name: path.basename(files[i]) });
    }

    archive.finalize();
  });
}

function cleanup() {
  del(['build/**/*']);
}

function prepare() {
  return new Promise((resolve, reject) => {
    let uid = shortid.generate();
    let location = path.join(__dirname, 'build', uid);
    mkdirp(location, (err) => {
      if (err) { reject(err); }
      else { resolve(uid); }
    });
  });
}
<commit_msg>Refactored cleanup() function<commit_after>'use strict';

var _ = require('lodash');
var fs = require('fs-extra');
var shortid = require('shortid');
var archiver = require('archiver');
var jsonfile = require('jsonfile');
var commentParser = require('comment-parser');
var Promise = require('bluebird');
var path = require('path');
var express = require('express');
var bodyParser = require('body-parser');
var webpack = require('webpack');
var config = require('./webpack.config.dev');

var remove = Promise.promisify(fs.remove);
var mkdirs = Promise.promisify(fs.mkdirs);
var copy = Promise.promisify(fs.copy);
var readJson = Promise.promisify(fs.readJson);
var writeJson = Promise.promisify(fs.writeJson);

var app = express();
var compiler = webpack(config);

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'assets')));
app.use(express.static(path.join(__dirname, 'modules')));

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
}));
app.use(require('webpack-hot-middleware')(compiler));

app.post('/download', (req, res) => {
  let framework = req.body.framework;
  let appName = req.body.appName;

  prepare().then((uid) => {
    generateFramework(framework, appName, uid).then(() => {

    });
  });

});

app.get('*', function(req, res) {
  res.sendFile(path.join(__dirname, 'index.html'));
});

app.listen(3000, 'localhost', function(err) {
  if (err) {
    console.log(err);
    return;
  }

  console.log('Listening at http://localhost:3000');
});

function generateFramework(framework, appName, uid) {
  return new Promise((resolve, reject) => {
    let dest = path.join(__dirname, 'build', uid);

    switch (framework) {
      case 'express':
        let src = path.join(__dirname, 'modules', 'express');
        copy(src, dest).then(() => {
          let packageJson = path.join(dest, 'package.json');
          readJson(packageJson).then((packageObj) => {
            packageObj.name = appName;
            writeJson(packageJson, packageObj, { spaces: 2 }).then(() => {
              resolve();
            });
          });
        });
        break;
      case 'hapi':
        break;
      case 'sails':
        break;
      default:
        reject('Unsupported Framework');
    }
  });
}

function generateTemplateEngine(params) {
  return new Promise(function(resolve, reject) {
    switch (params.templateEngine) {
      case 'jade':
        if (params.framework === 'express') {
          fs.readFile(__dirname + '/modules/express/app.js', function (err, data) {
            if (err) throw err;
            console.log(data);
          });
          // open app.js
          // parse comments
          // open template-engine/jade
          var parsed = commentParser.parse(data);
          console.log(parsed);
        }
        break;
      case 'handlebars':
        break;
      case 'swig':
        break;
      case 'none':
        break;
      default:
        reject('Unsupported template engine');
    }
  });
}

function generateZip(req, res) {
  return new Promise(function(resolve, reject) {
    var archive = archiver('zip');

    archive.on('error', function(err) {
      res.status(500).send(err.message);
    });

    res.on('close', function() {
      console.log('closing...')
      console.log('Archive wrote %d bytes', archive.pointer());
      return res.status(200).send('OK').end();
    });

    res.attachment('megaboilerplate-express.zip');

    archive.pipe(res);

    var files = [
      __dirname + '/modules/express/app.js',
      __dirname + '/modules/express/package.json'
    ];

    for (var i in files) {
      archive.append(fs.createReadStream(files[i]), { name: path.basename(files[i]) });
    }

    archive.finalize();
  });
}

function cleanup(uid) {
  return new Promise((resolve, reject) => {
    let location = path.join(__dirname, 'build', uid);
    remove(location).then(() => {
      resolve();
    }).catch(() => {
      reject();
    });
  });
}

function prepare() {
  return new Promise((resolve, reject) => {
    let uid = shortid.generate();
    let location = path.join(__dirname, 'build', uid);
    mkdirs(location).then(() => {
      resolve(uid);
    }).catch((err) => {
      reject(err);
    });
  });
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";

// Start the main app logic.
requirejs(
  [ 'hft/commonui',
    'hft/gameclient',
    'hft/misc/dpad',
    'hft/misc/input',
    'hft/misc/misc',
    'hft/misc/mobilehacks',
    'hft/misc/ticker',
    'hft/misc/touch',
    '../bower_components/hft-utils/dist/audio',
    '../bower_components/hft-utils/dist/imageloader',
    '../bower_components/hft-utils/dist/imageutils',
  ],
  function(
    CommonUI,
    GameClient,
    DPad,
    Input,
    Misc,
    MobileHacks,
    Ticker,
    Touch,
    AudioManager,
    ImageLoader,
    ImageProcess) {
  var g_client;
  var g_audioManager;
  var g_clock;
  var g_grid;
  var g_instrument;
  var g_leftRight = 0;
  var g_oldLeftRight = 0;
  var g_abutton = false;

  var globals = {
    debug: false,
    forceController: false,
    orientation: "landscape-primary",
  };
  Misc.applyUrlSettings(globals);
  MobileHacks.fixHeightHack();
  MobileHacks.adjustCSSBasedOnPhone([
    {
      test: MobileHacks.isIOS8OrNewerAndiPhone4OrIPhone5,
      styles: {
        "#abutton": {
          bottom: "96px",
        },
        "#dpadleft, #abutton": {
          bottom: "90px",
        },
      },
    },
  ]);

  var $ = document.getElementById.bind(document);

  var bombsCtx = $("bombs").getContext("2d");
  var bombSizeCtx = $("bombsize").getContext("2d");
  var msgContainerStyle = $("msgcontainer").style;
  var msgText = Misc.createTextNode($("msg"));
  var msgContainerOriginalDisplay = msgContainerStyle.display;

  var flashNdx;
  var ticker = new Ticker();
  var cancelFlash = function() {
    ticker.cancel();
  };
  var flash = function(colors) {
    flashNdx = 0;
    cancelFlash();
    ticker.tick(2, 0.1, function() {
      msgContainerStyle.backgroundColor = colors[(flashNdx++) % colors.length];
    });
  };

  var showMsg = function(msg, color) {
    cancelFlash()
    msgContainerStyle.backgroundColor = color;
    msgContainerStyle.display = msgContainerOriginalDisplay;
    msgText.nodeValue = msg;
  };

  var hideMsg = function() {
    msgContainerStyle.display = "none";
  };

  var images = {
    tiles0:  { url: "assets/bomb_party-00.png", },
  };
  var avatarTileId = 0x0101;
  var bombTileId   = 0x0504;
  var flameTileIds = [
    0x0501, // flameH,
    0x0500, // flameL,
    0x0503, // flameR,
  ];

  var startClient = function() {
    var cutTile = function(xy, ii, size) {
      var tx = (((xy >> 0) & 0xFF)     );
      var ty = (((xy >> 8) & 0xFF) + ii);
      var img = ImageProcess.cropImage(images.tiles0.img, tx * 16, ty * 16, 16, 16);
      return img = ImageProcess.scaleImage(img, size, size);
    };

    images.avatars = [];
    for (var ii = 0; ii < 4; ++ii) {
      images.avatars.push(cutTile(avatarTileId, ii, 128));
    }
    images.bomb = cutTile(bombTileId, 0, 16);
    images.flames = [];
    for (var ii = 0; ii < flameTileIds.length; ++ii) {
      images.flames.push(cutTile(flameTileIds[ii], 0, 16));
    }

    g_client = new GameClient();

    var handleScore = function() {
    };

    var handleDeath = function() {
      showMsg("DEAD!", "red");
      flash(["red", "yellow"]);
    };

    var handleWinner = function() {
      showMsg("WINNER!!!", "yellow");
      flash(["green", "blue", "purple", "red", "orange", "yellow", "purple"]);
    };

    var handleTie = function() {
      showMsg("tie", "green");
    };

    var handleWaitForStart = function(data) {
      showMsg("Start In: " + data.waitTime, "blue");
    };

    var handleWaitForNextGame = function(data) {
      showMsg("Please Wait For Next Game", "orange");
    };

    var handleWaitForMorePlayers = function(data) {
      showMsg("Please Wait For More Players", "orange");
    };

    var handleStart = function() {
      hideMsg();
    };

    var handleSpoil = function() {
      hideMsg();
    };

    var handleSetColor = function(msg) {
      var canvas = $("avatar");
      var width = canvas.clientWidth;
      var height = canvas.clientHeight;
      canvas.width = width;
      canvas.height = height;
      var ctx = canvas.getContext("2d");
      var frame = ImageProcess.adjustHSV(images.avatars[msg.set], msg.hsv[0], msg.hsv[1], msg.hsv[2]);
      ctx.drawImage(frame, 0, 0);
    };

    var handleNumBombs = function(msg) {
      Misc.resize(bombsCtx.canvas);
      bombsCtx.clearRect(0, 0, bombsCtx.canvas.width, bombsCtx.canvas.height);
      for (var ii = 0; ii < msg.numBombs; ++ii) {
        bombsCtx.drawImage(images.bomb, ii * 16, 0);
      }
    };

    var handleBombSize = function(msg) {
      Misc.resize(bombSizeCtx.canvas);
      bombSizeCtx.clearRect(0, 0, bombSizeCtx.canvas.width, bombSizeCtx.canvas.height);
      bombSizeCtx.drawImage(images.flames[1], 0, 0);
      for (var ii = 1; ii <= msg.size; ++ii) {
        bombSizeCtx.drawImage(images.flames[0], ii * 16, 0);
      }
      bombSizeCtx.drawImage(images.flames[2], ii * 16, 0);
    };

    if (globals.forceController) {
      hideMsg();
    } else {
      // These messages hide/show the controller so don't handle them
      // if we're testing the controller with `forceController`
      g_client.addEventListener('score', handleScore);
      g_client.addEventListener('start', handleStart);
      g_client.addEventListener('tied', handleTie);
      g_client.addEventListener('died', handleDeath);
      g_client.addEventListener('spoil', handleSpoil);
      g_client.addEventListener('winner', handleWinner);
      g_client.addEventListener('waitForStart', handleWaitForStart);
      g_client.addEventListener('waitForNextGame', handleWaitForNextGame);
      g_client.addEventListener('waitForMorePlayers', handleWaitForMorePlayers);
    }
    g_client.addEventListener('numBombs', handleNumBombs);
    g_client.addEventListener('bombSize', handleBombSize);
    g_client.addEventListener('setColor', handleSetColor);

    var sounds = {};
    g_audioManager = new AudioManager(sounds);

    CommonUI.setupStandardControllerUI(g_client, globals);

    var dpads = [
      new DPad({element: $("dpadleft")}),
    ];
    var dpadSize = dpads[0].getSize();

    var handleAbutton = function(pressed) {
      if (g_abutton != pressed) {
        g_abutton = pressed;
        g_client.sendCmd('abutton', {
            abutton: pressed,
        });
      }
    };

    var handleShow = function(pressed) {
      g_client.sendCmd('show', {show:pressed});
    };

    var handleDPad = function(e) {
      dpads[e.pad].draw(e.info);
      g_client.sendCmd('pad', {pad: e.pad, dir: e.info.direction});
    };

    var keys = { };
    keys["Z".charCodeAt(0)] = function(e) { handleAbutton(e.pressed); }
    keys["X".charCodeAt(0)] = function(e) { handleShow(e.pressed); }
    Input.setupKeys(keys);
    Input.setupKeyboardDPadKeys(handleDPad, Input.kASWDPadOnly);

    Touch.setupButtons({
      inputElement: $("buttons"),
      buttons: [
        { element: $("abuttoninput"), callback: function(e) { handleAbutton(e.pressed); }, },
        { element: $("avatarinput"),  callback: function(e) { handleShow(e.pressed); }, },
      ],
    });

    Touch.setupVirtualDPads({
      inputElement: $("dpadleftinput"),
      callback: handleDPad,
      fixedCenter: true,
      deadSpaceRadius: 0,
      divisions: 4,
      pads: [
        {
          referenceElement: $("dpadleft"),
          offsetX: dpadSize / 2,
          offsetY: dpadSize / 2,
        },
      ],
    });
  };

  ImageLoader.loadImages(images, startClient);
});

<commit_msg>remove offset from dpad<commit_after>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";

// Start the main app logic.
requirejs(
  [ 'hft/commonui',
    'hft/gameclient',
    'hft/misc/dpad',
    'hft/misc/input',
    'hft/misc/misc',
    'hft/misc/mobilehacks',
    'hft/misc/ticker',
    'hft/misc/touch',
    '../bower_components/hft-utils/dist/audio',
    '../bower_components/hft-utils/dist/imageloader',
    '../bower_components/hft-utils/dist/imageutils',
  ],
  function(
    CommonUI,
    GameClient,
    DPad,
    Input,
    Misc,
    MobileHacks,
    Ticker,
    Touch,
    AudioManager,
    ImageLoader,
    ImageProcess) {
  var g_client;
  var g_audioManager;
  var g_clock;
  var g_grid;
  var g_instrument;
  var g_leftRight = 0;
  var g_oldLeftRight = 0;
  var g_abutton = false;

  var globals = {
    debug: false,
    forceController: false,
    orientation: "landscape-primary",
  };
  Misc.applyUrlSettings(globals);
  MobileHacks.fixHeightHack();
  MobileHacks.adjustCSSBasedOnPhone([
    {
      test: MobileHacks.isIOS8OrNewerAndiPhone4OrIPhone5,
      styles: {
        "#abutton": {
          bottom: "96px",
        },
        "#dpadleft, #abutton": {
          bottom: "90px",
        },
      },
    },
  ]);

  var $ = document.getElementById.bind(document);

  var bombsCtx = $("bombs").getContext("2d");
  var bombSizeCtx = $("bombsize").getContext("2d");
  var msgContainerStyle = $("msgcontainer").style;
  var msgText = Misc.createTextNode($("msg"));
  var msgContainerOriginalDisplay = msgContainerStyle.display;

  var flashNdx;
  var ticker = new Ticker();
  var cancelFlash = function() {
    ticker.cancel();
  };
  var flash = function(colors) {
    flashNdx = 0;
    cancelFlash();
    ticker.tick(2, 0.1, function() {
      msgContainerStyle.backgroundColor = colors[(flashNdx++) % colors.length];
    });
  };

  var showMsg = function(msg, color) {
    cancelFlash()
    msgContainerStyle.backgroundColor = color;
    msgContainerStyle.display = msgContainerOriginalDisplay;
    msgText.nodeValue = msg;
  };

  var hideMsg = function() {
    msgContainerStyle.display = "none";
  };

  var images = {
    tiles0:  { url: "assets/bomb_party-00.png", },
  };
  var avatarTileId = 0x0101;
  var bombTileId   = 0x0504;
  var flameTileIds = [
    0x0501, // flameH,
    0x0500, // flameL,
    0x0503, // flameR,
  ];

  var startClient = function() {
    var cutTile = function(xy, ii, size) {
      var tx = (((xy >> 0) & 0xFF)     );
      var ty = (((xy >> 8) & 0xFF) + ii);
      var img = ImageProcess.cropImage(images.tiles0.img, tx * 16, ty * 16, 16, 16);
      return img = ImageProcess.scaleImage(img, size, size);
    };

    images.avatars = [];
    for (var ii = 0; ii < 4; ++ii) {
      images.avatars.push(cutTile(avatarTileId, ii, 128));
    }
    images.bomb = cutTile(bombTileId, 0, 16);
    images.flames = [];
    for (var ii = 0; ii < flameTileIds.length; ++ii) {
      images.flames.push(cutTile(flameTileIds[ii], 0, 16));
    }

    g_client = new GameClient();

    var handleScore = function() {
    };

    var handleDeath = function() {
      showMsg("DEAD!", "red");
      flash(["red", "yellow"]);
    };

    var handleWinner = function() {
      showMsg("WINNER!!!", "yellow");
      flash(["green", "blue", "purple", "red", "orange", "yellow", "purple"]);
    };

    var handleTie = function() {
      showMsg("tie", "green");
    };

    var handleWaitForStart = function(data) {
      showMsg("Start In: " + data.waitTime, "blue");
    };

    var handleWaitForNextGame = function(data) {
      showMsg("Please Wait For Next Game", "orange");
    };

    var handleWaitForMorePlayers = function(data) {
      showMsg("Please Wait For More Players", "orange");
    };

    var handleStart = function() {
      hideMsg();
    };

    var handleSpoil = function() {
      hideMsg();
    };

    var handleSetColor = function(msg) {
      var canvas = $("avatar");
      var width = canvas.clientWidth;
      var height = canvas.clientHeight;
      canvas.width = width;
      canvas.height = height;
      var ctx = canvas.getContext("2d");
      var frame = ImageProcess.adjustHSV(images.avatars[msg.set], msg.hsv[0], msg.hsv[1], msg.hsv[2]);
      ctx.drawImage(frame, 0, 0);
    };

    var handleNumBombs = function(msg) {
      Misc.resize(bombsCtx.canvas);
      bombsCtx.clearRect(0, 0, bombsCtx.canvas.width, bombsCtx.canvas.height);
      for (var ii = 0; ii < msg.numBombs; ++ii) {
        bombsCtx.drawImage(images.bomb, ii * 16, 0);
      }
    };

    var handleBombSize = function(msg) {
      Misc.resize(bombSizeCtx.canvas);
      bombSizeCtx.clearRect(0, 0, bombSizeCtx.canvas.width, bombSizeCtx.canvas.height);
      bombSizeCtx.drawImage(images.flames[1], 0, 0);
      for (var ii = 1; ii <= msg.size; ++ii) {
        bombSizeCtx.drawImage(images.flames[0], ii * 16, 0);
      }
      bombSizeCtx.drawImage(images.flames[2], ii * 16, 0);
    };

    if (globals.forceController) {
      hideMsg();
    } else {
      // These messages hide/show the controller so don't handle them
      // if we're testing the controller with `forceController`
      g_client.addEventListener('score', handleScore);
      g_client.addEventListener('start', handleStart);
      g_client.addEventListener('tied', handleTie);
      g_client.addEventListener('died', handleDeath);
      g_client.addEventListener('spoil', handleSpoil);
      g_client.addEventListener('winner', handleWinner);
      g_client.addEventListener('waitForStart', handleWaitForStart);
      g_client.addEventListener('waitForNextGame', handleWaitForNextGame);
      g_client.addEventListener('waitForMorePlayers', handleWaitForMorePlayers);
    }
    g_client.addEventListener('numBombs', handleNumBombs);
    g_client.addEventListener('bombSize', handleBombSize);
    g_client.addEventListener('setColor', handleSetColor);

    var sounds = {};
    g_audioManager = new AudioManager(sounds);

    CommonUI.setupStandardControllerUI(g_client, globals);

    var dpads = [
      new DPad({element: $("dpadleft")}),
    ];

    var handleAbutton = function(pressed) {
      if (g_abutton != pressed) {
        g_abutton = pressed;
        g_client.sendCmd('abutton', {
            abutton: pressed,
        });
      }
    };

    var handleShow = function(pressed) {
      g_client.sendCmd('show', {show:pressed});
    };

    var handleDPad = function(e) {
      dpads[e.pad].draw(e.info);
      g_client.sendCmd('pad', {pad: e.pad, dir: e.info.direction});
    };

    var keys = { };
    keys["Z".charCodeAt(0)] = function(e) { handleAbutton(e.pressed); }
    keys["X".charCodeAt(0)] = function(e) { handleShow(e.pressed); }
    Input.setupKeys(keys);
    Input.setupKeyboardDPadKeys(handleDPad, Input.kASWDPadOnly);

    Touch.setupButtons({
      inputElement: $("buttons"),
      buttons: [
        { element: $("abuttoninput"), callback: function(e) { handleAbutton(e.pressed); }, },
        { element: $("avatarinput"),  callback: function(e) { handleShow(e.pressed); }, },
      ],
    });

    Touch.setupVirtualDPads({
      inputElement: $("dpadleftinput"),
      callback: handleDPad,
      fixedCenter: true,
      deadSpaceRadius: 0,
      divisions: 4,
      pads: [
        {
          referenceElement: $("dpadleft"),
        },
      ],
    });
  };

  ImageLoader.loadImages(images, startClient);
});

<|endoftext|>