Working with webpack

This commit is contained in:
2016-02-28 12:55:24 +08:00
parent e1306cf35a
commit 56f2e7d8a7
35 changed files with 413 additions and 2826 deletions
+2 -1
View File
@@ -1,5 +1,6 @@
/** Custom google analystics events **/
var analytics =
var Helpers = require("js/helpers");
var analytics = module.exports =
{
enabled: true,
+29 -29
View File
@@ -2,46 +2,44 @@
* Define the angular app
*/
'use strict';
var app = (function () {
var ObjectStorage = require("js/storage");
var Helpers = require("js/helpers");
var GameObjects = require("js/gameobjects");
var analytics = require("js/analytics");
var Game = require("js/game");
var Rules = require("js/rules.js");
var app = (function (Helpers,analytics,Game,Rules) {
Helpers.validateSaveVersion();
var app = angular.module('scienceAlchemy', ['ngDragDrop', 'ui.grid','ngAnimate']);
var app = angular.module('scienceAlchemy', ['ngDragDrop','ngAnimate']);
// directives
/**
* Provides an easy way to toggle a checkboxes indeterminate property
*
* @example <input type="checkbox" ui-indeterminate="isUnkown">
*/
// app.directive('uiIndeterminate', [
// function () {
//
// return {
// compile: function (tElm, tAttrs) {
// if (!tAttrs.type || tAttrs.type.toLowerCase() !== 'checkbox') {
// return angular.noop;
// }
//
// return function ($scope, elm, attrs) {
// $scope.$watch(attrs.uiIndeterminate, function (newVal) {
// elm[0].indeterminate = !!newVal;
// });
// };
// }
// };
// }
// ]);
/**
* Make little score animations when score changes require ng-model="score"
* Make little "+2" "-1" score animations when score changes requires ng-model="score"
* Associated css:
* ```
* .update-value { // set constant height, and the position
position: relative;
right: -2em;
top: -1.42857em;
height: 1.42857em;
}
.update-plus { // if the change is +ve
color: green;
position: relative;
}
.update-minus {
color: red;
position: relative;
}
*/
function cfsScoreChange($compile) {
return {
link: function (scope, element, attrs) {
scope.$watch(attrs.ngModel, function (newValue, oldValue) {
console.log('value changed, new value is: ' + newValue, oldValue);
// showUpdateValue
var num = newValue-oldValue;
var formatted = Helpers.formatNumberPostfix(num);
@@ -56,6 +54,7 @@ var app = (function () {
.html(formatted);
}
// TODO it would be better to use an ::after element for this
// showUpdate
element.append(insert);
insert.animate({
@@ -416,4 +415,5 @@ var app = (function () {
analytics.init();
analytics.sendScreen(analytics.screens.main);
})();
})(Helpers,analytics,Game,Rules);
module.exports=app;
-127
View File
@@ -1,127 +0,0 @@
/** Manages the detector animation in the canvas of the detector pane **/
var Detector = function(){
return {
elements: new GameObjects.Cards(),
lastCards: new GameObjects.Cards(),
incorrectCards: new GameObjects.Cards(),
visible: true,
width: 400,
height: 400,
ratio: 1,
lastRender: 0,
bubblr: undefined,
init: function(game)
{
// deal first card
this.lastCards.push(_.sample(game.elements));
},
/** When a user clicks the detector **/
addEvent: function()
{
// this.bubblr.bubble(); // bubble for 500ms, TODO make one bubble
},
/** When a worker clicks the detector **/
addEventExternal: function(numWorkers)
{
// this.bubblr.genBubbles(numWorkers);
},
/** Draw current events **/
draw: function(duration)
{
// this.bubblr.bubble();
},
onDrop: function(event, ui, game){
var self=this;
console.debug('onDrop',arguments);
var $draggable = angular.element(ui.draggable),
$droppable = angular.element(event.target);
// if the dragger came from the elements panels, clone it to here
var newElement;
if ($draggable.hasClass('element-store')){
var elementStore = game.elements.filter(function(e){return e.key==$draggable.data('element');})[0];
elementStore.state.amount-=1;
newElement = angular.copy(elementStore);
this.elements.push(newElement);
}
var observation = game.test
console.log('intersectingElements', intersectingElements.length, observation);
return observation;
},
/** Run an experiment depending on reactants and conditions **/
experiment: function(options,game) {
var inputs = options.inputs || [];
var inputKeys = inputs.map(function(e){return e.key;});
inputKeys.sort(); // this makes reaction be independant of order
var result = game.testRules(inputKeys);
if (result) {
this.reaction(inputs,result.reactants,result.results, options.location, game);
} else {
result = {
reactants: [],
catalysts: [],
conditions: [],
results: [],
inputs: inputKeys
};
}
return result;
},
/** Remove reactants and make results with animations **/
reaction: function(inputs,reactants,results,location,game){
// remove reactants from detector
for (var i = 0; i < reactants.length; i++) {
// get the uuid from inputs
var ingredient = inputs.filter(function(e){return e.key===reactants[i];})[0];
var j = _.findIndex(this.elements,{uuid:ingredient.uuid});
var removed = this.elements.splice(j,1);
}
// TODO use angular effects to remove in puff of fade
// add results and discover them
for (var i = 0; i < results.length; i++) {
var resultKey = results[i];
// make sure it's discovered
var elementStore = game.elements.get(resultKey);
if (!elementStore.state.discovered){
// old discoveries are not interesting
game.elements.map(function(e){e.state.interesting=false;});
// a new discovery is interesting
elementStore.state.interesting=true;
elementStore.state.discovered=true;
}
// add new element to beaker
var newElem = elementStore.spawn();
newElem.state=location;
this.elements.push(newElem);
}
// effects
// this.bubblr.bubble();
},
};
};
-989
View File
@@ -1,989 +0,0 @@
/*!!
* Canvas 2 Svg v1.0.6
* A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document.
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Author:
* Kerry Liu
*
* Copyright (c) 2014 Gliffy Inc.
*/
;(function() {
"use strict";
var STYLES, ctx, CanvasGradient, CanvasPattern, namedEntities;
//helper function to format a string
function format(str, args) {
var keys = Object.keys(args), i;
for (i=0; i<keys.length; i++) {
str = str.replace(new RegExp("\\{" + keys[i] + "\\}", "gi"), args[keys[i]]);
}
return str;
}
//helper function that generates a random string
function randomString(holder) {
var chars, randomstring, i;
if (!holder) {
throw new Error("cannot create a random attribute name for an undefined object");
}
chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
randomstring = "";
do {
randomstring = "";
for (i = 0; i < 12; i++) {
randomstring += chars[Math.floor(Math.random() * chars.length)];
}
} while (holder[randomstring]);
return randomstring;
}
//helper function to map named to numbered entities
function createNamedToNumberedLookup(items, radix) {
var i, entity, lookup = {}, base10, base16;
items = items.split(',');
radix = radix || 10;
// Map from named to numbered entities.
for (i = 0; i < items.length; i += 2) {
entity = '&' + items[i + 1] + ';';
base10 = parseInt(items[i], radix);
lookup[entity] = '&#'+base10+';';
}
//FF and IE need to create a regex from hex values ie &nbsp; == \xa0
lookup["\\xa0"] = '&#160;';
return lookup;
}
//helper function to map canvas-textAlign to svg-textAnchor
function getTextAnchor(textAlign) {
//TODO: support rtl languages
var mapping = {"left":"start", "right":"end", "center":"middle", "start":"start", "end":"end"};
return mapping[textAlign] || mapping.start;
}
//helper function to map canvas-textBaseline to svg-dominantBaseline
function getDominantBaseline(textBaseline) {
//INFO: not supported in all browsers
var mapping = {"alphabetic": "alphabetic", "hanging": "hanging", "top":"text-before-edge", "bottom":"text-after-edge", "middle":"central"};
return mapping[textBaseline] || mapping.alphabetic;
}
// Unpack entities lookup where the numbers are in radix 32 to reduce the size
// entity mapping courtesy of tinymce
namedEntities = createNamedToNumberedLookup(
'50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
'5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
'5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
'5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
'68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
'6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
'6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
'75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
'7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
'7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
'81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
'8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
'8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
'8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
'8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
'80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
'811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro', 32);
//Some basic mappings for attributes and default values.
STYLES = {
"strokeStyle":{
svgAttr : "stroke", //corresponding svg attribute
canvas : "#000000", //canvas default
svg : "none", //svg default
apply : "stroke" //apply on stroke() or fill()
},
"fillStyle":{
svgAttr : "fill",
canvas : "#000000",
svg : null, //svg default is black, but we need to special case this to handle canvas stroke without fill
apply : "fill"
},
"lineCap":{
svgAttr : "stroke-linecap",
canvas : "butt",
svg : "butt",
apply : "stroke"
},
"lineJoin":{
svgAttr : "stroke-linejoin",
canvas : "miter",
svg : "miter",
apply : "stroke"
},
"miterLimit":{
svgAttr : "stroke-miterlimit",
canvas : 10,
svg : 4,
apply : "stroke"
},
"lineWidth":{
svgAttr : "stroke-width",
canvas : 1,
svg : 1,
apply : "stroke"
},
"globalAlpha": {
svgAttr : "opacity",
canvas : 1,
svg : 1,
apply : "fill stroke"
},
"font":{
//font converts to multiple svg attributes, there is custom logic for this
canvas : "10px sans-serif"
},
"shadowColor":{
canvas : "#000000"
},
"shadowOffsetX":{
canvas : 0
},
"shadowOffsetY":{
canvas : 0
},
"shadowBlur":{
canvas : 0
},
"textAlign":{
canvas : "start"
},
"textBaseline":{
canvas : "alphabetic"
}
};
/**
*
* @param gradientNode - reference to the gradient
* @constructor
*/
CanvasGradient = function(gradientNode) {
this.__root = gradientNode;
};
/**
* Adds a color stop to the gradient root
*/
CanvasGradient.prototype.addColorStop = function(offset, color) {
var stop = document.createElementNS("http://www.w3.org/2000/svg", "stop"), regex, matches;
stop.setAttribute("offset", offset);
if(color.indexOf("rgba") !== -1) {
//separate alpha value, since webkit can't handle it
regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi;
matches = regex.exec(color);
stop.setAttribute("stop-color", format("rgb({r},{g},{b})", {r:matches[1], g:matches[2], b:matches[3]}));
stop.setAttribute("stop-opacity", matches[4]);
} else {
stop.setAttribute("stop-color", color);
}
this.__root.appendChild(stop);
};
CanvasPattern = function(pattern, ctx) {
this.__root = pattern;
this.__ctx = ctx;
};
/**
* The mock canvas context
* @param o - options include:
* width - width of your canvas (defaults to 500)
* height - height of your canvas (defaults to 500)
* enableMirroring - enables canvas mirroring (get image data) (defaults to false)
*/
ctx = function(o) {
var defaultOptions = { width:500, height:500, enableMirroring : false }, options;
//keep support for this way of calling C2S: new C2S(width,height)
if(arguments.length > 1) {
options = defaultOptions;
options.width = arguments[0];
options.height = arguments[1];
} else if( !o ) {
options = defaultOptions;
} else {
options = o;
}
if(!(this instanceof ctx)) {
//did someone call this without new?
return new ctx(options);
}
//setup options
this.width = options.width || defaultOptions.width;
this.height = options.height || defaultOptions.height;
this.enableMirroring = options.enableMirroring !== undefined ? options.enableMirroring : defaultOptions.enableMirroring;
this.canvas = this; ///point back to this instance!
this.__canvas = document.createElement("canvas");
this.__ctx = this.__canvas.getContext("2d");
this.__setDefaultStyles();
this.__stack = [this.__getStyleState()];
this.__groupStack = [];
//the root svg element
this.__root = document.createElementNS("http://www.w3.org/2000/svg", "svg");
this.__root.setAttribute("version", 1.1);
this.__root.setAttribute("xmlns", "http://www.w3.org/2000/svg");
this.__root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
this.__root.setAttribute("width", this.width);
this.__root.setAttribute("height", this.height);
//make sure we don't generate the same ids in defs
this.__ids = {};
//defs tag
this.__defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
this.__root.appendChild(this.__defs);
//also add a group child. the svg element can't use the transform attribute
this.__currentElement = document.createElementNS("http://www.w3.org/2000/svg", "g");
this.__root.appendChild(this.__currentElement);
};
/**
* Creates the specified svg element
* @private
*/
ctx.prototype.__createElement = function(elementName, properties, resetFill) {
var element = document.createElementNS("http://www.w3.org/2000/svg", elementName),
keys = Object.keys(properties), i, key;
if(resetFill) {
//if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black.
element.setAttribute("fill", "none");
element.setAttribute("stroke", "none");
}
for(i=0; i<keys.length; i++) {
key = keys[i];
element.setAttribute(key, properties[key]);
}
return element;
};
/**
* Applies default canvas styles to the context
* @private
*/
ctx.prototype.__setDefaultStyles = function() {
//default 2d canvas context properties see:http://www.w3.org/TR/2dcontext/
var keys = Object.keys(STYLES), i, key;
for(i=0; i<keys.length; i++) {
key = keys[i];
this[key] = STYLES[key].canvas;
}
};
/**
* Applies styles on restore
* @param styleState
* @private
*/
ctx.prototype.__applyStyleState = function(styleState) {
var keys = Object.keys(styleState), i, key;
for(i=0; i<keys.length; i++) {
key = keys[i];
this[key] = styleState[key];
}
};
/**
* Gets the current style state
* @return {Object}
* @private
*/
ctx.prototype.__getStyleState = function() {
var i, styleState = {}, keys = Object.keys(STYLES), key;
for(i=0; i<keys.length; i++) {
key = keys[i];
styleState[key] = this[key];
}
return styleState;
};
/**
* Apples the current styles to the current SVG element. On "ctx.fill" or "ctx.stroke"
* @param type
* @private
*/
ctx.prototype.__applyStyleToCurrentElement = function(type) {
var keys = Object.keys(STYLES), i, style, value, id, regex, matches;
for(i=0; i<keys.length; i++) {
style = STYLES[keys[i]];
value = this[keys[i]];
if(style.apply) {
//is this a gradient or pattern?
if(style.apply.indexOf("fill")!==-1 && value instanceof CanvasPattern) {
//pattern
if(value.__ctx) {
//copy over defs
while(value.__ctx.__defs.childNodes.length) {
id = value.__ctx.__defs.childNodes[0].getAttribute("id");
this.__ids[id] = id;
this.__defs.appendChild(value.__ctx.__defs.childNodes[0]);
}
}
this.__currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
}
else if(style.apply.indexOf("fill")!==-1 && value instanceof CanvasGradient) {
//gradient
this.__currentElement.setAttribute("fill", format("url(#{id})", {id:value.__root.getAttribute("id")}));
} else if(style.apply.indexOf(type)!==-1 && style.svg !== value) {
if((style.svgAttr === "stroke" || style.svgAttr === "fill") && value.indexOf("rgba") !== -1) {
//separate alpha value, since illustrator can't handle it
regex = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?\.?\d*)\s*\)/gi;
matches = regex.exec(value);
this.__currentElement.setAttribute(style.svgAttr, format("rgb({r},{g},{b})", {r:matches[1], g:matches[2], b:matches[3]}));
this.__currentElement.setAttribute(style.svgAttr+"-opacity", matches[4]);
} else {
//otherwise only update attribute if right type, and not svg default
this.__currentElement.setAttribute(style.svgAttr, value);
}
}
}
}
};
/**
* Will return the closest group or svg node. May return the current element.
* @private
*/
ctx.prototype.__closestGroupOrSvg = function(node) {
node = node || this.__currentElement;
if(node.nodeName === "g" || node.nodeName === "svg") {
return node;
} else {
return this.__closestGroupOrSvg(node.parentNode);
}
};
/**
* Returns the serialized value of the svg so far
* @param fixNamedEntities - Standalone SVG doesn't support named entities, which document.createTextNode encodes.
* If true, we attempt to find all named entities and encode it as a numeric entity.
* @return serialized svg
*/
ctx.prototype.getSerializedSvg = function(fixNamedEntities) {
var serialized = new XMLSerializer().serializeToString(this.__root),
keys, i, key, value, regexp, xmlns;
//IE search for a duplicate xmnls because they didn't implement setAttributeNS correctly
xmlns = /xmlns="http:\/\/www\.w3\.org\/2000\/svg".+xmlns="http:\/\/www\.w3\.org\/2000\/svg/gi;
if(xmlns.test(serialized)) {
serialized = serialized.replace('xmlns="http://www.w3.org/2000/svg','xmlns:xlink="http://www.w3.org/1999/xlink');
}
if(fixNamedEntities) {
keys = Object.keys(namedEntities);
//loop over each named entity and replace with the proper equivalent.
for(i=0; i<keys.length; i++) {
key = keys[i];
value = namedEntities[key];
regexp = new RegExp(key, "gi");
if(regexp.test(serialized)) {
serialized = serialized.replace(regexp, value);
}
}
}
return serialized;
};
/**
* Returns the root svg
* @return
*/
ctx.prototype.getSvg = function() {
return this.__root;
};
/**
* Will generate a group tag.
*/
ctx.prototype.save = function() {
var group = document.createElementNS("http://www.w3.org/2000/svg", "g"), parent = this.__closestGroupOrSvg();
this.__groupStack.push(parent);
parent.appendChild(group);
this.__currentElement = group;
this.__stack.push(this.__getStyleState());
};
/**
* Sets current element to parent, or just root if already root
*/
ctx.prototype.restore = function(){
this.__currentElement = this.__groupStack.pop();
var state = this.__stack.pop();
this.__applyStyleState(state);
};
/**
* Helper method to add transform
* @private
*/
ctx.prototype.__addTransform = function(t) {
var transform = this.__currentElement.getAttribute("transform");
if(transform) {
transform += " ";
} else {
transform = "";
}
transform += t;
this.__currentElement.setAttribute("transform", transform);
};
/**
* scales the current element
*/
ctx.prototype.scale = function(x, y) {
if(y === undefined) {
y = x;
}
this.__addTransform(format("scale({x},{y})", {x:x, y:y}));
};
/**
* rotates the current element
*/
ctx.prototype.rotate = function(angle){
var degrees = (angle * 180 / Math.PI);
this.__addTransform(format("rotate({angle},{cx},{cy})", {angle:degrees, cx:0, cy:0}));
};
/**
* translates the current element
*/
ctx.prototype.translate = function(x, y){
this.__addTransform(format("translate({x},{y})", {x:x,y:y}));
};
/**
* applies a transform to the current element
*/
ctx.prototype.transform = function(a, b, c, d, e, f){
this.__addTransform(format("matrix({a},{b},{c},{d},{e},{f})", {a:a, b:b, c:c, d:d, e:e, f:f}));
};
/**
* Create a new Path Element
*/
ctx.prototype.beginPath = function(){
var path, parent;
path = this.__createElement("path", {}, true);
parent = this.__closestGroupOrSvg();
parent.appendChild(path);
this.__currentElement = path;
};
/**
* Helper function to add path command
* @private
*/
ctx.prototype.__addPathCommand = function(command){
if(this.__currentElement.nodeName === "path") {
var d = this.__currentElement.getAttribute("d");
if(d) {
d += " ";
} else {
d = "";
}
d += command;
this.__currentElement.setAttribute("d", d);
} else {
throw new Error("Attempted to add path command to node " + this.__currentElement.nodeName);
}
};
/**
* Adds the move command to the current path element,
* if the currentPathElement is not empty create a new path element
*/
ctx.prototype.moveTo = function(x,y){
if(this.__currentElement.nodeName !== "path") {
this.beginPath();
}
this.__addPathCommand(format("M {x} {y}", {x:x, y:y}));
};
/**
* Closes the current path
*/
ctx.prototype.closePath = function(){
this.__addPathCommand("Z");
};
/**
* Adds a line to command
*/
ctx.prototype.lineTo = function(x, y){
this.__addPathCommand(format("L {x} {y}", {x:x, y:y}));
};
/**
* Add a bezier command
*/
ctx.prototype.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
this.__addPathCommand(format("C {cp1x} {cp1y} {cp2x} {cp2y} {x} {y}",
{cp1x:cp1x, cp1y:cp1y, cp2x:cp2x, cp2y:cp2y, x:x, y:y}));
};
/**
* Adds a quadratic curve to command
*/
ctx.prototype.quadraticCurveTo = function(cpx, cpy, x, y){
this.__addPathCommand(format("Q {cpx} {cpy} {x} {y}", {cpx:cpx, cpy:cpy, x:x, y:y}));
};
/**
* Sets the stroke property on the current element
*/
ctx.prototype.stroke = function(){
this.__applyStyleToCurrentElement("stroke");
};
/**
* Sets fill properties on the current element
*/
ctx.prototype.fill = function(){
this.__applyStyleToCurrentElement("fill");
};
/**
* Adds a rectangle to the path.
*/
ctx.prototype.rect = function(x, y, width, height){
if(this.__currentElement.nodeName !== "path") {
this.beginPath();
}
this.moveTo(x, y);
this.lineTo(x+width, y);
this.lineTo(x+width, y+height);
this.lineTo(x, y+height);
this.lineTo(x, y);
this.closePath();
};
/**
* adds a rectangle element
*/
ctx.prototype.fillRect = function(x, y, width, height){
var rect, parent;
rect = this.__createElement("rect", {
x : x,
y : y,
width : width,
height : height
}, true);
parent = this.__closestGroupOrSvg();
parent.appendChild(rect);
this.__currentElement = rect;
this.__applyStyleToCurrentElement("fill");
};
/**
* Draws a rectangle with no fill
* @param x
* @param y
* @param width
* @param height
*/
ctx.prototype.strokeRect = function(x, y, width, height){
var rect, parent;
rect = this.__createElement("rect", {
x : x,
y : y,
width : width,
height : height
}, true);
parent = this.__closestGroupOrSvg();
parent.appendChild(rect);
this.__currentElement = rect;
this.__applyStyleToCurrentElement("stroke");
};
/**
* "Clears" a canvas by just drawing a white rectangle in the current group.
*/
ctx.prototype.clearRect = function(x, y, width, height) {
var rect, parent = this.__closestGroupOrSvg();
rect = this.__createElement("rect", {
x : x,
y : y,
width : width,
height : height,
fill : "#FFFFFF"
}, true);
parent.appendChild(rect);
};
/**
* Adds a linear gradient to a defs tag.
* Returns a canvas gradient object that has a reference to it's parent def
*/
ctx.prototype.createLinearGradient = function(x1, y1, x2, y2){
var grad = this.__createElement("linearGradient", {
id : randomString(this.__ids),
x1 : x1+"px",
x2 : x2+"px",
y1 : y1+"px",
y2 : y2+"px",
"gradientUnits" : "userSpaceOnUse"
}, false);
this.__defs.appendChild(grad);
return new CanvasGradient(grad);
};
/**
* Adds a radial gradient to a defs tag.
* Returns a canvas gradient object that has a reference to it's parent def
*/
ctx.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){
var grad = this.__createElement("radialGradient", {
id : randomString(this.__ids),
cx : x1+"px",
cy : y1+"px",
r : r1+"px",
fx : x0+"px",
fy : y0+"px",
"gradientUnits" : "userSpaceOnUse"
}, false);
this.__defs.appendChild(grad);
return new CanvasGradient(grad);
};
/**
* Parses the font string and returns svg mapping
* @private
*/
ctx.prototype.__parseFont = function() {
var font = this.font, parts, token, index = 0, data = {
style : "normal",
size : "10px",
family : "sans-serif",
weight: "normal",
decoration : "none", //underline | none
href : null
};
//canvas doesn't support underline natively, but we can pass this attribute
if(this.__fontUnderline === "underline") {
data.decoration = "underline";
}
//canvas also doesn't support linking, but we can pass this as well
if(this.__fontHref) {
data.href = this.__fontHref;
}
parts = font.split(" ");
token = parts[index];
//text decoration
while(/italic|bold|normal/.test(token)) {
if(token === "bold") {
data.weight = token; //[normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit]
} else {
data.style = token; //[normal / italic /oblique /inherit]
}
//advance to next token
index++;
token = parts[index];
}
//next token should be font size
if(/em|px|pt|%/.test(token)) {
data.size = token;
index++;
}
//font family?
parts.splice(0, index);
data.family = parts.join(" ");
return data;
};
/**
* Helper to link text fragments
* @param font
* @param element
* @return {*}
* @private
*/
ctx.prototype.__wrapTextLink = function(font, element) {
if(font.href) {
var a = document.createElementNS("http://www.w3.org/2000/svg", "a");
a.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", font.href);
a.appendChild(element);
return a;
}
return element;
};
/**
* Fills or strokes text
* @param text
* @param x
* @param y
* @param action - stroke or fill
* @private
*/
ctx.prototype.__applyText = function(text, x, y, action) {
var font = this.__parseFont(),
parent = this.__closestGroupOrSvg(),
textElement = this.__createElement("text", {
"font-family" : font.family,
"font-size" : font.size,
"font-style" : font.style,
"font-weight" : font.weight,
"text-decoration" : font.decoration,
"x" : x,
"y" : y,
"text-anchor": getTextAnchor(this.textAlign),
"dominant-baseline": getDominantBaseline(this.textBaseline)
}, true);
textElement.appendChild(document.createTextNode(text));
this.__currentElement = textElement;
this.__applyStyleToCurrentElement(action);
parent.appendChild(this.__wrapTextLink(font,textElement));
};
/**
* Creates a text element
* @param text
* @param x
* @param y
*/
ctx.prototype.fillText = function(text, x, y){
this.__applyText(text, x, y, "fill");
};
/**
* Strokes text
* @param text
* @param x
* @param y
*/
ctx.prototype.strokeText = function(text, x, y){
this.__applyText(text, x, y, "stroke");
};
/**
* No need to implement this for svg.
* @param text
* @return {TextMetrics}
*/
ctx.prototype.measureText = function(text){
this.__ctx.font = this.font;
return this.__ctx.measureText(text);
};
/**
* Arc command!
*/
ctx.prototype.arc = function(x, y, radius, startAngle, endAngle, counterClockwise) {
startAngle = startAngle % (2*Math.PI);
endAngle = endAngle % (2*Math.PI);
if(startAngle === endAngle) {
//circle time! subtract some of the angle so svg is happy (svg elliptical arc can't draw a full circle)
endAngle = ((endAngle + (2*Math.PI)) - 0.001 * (counterClockwise ? -1 : 1)) % (2*Math.PI);
}
var endX = x+radius*Math.cos(endAngle),
endY = y+radius*Math.sin(endAngle),
startX = x+radius*Math.cos(startAngle),
startY = y+radius*Math.sin(startAngle),
sweepFlag = counterClockwise ? 0 : 1,
largeArcFlag = 0,
diff = endAngle - startAngle;
// https://github.com/gliffy/canvas2svg/issues/4
if(diff < 0) {
diff += 2*Math.PI;
}
if(counterClockwise) {
largeArcFlag = diff > Math.PI ? 0 : 1;
} else {
largeArcFlag = diff > Math.PI ? 1 : 0;
}
this.moveTo(startX, startY);
this.__addPathCommand(format("A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}",
{rx:radius, ry:radius, xAxisRotation:0, largeArcFlag:largeArcFlag, sweepFlag:sweepFlag, endX:endX, endY:endY}));
};
/**
* Generates a ClipPath from the clip command.
*/
ctx.prototype.clip = function(){
var group = this.__closestGroupOrSvg(),
clipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath"),
id = randomString(this.__ids),
newGroup = document.createElementNS("http://www.w3.org/2000/svg", "g");
group.removeChild(this.__currentElement);
clipPath.setAttribute("id", id);
clipPath.appendChild(this.__currentElement);
this.__defs.appendChild(clipPath);
//set the clip path to this group
group.setAttribute("clip-path", format("url(#{id})", {id:id}));
//clip paths can be scaled and transformed, we need to add another wrapper group to avoid later transformations
// to this path
group.appendChild(newGroup);
this.__currentElement = newGroup;
};
/**
* Draws a canvas, image or mock context to this canvas.
* Note that all svg dom manipulation uses node.childNodes rather than node.children for IE support.
* http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage
*/
ctx.prototype.drawImage = function(){
//convert arguments to a real array
var args = Array.prototype.slice.call(arguments),
image=args[0],
dx, dy, dw, dh, sx=0, sy=0, sw, sh, parent, svg, defs, group,
currentElement, svgImage, canvas, context, id;
if(args.length === 3) {
dx = args[1];
dy = args[2];
sw = image.width;
sh = image.height;
dw = sw;
dh = sh;
} else if(args.length === 5) {
dx = args[1];
dy = args[2];
dw = args[3];
dh = args[4];
sw = image.width;
sh = image.height;
} else if(args.length === 9) {
sx = args[1];
sy = args[2];
sw = args[3];
sh = args[4];
dx = args[5];
dy = args[6];
dw = args[7];
dh = args[8];
} else {
throw new Error("Inavlid number of arguments passed to drawImage: " + arguments.length);
}
parent = this.__closestGroupOrSvg();
currentElement = this.__currentElement;
if(image instanceof ctx) {
//canvas2svg mock canvas context. In the future we may want to clone nodes instead.
//also I'm currently ignoring dw, dh, sw, sh, sx, sy for a mock context.
svg = image.getSvg();
defs = svg.childNodes[0];
while(defs.childNodes.length) {
id = defs.childNodes[0].getAttribute("id");
this.__ids[id] = id;
this.__defs.appendChild(defs.childNodes[0]);
}
group = svg.childNodes[1];
parent.appendChild(group);
this.__currentElement = group;
this.translate(dx, dy);
this.__currentElement = currentElement;
} else if(image.nodeName === "CANVAS" || image.nodeName === "IMG") {
//canvas or image
svgImage = document.createElementNS("http://www.w3.org/2000/svg", "image");
svgImage.setAttribute("width", dw);
svgImage.setAttribute("height", dh);
svgImage.setAttribute("preserveAspectRatio", "none");
if(sx || sy || sw !== image.width || sh !== image.height) {
//crop the image using a temporary canvas
canvas = document.createElement("canvas");
canvas.width = dw;
canvas.height = dh;
context = canvas.getContext("2d");
context.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh);
image = canvas;
}
svgImage.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href",
image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src"));
parent.appendChild(svgImage);
this.__currentElement = svgImage;
this.translate(dx, dy);
this.__currentElement = currentElement;
}
};
/**
* Generates a pattern tag
*/
ctx.prototype.createPattern = function(image, repetition){
var pattern = document.createElementNS("http://www.w3.org/2000/svg", "pattern"), id = randomString(this.__ids),
img;
pattern.setAttribute("id", id);
pattern.setAttribute("width", image.width);
pattern.setAttribute("height", image.height);
if(image.nodeName === "CANVAS" || image.nodeName === "IMG") {
img = document.createElementNS("http://www.w3.org/2000/svg", "image");
img.setAttribute("width", image.width);
img.setAttribute("height", image.height);
img.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href",
image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src"));
pattern.appendChild(img);
this.__defs.appendChild(pattern);
} else if(image instanceof ctx) {
pattern.appendChild(image.__root.childNodes[1]);
this.__defs.appendChild(pattern);
}
return new CanvasPattern(pattern, this);
};
/**
* Not yet implemented
*/
ctx.prototype.drawFocusRing = function(){};
ctx.prototype.createImageData = function(){};
ctx.prototype.getImageData = function(){};
ctx.prototype.putImageData = function(){};
ctx.prototype.globalCompositeOperation = function(){};
ctx.prototype.arcTo = function(){};
ctx.prototype.setTransform = function(){};
//add options for alternative namespace
window.C2S = ctx;
}());
-196
View File
@@ -1,196 +0,0 @@
/*!
* Retina.js v1.3.0
*
* Copyright 2014 Imulus, LLC
* Released under the MIT license
*
* Retina.js is an open source script that makes it easy to serve
* high-resolution images to devices with retina displays.
*/
(function() {
var root = (typeof exports === 'undefined' ? window : exports);
var config = {
// An option to choose a suffix for 2x images
retinaImageSuffix : '@2x',
// Ensure Content-Type is an image before trying to load @2x image
// https://github.com/imulus/retinajs/pull/45)
check_mime_type: true,
// Resize high-resolution images to original image's pixel dimensions
// https://github.com/imulus/retinajs/issues/8
force_original_dimensions: true
};
function Retina() {}
root.Retina = Retina;
Retina.configure = function(options) {
if (options === null) {
options = {};
}
for (var prop in options) {
if (options.hasOwnProperty(prop)) {
config[prop] = options[prop];
}
}
};
Retina.init = function(context) {
if (context === null) {
context = root;
}
var existing_onload = context.onload || function(){};
context.onload = function() {
var images = document.getElementsByTagName('img'), retinaImages = [], i, image;
for (i = 0; i < images.length; i += 1) {
image = images[i];
if (!!!image.getAttributeNode('data-no-retina')) {
image.setAttribute('data-at2x-loaded', true);
retinaImages.push(new RetinaImage(image));
}
}
existing_onload();
};
};
Retina.recheck = function() {
var images = document.getElementsByTagName('img'), retinaImages = [], i, image;
for (i = 0; i < images.length; i += 1) {
image = images[i];
if (!!!image.getAttributeNode('data-no-retina')) {
if (!!!image.getAttributeNode('data-at2x-loaded')) {
image.setAttribute('data-at2x-loaded', true);
retinaImages.push(new RetinaImage(image));
}
}
}
};
Retina.isRetina = function(){
var mediaQuery = '(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)';
if (root.devicePixelRatio > 1) {
return true;
}
if (root.matchMedia && root.matchMedia(mediaQuery).matches) {
return true;
}
return false;
};
var regexMatch = /\.\w+$/;
function suffixReplace (match) {
return config.retinaImageSuffix + match;
}
function RetinaImagePath(path, at_2x_path) {
this.path = path || '';
if (typeof at_2x_path !== 'undefined' && at_2x_path !== null) {
this.at_2x_path = at_2x_path;
this.perform_check = false;
} else {
if (undefined !== document.createElement) {
var locationObject = document.createElement('a');
locationObject.href = this.path;
locationObject.pathname = locationObject.pathname.replace(regexMatch, suffixReplace);
this.at_2x_path = locationObject.href;
} else {
var parts = this.path.split('?');
parts[0] = parts[0].replace(regexMatch, suffixReplace);
this.at_2x_path = parts.join('?');
}
this.perform_check = true;
}
}
root.RetinaImagePath = RetinaImagePath;
RetinaImagePath.confirmed_paths = [];
RetinaImagePath.prototype.is_external = function() {
return !!(this.path.match(/^https?\:/i) && !this.path.match('//' + document.domain) );
};
RetinaImagePath.prototype.check_2x_variant = function(callback) {
var http, that = this;
if (this.is_external()) {
return callback(false);
} else if (!this.perform_check && typeof this.at_2x_path !== 'undefined' && this.at_2x_path !== null) {
return callback(true);
} else if (this.at_2x_path in RetinaImagePath.confirmed_paths) {
return callback(true);
} else {
http = new XMLHttpRequest();
http.open('HEAD', this.at_2x_path);
http.onreadystatechange = function() {
if (http.readyState !== 4) {
return callback(false);
}
if (http.status >= 200 && http.status <= 399) {
if (config.check_mime_type) {
var type = http.getResponseHeader('Content-Type');
if (type === null || !type.match(/^image/i)) {
return callback(false);
}
}
RetinaImagePath.confirmed_paths.push(that.at_2x_path);
return callback(true);
} else {
return callback(false);
}
};
http.send();
}
};
function RetinaImage(el) {
this.el = el;
this.path = new RetinaImagePath(this.el.getAttribute('src'), this.el.getAttribute('data-at2x'));
var that = this;
this.path.check_2x_variant(function(hasVariant) {
if (hasVariant) {
that.swap();
}
});
}
root.RetinaImage = RetinaImage;
RetinaImage.prototype.swap = function(path) {
if (typeof path === 'undefined') {
path = this.path.at_2x_path;
}
var that = this;
function load() {
if (! that.el.complete) {
setTimeout(load, 5);
} else {
if (config.force_original_dimensions) {
that.el.setAttribute('width', that.el.width);
that.el.setAttribute('height', that.el.height);
}
that.el.setAttribute('src', path);
}
}
load();
};
if (Retina.isRetina()) {
Retina.init(root);
}
})();
+6 -2
View File
@@ -1,7 +1,11 @@
/**
* Game object load/saves game resources and stores game objects
*/
var Game = (function (Helpers, GameObjects, ObjectStorage) {
var ObjectStorage = require("js/storage");
var Helpers = require("js/helpers");
var GameObjects = require("js/gameobjects");
var Rules = require("js/rules.js");
var Game = module.exports =(function (Helpers, GameObjects, ObjectStorage,Rules) {
'use strict';
var Game = function () {
@@ -193,4 +197,4 @@ var Game = (function (Helpers, GameObjects, ObjectStorage) {
};
return Game;
}(Helpers, GameObjects, ObjectStorage));
}(Helpers, GameObjects, ObjectStorage,Rules));
+1 -1
View File
@@ -2,7 +2,7 @@
* Game objects such as workers, research, upgrades, and achievements.
*/
var GameObjects = (function () {
var GameObjects = module.exports = (function () {
'use strict';
var GLOBAL_VISIBILITY_THRESHOLD = 0.5;
+4 -2
View File
@@ -1,7 +1,8 @@
/** @module Helpers
* Define some useful helpers that are used throughout the game.
*/
var Helpers = (function () {
var ObjectStorage = require("js/storage");
var Helpers = (function (ObjectStorage) {
'use strict';
/** Load a file (usually JSON).
*/
@@ -100,4 +101,5 @@ var Helpers = (function () {
validateSaveVersion: validateSaveVersion,
analytics: ''
};
})();
})(ObjectStorage);
module.exports=Helpers;
+4 -3
View File
@@ -3,7 +3,8 @@
* @param {[type]} function functionName( [description]
* @return {[type]} [description]
*/
var Rules = (function functionName(_) {
var chai = require("chai");
var Rules = module.exports = (function functionName(_,chai) {
@@ -250,7 +251,7 @@ var Rules = (function functionName(_) {
};
/** How many combination of this rule **/
Rule.prototype.combinations = function (arguments) {
Rule.prototype.combinations = function () {
var pos = _.map(this.optionDesc, 'possibleVals');
var c = 0;
for (var i = 0; i < pos.length; i++) {
@@ -577,4 +578,4 @@ var Rules = (function functionName(_) {
};
})(_);
})(_,chai);
+1 -1
View File
@@ -1,7 +1,7 @@
/** Allows to save objects to HTML5 local storage.
* However, it can only save properties, not functions.
*/
var ObjectStorage = (function() {
var ObjectStorage = module.exports = (function() {
'use strict';
try {
var _s = localStorage;
+44 -42
View File
@@ -2,7 +2,9 @@
/** Define UI specific stuff.
*/
var UI = (function () {
var FastClick = require("fastclick");
var Cookies = require("js-cookie");
var UI = module.exports = (function (FastClick,Cookies) {
/** Introduce FastClick for faster clicking on mobile.
*/
$(function() {
@@ -84,7 +86,7 @@ var UI = (function () {
}
// display cookie warning
if (typeof $.cookie('cookielaw') === 'undefined') {
if (typeof Cookies.get('cookielaw') === 'undefined') {
var alert = '<div id="cookielaw" class="alert alert-info" role="alert">';
alert += '<button type="button" class="btn btn-primary">OK</button>';
alert += '<i class="fa fa-info-circle alert-glyph"></i> <span class="alert-text">Particle Clicker uses local storage to store your current progress.</span>';
@@ -92,7 +94,7 @@ var UI = (function () {
alert = $(alert);
alert.find('button').click(function ()
{
$.cookie('cookielaw', 'informed', { expires: 365 });
Cookies.set('cookielaw', 'informed', { expires: 365 });
$('#cookielaw').slideUp(300, function() { $('#cookielaw').remove(); });
})
@@ -100,7 +102,7 @@ var UI = (function () {
}
// display new user alert
// if (typeof $.cookie('cern60') === 'undefined') {
// if (typeof Cookies.get('cern60') === 'undefined') {
// var alert = '<div id="cern60" class="alert alert-info" role="alert">';
// alert += '<button type="button" class="btn btn-primary">Close</button>';
// alert += '<i class="fa fa-area-chart alert-glyph"></i> <span class="alert-text"><a class="alert-link" href="http://home.web.cern.ch/about/updates/2014/12/take-part-cern-60-public-computing-challenge" target="_blank">Join the CERN 60 computing challenge!</a></span>';
@@ -108,7 +110,7 @@ var UI = (function () {
// alert = $(alert);
// alert.find('button').click(function ()
// {
// $.cookie('cern60', 'closed', { expires: 365 });
// Cookies.set('cern60', 'closed', { expires: 365 });
// $('#cern60').slideUp(300, function() { $('#cern60').remove(); });
// })
//
@@ -120,41 +122,41 @@ var UI = (function () {
showModal: showModal,
showLevels: showLevels,
showUpdateValue: showUpdateValue
}
})();
};
})(FastClick,Cookies);
// I don't know what this is for, so I leave it here for the moment...
(function() {
var hidden = "hidden";
// Standards:
if (hidden in document)
document.addEventListener("visibilitychange", onchange);
else if ((hidden = "mozHidden") in document)
document.addEventListener("mozvisibilitychange", onchange);
else if ((hidden = "webkitHidden") in document)
document.addEventListener("webkitvisibilitychange", onchange);
else if ((hidden = "msHidden") in document)
document.addEventListener("msvisibilitychange", onchange);
// IE 9 and lower:
else if ('onfocusin' in document)
document.onfocusin = document.onfocusout = onchange;
// All others:
else
window.onpageshow = window.onpagehide
= window.onfocus = window.onblur = onchange;
function onchange (evt) {
var v = 'visible', h = 'hidden',
evtMap = {
focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
};
evt = evt || window.event;
if (evt.type in evtMap)
detector.visible = evtMap[evt.type] == 'visible';
else
detector.visible = !this[hidden];
}
})();
//
// // I don't know what this is for, so I leave it here for the moment...
// (function() {
// var hidden = "hidden";
//
// // Standards:
// if (hidden in document)
// document.addEventListener("visibilitychange", onchange);
// else if ((hidden = "mozHidden") in document)
// document.addEventListener("mozvisibilitychange", onchange);
// else if ((hidden = "webkitHidden") in document)
// document.addEventListener("webkitvisibilitychange", onchange);
// else if ((hidden = "msHidden") in document)
// document.addEventListener("msvisibilitychange", onchange);
// // IE 9 and lower:
// else if ('onfocusin' in document)
// document.onfocusin = document.onfocusout = onchange;
// // All others:
// else
// window.onpageshow = window.onpagehide
// = window.onfocus = window.onblur = onchange;
//
// function onchange (evt) {
// var v = 'visible', h = 'hidden',
// evtMap = {
// focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
// };
//
// evt = evt || window.event;
// if (evt.type in evtMap)
// detector.visible = evtMap[evt.type] == 'visible';
// else
// detector.visible = !this[hidden];
// }
// })();