<commit_before>var htmlparser = require('htmlparser2');
var https = require('https');
var models = require('../models/index');

const FladeService = {};

FladeService.getAndSaveCurrentFlade = function(callback){
  isFladeFromToday(function(fromToday){
    if(!fromToday){
      updateFlade(callback);
    } else {
      FladeService.getCurrentFlade(callback);
    }
  });
};

function isFladeFromToday(callback){
  FladeService.getCurrentFlade(function(flade){
    if(!flade){
      callback(false);
    } else {
      callback(new Date(flade.timestamp).toDateString() === new Date().toDateString());
    }
  })
}

function updateFlade(callback){
  https.get({
    host: 'fladerei.com',
    path: '/dyn_inhalte/tagesflade.html'
  }, function(res){
    var content = '';
    res.setEncoding('utf8');
    res.on('data', function (chunk) {
      content += chunk;
    });
    res.on('end', function(){
      parseContentToFlade(content, function(result){
        updateCurrentFlade(result, callback);
      });
    });
  });
}

function parseContentToFlade(content, callback){
  var berggasse = false;
  var tagesflade = false;
  var Parser = new htmlparser.Parser({

    onopentag: function(name, attribs){
      if(name === 'a' && attribs.href.indexOf('berggasse') !== -1){
        berggasse = true;
      } else if (name === 'span' && berggasse){
        tagesflade = true;
      }
    },
    ontext: function(text){
      if(tagesflade){
        callback(text.replace(/ /gi,''));
      }
    },
    onclosetag: function(tagname){
      if(tagname === 'span' && berggasse && tagesflade){
        berggasse = tagesflade = false;
      }
    }
  });

  Parser.write(content);
  Parser.end();
}

function updateCurrentFlade(text, callback){
  models.Flade.remove({}, function(){
    var flade = new models.Flade({
      text: text,
      timestamp: new Date()
    });
    flade.save(function(err, flade){
      callback(flade);
    });
  });
}

FladeService.getCurrentFlade = function(callback){
  models.Flade.findOne({}).then(function(flade){
    callback(flade);
  })
};

module.exports = FladeService;
<commit_msg>Fixed flade<commit_after>var htmlparser = require('htmlparser2');
var https = require('https');
var models = require('../models/index');

const FladeService = {};

FladeService.getAndSaveCurrentFlade = function(callback){
  isFladeFromToday(function(fromToday){
    if(!fromToday){
      updateFlade(callback);
    } else {
      FladeService.getCurrentFlade(callback);
    }
  });
};

function isFladeFromToday(callback){
  FladeService.getCurrentFlade(function(flade){
    if(!flade){
      callback(false);
    } else {
      callback(new Date(flade.timestamp).toDateString() === new Date().toDateString());
    }
  })
}

function updateFlade(callback){
  https.get({
    host: 'fladerei.com',
    path: '/dyn_inhalte/tagesflade.html'
  }, function(res){
    var content = '';
    res.setEncoding('utf8');
    res.on('data', function (chunk) {
      content += chunk;
    });
    res.on('end', function(){
      parseContentToFlade(content, function(result){
<<<<<<< HEAD
        updateCurrentFlade(result, callback);
=======
        var flade = new models.Flade({
          text: result,
          timestamp: new Date()
        });
        flade.save(function(err, flade){
          callback && callback(flade);
        });
>>>>>>> 08534a09fe73e1255a4b6fb23cab31625be27cc6
      });
    });
  });
}

function parseContentToFlade(content, callback){
  var berggasse = false;
  var tagesflade = false;
  var Parser = new htmlparser.Parser({

    onopentag: function(name, attribs){
      if(name === 'a' && attribs.href.indexOf('berggasse') !== -1){
        berggasse = true;
      } else if (name === 'span' && berggasse){
        tagesflade = true;
      }
    },
    ontext: function(text){
      if(tagesflade){
        callback(text.replace(/ /gi,''));
      }
    },
    onclosetag: function(tagname){
      if(tagname === 'span' && berggasse && tagesflade){
        berggasse = tagesflade = false;
      }
    }
  });

  Parser.write(content);
  Parser.end();
}

function updateCurrentFlade(text, callback){
  models.Flade.remove({}, function(){
    var flade = new models.Flade({
      text: text,
      timestamp: new Date()
    });
    flade.save(function(err, flade){
      callback(flade);
    });
  });
}

FladeService.getCurrentFlade = function(callback){
  models.Flade.findOne({}).then(function(flade){
    callback && callback(flade);
  })
};

module.exports = FladeService;
<|endoftext|>


<commit_before>/**
  Copyright 2019 Google LLC

  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

      https://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.

*/
const {
  Given,
  When,
  Then,
  After
} = require('cucumber')
const puppeteer = require('puppeteer')
const org = process.env.APIGEE_ORG
const env = process.env.APIGEE_ENV

Given('I navigate to the authorize page', async function() {
  this.browser = await puppeteer.launch()
  this.page = await this.browser.newPage()
  return await this.page.goto('https://' + org + '-' + env +
    '.apigee.net/mock-idp/auth?client_id=' + this.apickli.scenarioVariables.clientId
    + '&redirect_uri=https://httpbin.org/get&response_type=code&scope=openid&state=123')
})

When('I sign in and consent', async function() {
  //fill in login page
  await this.page.click('#login')
  await this.page.keyboard.type('user@example.com')
  await this.page.click('#password')
  await this.page.keyboard.type('password')

  //submit
  await Promise.all([
    this.page.click('#submit'),
    this.page.waitForNavigation()
  ])

  //return submit
  return await Promise.all([
    this.page.click('#submit'),
    this.page.waitForNavigation()
  ])

})

Then('I am redirected to the TPP', function(cb) {
  cb(this.page.url().indexOf('https://httpbin.org/get') === -1)

})

Then('I receive an auth code in a query param',  function(cb) {
  cb(this.page.url().indexOf('code=') === -1)
})

Then('I store the auth code in global scope', async function() {
  this.apickli.setGlobalVariable('authCode',
    new URL(this.page.url()).searchParams.get('code'))
})

After(async function() {
  if (this.browser) this.browser.close()
})

<commit_msg>used client id from global variables<commit_after>/**
  Copyright 2019 Google LLC

  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

      https://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.

*/
const {
  Given,
  When,
  Then,
  After
} = require('cucumber')
const puppeteer = require('puppeteer')
const org = process.env.APIGEE_ORG
const env = process.env.APIGEE_ENV

Given('I navigate to the authorize page', async function() {
  this.browser = await puppeteer.launch()
  this.page = await this.browser.newPage()
  return await this.page.goto('https://' + org + '-' + env +
    '.apigee.net/mock-idp/auth?client_id=' + this.apickli.globalVariables.clientId
    + '&redirect_uri=https://httpbin.org/get&response_type=code&scope=openid&state=123')
})

When('I sign in and consent', async function() {
  //fill in login page
  await this.page.click('#login')
  await this.page.keyboard.type('user@example.com')
  await this.page.click('#password')
  await this.page.keyboard.type('password')

  //submit
  await Promise.all([
    this.page.click('#submit'),
    this.page.waitForNavigation()
  ])

  //return submit
  return await Promise.all([
    this.page.click('#submit'),
    this.page.waitForNavigation()
  ])

})

Then('I am redirected to the TPP', function(cb) {
  cb(this.page.url().indexOf('https://httpbin.org/get') === -1)

})

Then('I receive an auth code in a query param',  function(cb) {
  cb(this.page.url().indexOf('code=') === -1)
})

Then('I store the auth code in global scope', async function() {
  this.apickli.setGlobalVariable('authCode',
    new URL(this.page.url()).searchParams.get('code'))
})

After(async function() {
  if (this.browser) this.browser.close()
})

<|endoftext|>


<commit_before>// Copyright 2013-2016, University of Colorado Boulder

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

// use chipper's gruntfile
const Gruntfile = require( '../chipper/js/grunt/Gruntfile.js' ); // eslint-disable-line require-statement-match

// Add repo-specific grunt tasks
module.exports = function( grunt ) {
  'use strict';

  grunt.registerTask( 'generate-svgPath-parser',
    'Uses js/parser/svgPath.pegjs to generate js/parser/svgPath.js',
    function() {
      const pegInput = fs.readFileSync( 'js/parser/svgPath.pegjs', 'utf8' );
      let source = pegjs.buildParser( pegInput ).toSource();

      // replace fixed strings at the start/end with our prefix/suffix, so that it will work nicely with require.js
      const prefix = '/' + '*\n' +
                   ' * NOTE: Generated from svgPath.pegjs using PEG.js, with added kite namespace and require.js compatibility.\n' +
                   ' * See svgPath.pegjs for more documentation, or run \'grunt generate-svgPath-parser\' to regenerate.\n' +
                   ' *' + '/\n' +
                   '\n' +
                   'define( require => {\n' +
                   '  const kite = require( \'KITE/kite\' );\n';
      const suffix = '  kite.register( \'svgPath\', result );\n' +
                   '  return kite.svgPath;\n' +
                   '} );\n';
      const toStripFromStart = '(function(){';
      const toStrimFromEnd = '  return result;\n})()';

      const startIndex = source.indexOf( toStripFromStart );
      if ( startIndex !== 0 ) {
        throw new Error( 'Could not find string to strip from the beginning of the PEG.js output' );
      }
      source = prefix + source.substring( startIndex + toStripFromStart.length );

      const endIndex = source.lastIndexOf( toStrimFromEnd );
      if ( endIndex === -1 ) {
        throw new Error( 'Could not find string to strip from the end of the PEG.js output' );
      }
      source = source.substring( 0, endIndex ) + suffix;

      // write the output
      fs.writeFileSync( 'js/parser/svgPath.js', source, 'utf8' );

      console.log( 'Please reformat the generated svgPath.js before checking in!' );
    } );

  Gruntfile( grunt );
};
<commit_msg>Updating require.js documentation and associated linting/build changes, see https://github.com/phetsims/chipper/issues/905<commit_after>// Copyright 2013-2016, University of Colorado Boulder

/* eslint-env node */

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

// use chipper's gruntfile
const Gruntfile = require( '../chipper/js/grunt/Gruntfile.js' ); // eslint-disable-line require-statement-match

// Add repo-specific grunt tasks
module.exports = function( grunt ) {
  'use strict';

  grunt.registerTask( 'generate-svgPath-parser',
    'Uses js/parser/svgPath.pegjs to generate js/parser/svgPath.js',
    function() {
      const pegInput = fs.readFileSync( 'js/parser/svgPath.pegjs', 'utf8' );
      let source = pegjs.buildParser( pegInput ).toSource();

      // replace fixed strings at the start/end with our prefix/suffix, so that it will work nicely with require.js
      const prefix = '/' + '*\n' +
                   ' * NOTE: Generated from svgPath.pegjs using PEG.js, with added kite namespace and require.js compatibility.\n' +
                   ' * See svgPath.pegjs for more documentation, or run \'grunt generate-svgPath-parser\' to regenerate.\n' +
                   ' *' + '/\n' +
                   '\n' +
                   'define( require => {\n' +
                   '  const kite = require( \'KITE/kite\' );\n';
      const suffix = '  kite.register( \'svgPath\', result );\n' +
                   '  return kite.svgPath;\n' +
                   '} );\n';
      const toStripFromStart = '(function(){';
      const toStrimFromEnd = '  return result;\n})()';

      const startIndex = source.indexOf( toStripFromStart );
      if ( startIndex !== 0 ) {
        throw new Error( 'Could not find string to strip from the beginning of the PEG.js output' );
      }
      source = prefix + source.substring( startIndex + toStripFromStart.length );

      const endIndex = source.lastIndexOf( toStrimFromEnd );
      if ( endIndex === -1 ) {
        throw new Error( 'Could not find string to strip from the end of the PEG.js output' );
      }
      source = source.substring( 0, endIndex ) + suffix;

      // write the output
      fs.writeFileSync( 'js/parser/svgPath.js', source, 'utf8' );

      console.log( 'Please reformat the generated svgPath.js before checking in!' );
    } );

  Gruntfile( grunt );
};
<|endoftext|>


<commit_before>'use strict';
const n = require('numeric');

module.exports = {
  defaultLambda: 1,

  objective(w, xVals, yVals, lambda) {
    const localLambda = lambda || this.defaultLambda;
    return n.sum(n.pow(n.sub(yVals, n.dot(xVals, w)), 2)) +
      (localLambda * n.dot(w, w) * 0.5);
  },

  oneShot(xVals, yVals, initialMVals) {
    const localInitialMVals = initialMVals || n.random(n.dim(xVals[0]));
    console.log('xVals are:',xVals);
    console.log('yVals are:',yVals);
    console.log('localInitialMVals are:',localInitialMVals);
    return n.uncmin(w => this.objective(w, xVals, yVals), localInitialMVals,0.01).solution;
  },

  rSquared(xVals,yVals,betaVector) {
   const SSresidual=n.sum(n.pow(n.sub(yVals,n.dot(xVals,betaVector)),2));
   const meanyVals=n.sum(yVals)/yVals.length;
   const SStotal=n.sum(n.pow(n.sub(yVals,n.rep(n.dim(yVals),meanyVals)),2));
   return  1-(SSresidual/SStotal);
  },

  tValue(xVals,yVals,betaVector) {
   const varError=(1/(n.dim(yVals)-2))*(n.sum(n.pow(n.sub(yVals, n.dot(xVals, betaVector)), 2)));
   var varBeta=n.mul(n.inv(n.dot(n.transpose(xVals),xVals)),varError);
   // initialize seBeta list
   const seBeta=[];
   for (let i=0; i<betaVector.length; i += 1) {
    seBeta.push(Math.sqrt(varBeta[i][i]));
    }
   //calcualte the T value from seBeta
   const tValue=[];
   for (let i=0; i<betaVector.length; i += 1) {
     tValue.push(betaVector[i]/seBeta[i]);
   }
   return tValue;
  },

}
<commit_msg>change tol to 0.001<commit_after>'use strict';
const n = require('numeric');

module.exports = {
  defaultLambda: 1,

  objective(w, xVals, yVals, lambda) {
    const localLambda = lambda || this.defaultLambda;
    return n.sum(n.pow(n.sub(yVals, n.dot(xVals, w)), 2)) +
      (localLambda * n.dot(w, w) * 0.5);
  },

  oneShot(xVals, yVals, initialMVals) {
    const localInitialMVals = initialMVals || n.random(n.dim(xVals[0]));
    console.log('xVals are:',xVals);
    console.log('yVals are:',yVals);
    console.log('localInitialMVals are:',localInitialMVals);
    return n.uncmin(w => this.objective(w, xVals, yVals), localInitialMVals,0.001).solution;
  },

  rSquared(xVals,yVals,betaVector) {
   const SSresidual=n.sum(n.pow(n.sub(yVals,n.dot(xVals,betaVector)),2));
   const meanyVals=n.sum(yVals)/yVals.length;
   const SStotal=n.sum(n.pow(n.sub(yVals,n.rep(n.dim(yVals),meanyVals)),2));
   return  1-(SSresidual/SStotal);
  },

  tValue(xVals,yVals,betaVector) {
   const varError=(1/(n.dim(yVals)-2))*(n.sum(n.pow(n.sub(yVals, n.dot(xVals, betaVector)), 2)));
   var varBeta=n.mul(n.inv(n.dot(n.transpose(xVals),xVals)),varError);
   // initialize seBeta list
   const seBeta=[];
   for (let i=0; i<betaVector.length; i += 1) {
    seBeta.push(Math.sqrt(varBeta[i][i]));
    }
   //calcualte the T value from seBeta
   const tValue=[];
   for (let i=0; i<betaVector.length; i += 1) {
     tValue.push(betaVector[i]/seBeta[i]);
   }
   return tValue;
  },

}
<|endoftext|>


<commit_before>define([
	"dojo/_base/kernel",
	"dojo/_base/array",
	"dojo/_base/connect",
	"dojo/_base/declare",
	"dojo/_base/lang",
	"dojo/_base/window",
	"dojo/dom",
	"dojo/dom-class",
	"dojo/dom-construct",
//	"dojo/hash", // optionally prereq'ed
	"dojo/on",
	"dojo/ready",
	"dijit/registry",	// registry.byId
	"./ProgressIndicator",
	"./TransitionEvent"
], function(dojo, array, connect, declare, lang, win, dom, domClass, domConstruct, on, ready, registry, ProgressIndicator, TransitionEvent){

	// module:
	//		dojox/mobile/ViewController
	// summary:
	//		A singleton class that controlls view transition.

	var dm = lang.getObject("dojox.mobile", true);

	var Controller = declare("dojox.mobile.ViewController", null, {
		// summary:
		//		A singleton class that controlls view transition.
		// description:
		//		This class listens to the "startTransition" events and performs
		//		view transitions. If the transition destination is an external
		//		view specified with the url parameter, retrieves the view
		//		content and parses it to create a new target view.

		constructor: function(){
			this.viewMap={};
			this.currentView=null;
			this.defaultView=null;
			ready(lang.hitch(this, function(){
				on(win.body(), "startTransition", lang.hitch(this, "onStartTransition"));
			}));
		},

		findCurrentView: function(moveTo,src){
			// summary:
			//		Searches for the currently showing view.
			if(moveTo){
				var w = registry.byId(moveTo);
				if(w && w.getShowingView){ return w.getShowingView(); }
			}
			if(dm.currentView){
				return dm.currentView; //TODO:1.8 may not return an expected result especially when views are nested
			}
			//TODO:1.8 probably never reaches here
			w = src;
			while(true){
				w = w.getParent();
				if(!w){ return null; }
				if(domClass.contains(w.domNode, "mblView")){ break; }
			}
			return w;
		},

		onStartTransition: function(evt){
			// summary:
			//		A handler that performs view transition.

			evt.preventDefault();
			if(!evt.detail || (evt.detail && !evt.detail.moveTo && !evt.detail.href && !evt.detail.url && !evt.detail.scene)){ return; }
			var w = this.findCurrentView(evt.detail.moveTo, (evt.target && evt.target.id)?registry.byId(evt.target.id):registry.byId(evt.target)); // the current view widget
			if(!w || (evt.detail && evt.detail.moveTo && w === registry.byId(evt.detail.moveTo))){ return; }
			if(evt.detail.href){
				var t = registry.byId(evt.target.id).hrefTarget;
				if(t){
					dm.openWindow(evt.detail.href, t);
				}else{
					w.performTransition(null, evt.detail.transitionDir, evt.detail.transition, evt.target, function(){location.href = evt.detail.href;});
				}
				return;
			} else if(evt.detail.scene){
				connect.publish("/dojox/mobile/app/pushScene", [evt.detail.scene]);
				return;
			}
			var moveTo = evt.detail.moveTo;
			if(evt.detail.url){
				var id;
				if(dm._viewMap && dm._viewMap[evt.detail.url]){
					// external view has already been loaded
					id = dm._viewMap[evt.detail.url];
				}else{
					// get the specified external view and append it to the
					var text = this._text;
					if(!text){
						if(registry.byId(evt.target.id).sync){
							// We do not add explicit dependency on dojo/_base/xhr to this module
							// to be able to create a build that does not contain dojo/_base/xhr.
							// User applications that do sync loading here need to explicitly
							// require dojo/_base/xhr up front.
							dojo.xhrGet({url:evt.detail.url, sync:true, load:function(result){
								text = lang.trim(result);
							}});
						}else{
							var s = "dojo/_base/xhr"; // assign to a variable so as not to be picked up by the build tool
							require([s], lang.hitch(this, function(xhr){
								var prog = ProgressIndicator.getInstance();
								win.body().appendChild(prog.domNode);
								prog.start();
								var obj = xhr.get({
									url: evt.detail.url,
									handleAs: "text"
								});
								obj.addCallback(lang.hitch(this, function(response, ioArgs){
									prog.stop();
									if(response){
										this._text = response;
										new TransitionEvent(evt.target, {
												transition: evt.detail.transition,
											 	transitionDir: evt.detail.transitionDir,
											 	moveTo: moveTo,
											 	href: evt.detail.href,
											 	url: evt.detail.url,
											 	scene: evt.detail.scene},
											 		evt.detail)
											 			.dispatch();
									}
								}));
								obj.addErrback(function(error){
									prog.stop();
									console.log("Failed to load "+evt.detail.url+"\n"+(error.description||error));
								});
							}));
							return;
						}
					}
					this._text = null;
					id = this._parse(text, registry.byId(evt.target.id).urlTarget);
					if(!dm._viewMap){
						dm._viewMap = [];
					}
					dm._viewMap[evt.detail.url] = id;
				}
				moveTo = id;
				w = this.findCurrentView(moveTo,registry.byId(evt.target.id)) || w; // the current view widget
			}
			w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, null, null);
		},

		_parse: function(text, id){
			// summary:
			//		Parses the given view content.
			// description:
			//		If the content is html fragment, constructs dom tree with it
			//		and runs the parser. If the content is json data, passes it
			//		to _instantiate().
			var container, view, i, j, len;
			var currentView	 = this.findCurrentView();
			var target = registry.byId(id) && registry.byId(id).containerNode
						|| dom.byId(id)
						|| currentView && currentView.domNode.parentNode
						|| win.body();
			// if a fixed bottom bar exists, a new view should be placed before it.
			var refNode = null;
			for(j = target.childNodes.length - 1; j >= 0; j--){
				var c = target.childNodes[j];
				if(c.nodeType === 1){
					if(c.getAttribute("fixed") === "bottom"){
						refNode = c;
					}
					break;
				}
			}
			if(text.charAt(0) === "<"){ // html markup
				container = domConstruct.create("DIV", {innerHTML: text});
				for(i = 0; i < container.childNodes.length; i++){
					var n = container.childNodes[i];
					if(n.nodeType === 1){
						view = n; // expecting

						break;
					}
				}
				if(!view){
					console.log("dojox.mobile.ViewController#_parse: invalid view content");
					return;
				}
				view.style.visibility = "hidden";
				target.insertBefore(container, refNode);
				var ws = dojo.parser.parse(container);
				array.forEach(ws, function(w){
					if(w && !w._started && w.startup){
						w.startup();
					}
				});

				// allows multiple root nodes in the fragment,
				// but transition will be performed to the 1st view.
				for(i = 0, len = container.childNodes.length; i < len; i++){
					target.insertBefore(container.firstChild, refNode); // reparent
				}
				target.removeChild(container);

				registry.byNode(view)._visible = true;
			}else if(text.charAt(0) === "{"){ // json
				container = domConstruct.create("DIV");
				target.insertBefore(container, refNode);
				this._ws = [];
				view = this._instantiate(eval('('+text+')'), container);
				for(i = 0; i < this._ws.length; i++){
					var w = this._ws[i];
					w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
				}
				this._ws = null;
			}
			view.style.display = "none";
			view.style.visibility = "visible";
			return dojo.hash ? "#" + view.id : view.id;
		},

		_instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){
			// summary:
			//		Given the evaluated json data, does the same thing as what
			//		the parser does.
			var widget;
			for(var key in obj){
				if(key.charAt(0) == "@"){ continue; }
				var cls = lang.getObject(key);
				if(!cls){ continue; }
				var params = {};
				var proto = cls.prototype;
				var objs = lang.isArray(obj[key]) ? obj[key] : [obj[key]];
				for(var i = 0; i < objs.length; i++){
					for(var prop in objs[i]){
						if(prop.charAt(0) == "@"){
							var val = objs[i][prop];
							prop = prop.substring(1);
							if(typeof proto[prop] == "string"){
								params[prop] = val;
							}else if(typeof proto[prop] == "number"){
								params[prop] = val - 0;
							}else if(typeof proto[prop] == "boolean"){
							params[prop] = (val != "false");
							}else if(typeof proto[prop] == "object"){
								params[prop] = eval("(" + val + ")");
							}
						}
					}
					widget = new cls(params, node);
					if(node){ // to call View's startup()
						widget._visible = true;
						this._ws.push(widget);
					}
					if(parent && parent.addChild){
						parent.addChild(widget);
					}
					this._instantiate(objs[i], null, widget);
				}
			}
			return widget && widget.domNode;
		}
	});
	new Controller(); // singleton
	return Controller;
});

<commit_msg>Fixes #14186 !strict. If a widget that initiated the transition has a callback, pass it to View.performTransition(). This was a regression bug introduced during the view transition refactoring.<commit_after>define([
	"dojo/_base/kernel",
	"dojo/_base/array",
	"dojo/_base/connect",
	"dojo/_base/declare",
	"dojo/_base/lang",
	"dojo/_base/window",
	"dojo/dom",
	"dojo/dom-class",
	"dojo/dom-construct",
//	"dojo/hash", // optionally prereq'ed
	"dojo/on",
	"dojo/ready",
	"dijit/registry",	// registry.byId
	"./ProgressIndicator",
	"./TransitionEvent"
], function(dojo, array, connect, declare, lang, win, dom, domClass, domConstruct, on, ready, registry, ProgressIndicator, TransitionEvent){

	// module:
	//		dojox/mobile/ViewController
	// summary:
	//		A singleton class that controlls view transition.

	var dm = lang.getObject("dojox.mobile", true);

	var Controller = declare("dojox.mobile.ViewController", null, {
		// summary:
		//		A singleton class that controlls view transition.
		// description:
		//		This class listens to the "startTransition" events and performs
		//		view transitions. If the transition destination is an external
		//		view specified with the url parameter, retrieves the view
		//		content and parses it to create a new target view.

		constructor: function(){
			this.viewMap={};
			this.currentView=null;
			this.defaultView=null;
			ready(lang.hitch(this, function(){
				on(win.body(), "startTransition", lang.hitch(this, "onStartTransition"));
			}));
		},

		findCurrentView: function(moveTo,src){
			// summary:
			//		Searches for the currently showing view.
			if(moveTo){
				var w = registry.byId(moveTo);
				if(w && w.getShowingView){ return w.getShowingView(); }
			}
			if(dm.currentView){
				return dm.currentView; //TODO:1.8 may not return an expected result especially when views are nested
			}
			//TODO:1.8 probably never reaches here
			w = src;
			while(true){
				w = w.getParent();
				if(!w){ return null; }
				if(domClass.contains(w.domNode, "mblView")){ break; }
			}
			return w;
		},

		onStartTransition: function(evt){
			// summary:
			//		A handler that performs view transition.

			evt.preventDefault();
			if(!evt.detail || (evt.detail && !evt.detail.moveTo && !evt.detail.href && !evt.detail.url && !evt.detail.scene)){ return; }
			var w = this.findCurrentView(evt.detail.moveTo, (evt.target && evt.target.id)?registry.byId(evt.target.id):registry.byId(evt.target)); // the current view widget
			if(!w || (evt.detail && evt.detail.moveTo && w === registry.byId(evt.detail.moveTo))){ return; }
			if(evt.detail.href){
				var t = registry.byId(evt.target.id).hrefTarget;
				if(t){
					dm.openWindow(evt.detail.href, t);
				}else{
					w.performTransition(null, evt.detail.transitionDir, evt.detail.transition, evt.target, function(){location.href = evt.detail.href;});
				}
				return;
			} else if(evt.detail.scene){
				connect.publish("/dojox/mobile/app/pushScene", [evt.detail.scene]);
				return;
			}
			var moveTo = evt.detail.moveTo;
			if(evt.detail.url){
				var id;
				if(dm._viewMap && dm._viewMap[evt.detail.url]){
					// external view has already been loaded
					id = dm._viewMap[evt.detail.url];
				}else{
					// get the specified external view and append it to the
					var text = this._text;
					if(!text){
						if(registry.byId(evt.target.id).sync){
							// We do not add explicit dependency on dojo/_base/xhr to this module
							// to be able to create a build that does not contain dojo/_base/xhr.
							// User applications that do sync loading here need to explicitly
							// require dojo/_base/xhr up front.
							dojo.xhrGet({url:evt.detail.url, sync:true, load:function(result){
								text = lang.trim(result);
							}});
						}else{
							var s = "dojo/_base/xhr"; // assign to a variable so as not to be picked up by the build tool
							require([s], lang.hitch(this, function(xhr){
								var prog = ProgressIndicator.getInstance();
								win.body().appendChild(prog.domNode);
								prog.start();
								var obj = xhr.get({
									url: evt.detail.url,
									handleAs: "text"
								});
								obj.addCallback(lang.hitch(this, function(response, ioArgs){
									prog.stop();
									if(response){
										this._text = response;
										new TransitionEvent(evt.target, {
												transition: evt.detail.transition,
											 	transitionDir: evt.detail.transitionDir,
											 	moveTo: moveTo,
											 	href: evt.detail.href,
											 	url: evt.detail.url,
											 	scene: evt.detail.scene},
											 		evt.detail)
											 			.dispatch();
									}
								}));
								obj.addErrback(function(error){
									prog.stop();
									console.log("Failed to load "+evt.detail.url+"\n"+(error.description||error));
								});
							}));
							return;
						}
					}
					this._text = null;
					id = this._parse(text, registry.byId(evt.target.id).urlTarget);
					if(!dm._viewMap){
						dm._viewMap = [];
					}
					dm._viewMap[evt.detail.url] = id;
				}
				moveTo = id;
				w = this.findCurrentView(moveTo,registry.byId(evt.target.id)) || w; // the current view widget
			}
			var src = registry.getEnclosingWidget(evt.target);
			var context, method;
			if(src && src.callback){
				context = src;
				method = src.callback;
			}
			w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, context, method);
		},

		_parse: function(text, id){
			// summary:
			//		Parses the given view content.
			// description:
			//		If the content is html fragment, constructs dom tree with it
			//		and runs the parser. If the content is json data, passes it
			//		to _instantiate().
			var container, view, i, j, len;
			var currentView	 = this.findCurrentView();
			var target = registry.byId(id) && registry.byId(id).containerNode
						|| dom.byId(id)
						|| currentView && currentView.domNode.parentNode
						|| win.body();
			// if a fixed bottom bar exists, a new view should be placed before it.
			var refNode = null;
			for(j = target.childNodes.length - 1; j >= 0; j--){
				var c = target.childNodes[j];
				if(c.nodeType === 1){
					if(c.getAttribute("fixed") === "bottom"){
						refNode = c;
					}
					break;
				}
			}
			if(text.charAt(0) === "<"){ // html markup
				container = domConstruct.create("DIV", {innerHTML: text});
				for(i = 0; i < container.childNodes.length; i++){
					var n = container.childNodes[i];
					if(n.nodeType === 1){
						view = n; // expecting

						break;
					}
				}
				if(!view){
					console.log("dojox.mobile.ViewController#_parse: invalid view content");
					return;
				}
				view.style.visibility = "hidden";
				target.insertBefore(container, refNode);
				var ws = dojo.parser.parse(container);
				array.forEach(ws, function(w){
					if(w && !w._started && w.startup){
						w.startup();
					}
				});

				// allows multiple root nodes in the fragment,
				// but transition will be performed to the 1st view.
				for(i = 0, len = container.childNodes.length; i < len; i++){
					target.insertBefore(container.firstChild, refNode); // reparent
				}
				target.removeChild(container);

				registry.byNode(view)._visible = true;
			}else if(text.charAt(0) === "{"){ // json
				container = domConstruct.create("DIV");
				target.insertBefore(container, refNode);
				this._ws = [];
				view = this._instantiate(eval('('+text+')'), container);
				for(i = 0; i < this._ws.length; i++){
					var w = this._ws[i];
					w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
				}
				this._ws = null;
			}
			view.style.display = "none";
			view.style.visibility = "visible";
			return dojo.hash ? "#" + view.id : view.id;
		},

		_instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){
			// summary:
			//		Given the evaluated json data, does the same thing as what
			//		the parser does.
			var widget;
			for(var key in obj){
				if(key.charAt(0) == "@"){ continue; }
				var cls = lang.getObject(key);
				if(!cls){ continue; }
				var params = {};
				var proto = cls.prototype;
				var objs = lang.isArray(obj[key]) ? obj[key] : [obj[key]];
				for(var i = 0; i < objs.length; i++){
					for(var prop in objs[i]){
						if(prop.charAt(0) == "@"){
							var val = objs[i][prop];
							prop = prop.substring(1);
							if(typeof proto[prop] == "string"){
								params[prop] = val;
							}else if(typeof proto[prop] == "number"){
								params[prop] = val - 0;
							}else if(typeof proto[prop] == "boolean"){
							params[prop] = (val != "false");
							}else if(typeof proto[prop] == "object"){
								params[prop] = eval("(" + val + ")");
							}
						}
					}
					widget = new cls(params, node);
					if(node){ // to call View's startup()
						widget._visible = true;
						this._ws.push(widget);
					}
					if(parent && parent.addChild){
						parent.addChild(widget);
					}
					this._instantiate(objs[i], null, widget);
				}
			}
			return widget && widget.domNode;
		}
	});
	new Controller(); // singleton
	return Controller;
});

<|endoftext|>


<commit_before>import Ember from 'ember';
import Application from '../../app';
import Router from '../../router';
import config from '../../config/environment';

export default function startApp(attrs) {
  var application;

  var attributes = Ember.merge({}, config.APP);
  attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;

  Ember.run(function() {
    application = Application.create(attributes);
    application.setupForTesting();
    application.injectTestHelpers();
  });

  return application;
}
<commit_msg>drop unused line from app blueprint<commit_after>import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';

export default function startApp(attrs) {
  var application;

  var attributes = Ember.merge({}, config.APP);
  attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;

  Ember.run(function() {
    application = Application.create(attributes);
    application.setupForTesting();
    application.injectTestHelpers();
  });

  return application;
}
<|endoftext|>


<commit_before>
/* eslint-disable react/prop-types */
import classNames from 'classnames';
import React from 'react';
import ReactDOM from 'react-dom';
import tbsUtils, { bsClass, bsSizes } from './utils/bootstrapUtils';
import { Sizes } from './styleMaps';

import getScrollbarSize from 'dom-helpers/util/scrollbarSize';
import canUseDOM from 'dom-helpers/util/inDOM';
import ownerDocument from 'dom-helpers/ownerDocument';
import events from 'dom-helpers/events';
import elementType from 'react-prop-types/lib/elementType';

import Fade from './Fade';
import ModalDialog from './ModalDialog';
import Body from './ModalBody';
import Header from './ModalHeader';
import Title from './ModalTitle';
import Footer from './ModalFooter';

import BaseModal from 'react-overlays/lib/Modal';
import isOverflowing from 'react-overlays/lib/utils/isOverflowing';
import pick from 'lodash-compat/object/pick';

const Modal = React.createClass({

  propTypes: {
    ...BaseModal.propTypes,
    ...ModalDialog.propTypes,

    /**
     * Include a backdrop component. Specify 'static' for a backdrop that doesn't trigger an "onHide" when clicked.
     */
    backdrop: React.PropTypes.oneOf(['static', true, false]),

    /**
     * Close the modal when escape key is pressed
     */
    keyboard: React.PropTypes.bool,

    /**
     * Open and close the Modal with a slide and fade animation.
     */
    animation: React.PropTypes.bool,

    /**
     * A Component type that provides the modal content Markup. This is a useful prop when you want to use your own
     * styles and markup to create a custom modal component.
     */
    dialogComponent: elementType,

    /**
     * When `true` The modal will automatically shift focus to itself when it opens, and replace it to the last focused element when it closes.
     * Generally this should never be set to false as it makes the Modal less accessible to assistive technologies, like screen-readers.
     */
    autoFocus: React.PropTypes.bool,

    /**
     * When `true` The modal will prevent focus from leaving the Modal while open.
     * Consider leaving the default value here, as it is necessary to make the Modal work well with assistive technologies,
     * such as screen readers.
     */
    enforceFocus: React.PropTypes.bool,

    /**
     * Hide this from automatic props documentation generation.
     * @private
     */
    bsStyle: React.PropTypes.string,

    /**
     * When `true` The modal will show itself.
     */
    show: React.PropTypes.bool,

    /**
     * A callback fired when the header closeButton or non-static backdrop is
     * clicked. Required if either are specified.
     */
    onHide: React.PropTypes.func
  },

  childContextTypes: {
    '$bs_onModalHide': React.PropTypes.func
  },

  getDefaultProps() {
    return {
      ...BaseModal.defaultProps,
      bsClass: 'modal',
      animation: true,
      dialogComponent: ModalDialog,
    };
  },

  getInitialState() {
    return {
      modalStyles: {}
    };
  },

  getChildContext() {
    return {
      $bs_onModalHide: this.props.onHide
    };
  },

  componentWillUnmount() {
    events.off(window, 'resize', this.handleWindowResize);
  },

  render() {
    let {
        className
      , children
      , dialogClassName
      , animation
      , ...props } = this.props;

    let { modalStyles } = this.state;

    let inClass = { in: props.show && !animation };
    let Dialog = props.dialogComponent;

    let parentProps = pick(props,
      Object.keys(BaseModal.propTypes).concat(
        ['onExit', 'onExiting', 'onEnter', 'onEntered']) // the rest are fired in _onHide() and _onShow()
    );

    let modal = (
      <Dialog
        key="modal"
        ref={ref => this._modal = ref}
        {...props}
        style={modalStyles}
        className={classNames(className, inClass)}
        dialogClassName={dialogClassName}
        onClick={props.backdrop === true ? this.handleDialogClick : null}
      >
        { this.props.children }
      </Dialog>
    );

    return (
      <BaseModal
        {...parentProps}
        show={props.show}
        ref={ref => {
          this._wrapper = (ref && ref.refs.modal);
          this._backdrop = (ref && ref.refs.backdrop);
        }}
        onEntering={this._onShow}
        onExited={this._onHide}
        backdropClassName={classNames(tbsUtils.prefix(props, 'backdrop'), inClass)}
        containerClassName={tbsUtils.prefix(props, 'open')}
        transition={animation ? Fade : undefined}
        dialogTransitionTimeout={Modal.TRANSITION_DURATION}
        backdropTransitionTimeout={Modal.BACKDROP_TRANSITION_DURATION}
      >
        { modal }
      </BaseModal>
    );
  },

  _onShow(...args) {
    events.on(window, 'resize', this.handleWindowResize);

    this.setState(
      this._getStyles()
    );

    if (this.props.onEntering) {
      this.props.onEntering(...args);
    }
  },

  _onHide(...args) {
    events.off(window, 'resize', this.handleWindowResize);

    if (this.props.onExited) {
      this.props.onExited(...args);
    }
  },

  handleDialogClick(e) {
    if (e.target !== e.currentTarget) {
      return;
    }

    this.props.onHide();
  },

  handleWindowResize() {
    this.setState(this._getStyles());
  },

  _getStyles() {
    if (!canUseDOM) {
      return {};
    }

    let node = ReactDOM.findDOMNode(this._modal);
    let doc = ownerDocument(node);

    let scrollHt = node.scrollHeight;
    let bodyIsOverflowing = isOverflowing(ReactDOM.findDOMNode(this.props.container || doc.body));
    let modalIsOverflowing = scrollHt > doc.documentElement.clientHeight;

    return {
      modalStyles: {
        paddingRight: bodyIsOverflowing && !modalIsOverflowing ? getScrollbarSize() : void 0,
        paddingLeft: !bodyIsOverflowing && modalIsOverflowing ? getScrollbarSize() : void 0
      }
    };
  }
});

Modal.Body = Body;
Modal.Header = Header;
Modal.Title = Title;
Modal.Footer = Footer;

Modal.Dialog = ModalDialog;

Modal.TRANSITION_DURATION = 300;
Modal.BACKDROP_TRANSITION_DURATION = 150;

export default bsSizes([Sizes.LARGE, Sizes.SMALL],
  bsClass('modal', Modal)
);
<commit_msg>Add Modal propTypes for transition callbacks so it will be documented.<commit_after>
/* eslint-disable react/prop-types */
import classNames from 'classnames';
import React from 'react';
import ReactDOM from 'react-dom';
import tbsUtils, { bsClass, bsSizes } from './utils/bootstrapUtils';
import { Sizes } from './styleMaps';

import getScrollbarSize from 'dom-helpers/util/scrollbarSize';
import canUseDOM from 'dom-helpers/util/inDOM';
import ownerDocument from 'dom-helpers/ownerDocument';
import events from 'dom-helpers/events';
import elementType from 'react-prop-types/lib/elementType';

import Fade from './Fade';
import ModalDialog from './ModalDialog';
import Body from './ModalBody';
import Header from './ModalHeader';
import Title from './ModalTitle';
import Footer from './ModalFooter';

import BaseModal from 'react-overlays/lib/Modal';
import isOverflowing from 'react-overlays/lib/utils/isOverflowing';
import pick from 'lodash-compat/object/pick';

const Modal = React.createClass({

  propTypes: {
    ...BaseModal.propTypes,
    ...ModalDialog.propTypes,

    /**
     * Include a backdrop component. Specify 'static' for a backdrop that doesn't trigger an "onHide" when clicked.
     */
    backdrop: React.PropTypes.oneOf(['static', true, false]),

    /**
     * Close the modal when escape key is pressed
     */
    keyboard: React.PropTypes.bool,

    /**
     * Open and close the Modal with a slide and fade animation.
     */
    animation: React.PropTypes.bool,

    /**
     * A Component type that provides the modal content Markup. This is a useful prop when you want to use your own
     * styles and markup to create a custom modal component.
     */
    dialogComponent: elementType,

    /**
     * When `true` The modal will automatically shift focus to itself when it opens, and replace it to the last focused element when it closes.
     * Generally this should never be set to false as it makes the Modal less accessible to assistive technologies, like screen-readers.
     */
    autoFocus: React.PropTypes.bool,

    /**
     * When `true` The modal will prevent focus from leaving the Modal while open.
     * Consider leaving the default value here, as it is necessary to make the Modal work well with assistive technologies,
     * such as screen readers.
     */
    enforceFocus: React.PropTypes.bool,

    /**
     * Hide this from automatic props documentation generation.
     * @private
     */
    bsStyle: React.PropTypes.string,

    /**
     * When `true` The modal will show itself.
     */
    show: React.PropTypes.bool,

    /**
     * A callback fired when the header closeButton or non-static backdrop is
     * clicked. Required if either are specified.
     */
    onHide: React.PropTypes.func,

    /**
     * Callback fired before the Modal transitions in
     */
    onEnter: React.PropTypes.func,

    /**
     * Callback fired as the Modal begins to transition in
     */
    onEntering: React.PropTypes.func,

    /**
     * Callback fired after the Modal finishes transitioning in
     */
    onEntered: React.PropTypes.func,

    /**
     * Callback fired right before the Modal transitions out
     */
    onExit: React.PropTypes.func,

    /**
     * Callback fired as the Modal begins to transition out
     */
    onExiting: React.PropTypes.func,

    /**
     * Callback fired after the Modal finishes transitioning out
     */
    onExited: React.PropTypes.func
  },

  childContextTypes: {
    '$bs_onModalHide': React.PropTypes.func
  },

  getDefaultProps() {
    return {
      ...BaseModal.defaultProps,
      bsClass: 'modal',
      animation: true,
      dialogComponent: ModalDialog,
    };
  },

  getInitialState() {
    return {
      modalStyles: {}
    };
  },

  getChildContext() {
    return {
      $bs_onModalHide: this.props.onHide
    };
  },

  componentWillUnmount() {
    events.off(window, 'resize', this.handleWindowResize);
  },

  render() {
    let {
        className
      , children
      , dialogClassName
      , animation
      , ...props } = this.props;

    let { modalStyles } = this.state;

    let inClass = { in: props.show && !animation };
    let Dialog = props.dialogComponent;

    let parentProps = pick(props,
      Object.keys(BaseModal.propTypes).concat(
        ['onExit', 'onExiting', 'onEnter', 'onEntered']) // the rest are fired in _onHide() and _onShow()
    );

    let modal = (
      <Dialog
        key="modal"
        ref={ref => this._modal = ref}
        {...props}
        style={modalStyles}
        className={classNames(className, inClass)}
        dialogClassName={dialogClassName}
        onClick={props.backdrop === true ? this.handleDialogClick : null}
      >
        { this.props.children }
      </Dialog>
    );

    return (
      <BaseModal
        {...parentProps}
        show={props.show}
        ref={ref => {
          this._wrapper = (ref && ref.refs.modal);
          this._backdrop = (ref && ref.refs.backdrop);
        }}
        onEntering={this._onShow}
        onExited={this._onHide}
        backdropClassName={classNames(tbsUtils.prefix(props, 'backdrop'), inClass)}
        containerClassName={tbsUtils.prefix(props, 'open')}
        transition={animation ? Fade : undefined}
        dialogTransitionTimeout={Modal.TRANSITION_DURATION}
        backdropTransitionTimeout={Modal.BACKDROP_TRANSITION_DURATION}
      >
        { modal }
      </BaseModal>
    );
  },

  _onShow(...args) {
    events.on(window, 'resize', this.handleWindowResize);

    this.setState(
      this._getStyles()
    );

    if (this.props.onEntering) {
      this.props.onEntering(...args);
    }
  },

  _onHide(...args) {
    events.off(window, 'resize', this.handleWindowResize);

    if (this.props.onExited) {
      this.props.onExited(...args);
    }
  },

  handleDialogClick(e) {
    if (e.target !== e.currentTarget) {
      return;
    }

    this.props.onHide();
  },

  handleWindowResize() {
    this.setState(this._getStyles());
  },

  _getStyles() {
    if (!canUseDOM) {
      return {};
    }

    let node = ReactDOM.findDOMNode(this._modal);
    let doc = ownerDocument(node);

    let scrollHt = node.scrollHeight;
    let bodyIsOverflowing = isOverflowing(ReactDOM.findDOMNode(this.props.container || doc.body));
    let modalIsOverflowing = scrollHt > doc.documentElement.clientHeight;

    return {
      modalStyles: {
        paddingRight: bodyIsOverflowing && !modalIsOverflowing ? getScrollbarSize() : void 0,
        paddingLeft: !bodyIsOverflowing && modalIsOverflowing ? getScrollbarSize() : void 0
      }
    };
  }
});

Modal.Body = Body;
Modal.Header = Header;
Modal.Title = Title;
Modal.Footer = Footer;

Modal.Dialog = ModalDialog;

Modal.TRANSITION_DURATION = 300;
Modal.BACKDROP_TRANSITION_DURATION = 150;

export default bsSizes([Sizes.LARGE, Sizes.SMALL],
  bsClass('modal', Modal)
);
<|endoftext|>


<commit_before>'use strict';

var chai = require('chai');
var api = require('../index.js');

require('dotenv').load();
chai.should();

describe('Unsplash API public endpoints', function() {
  api.init(process.env.CLIENT_ID);

  describe('User', function() {
    describe('getUserPhotos', function() {
      it('should return without err and with an empty array', function(done) {
        api.getUserPhotos('fletcher_hills', function(err, photos) {
          if (err) return done(err);

          photos.should.be.instanceOf(Array);

          done();
        });
      });

      it('should return with invalid username error', function(done) {
        api.getUserPhotos('01234', function(err, photos) {

          err.should.exist;
          chai.expect(photos).to.not.exist;

          done();
        });
      })
    });

    describe('getUserByName', function() {
      it('should return without err and with a user', function(done) {
        api.getUserByName('fletcher_hills', function(err, user) {
          if (err) return done(err);

          user.should.be.ok;

          done();
        });
      });

      it('should return with invalid username error', function(done) {
        api.getUserByName('01234', function(err, user) {

          err.should.exist;
          chai.expect(user).to.not.exist;

          done();
        });
      });
    });
  });

  describe('Photos', function() {
     describe('getPhotos', function() {
        it('should return without err and with the first 10 pictures', function(done) {
           api.getPhotos(null, null, function(err, photos, link) {
              if (err) return done(err);

              photos.should.be.instanceOf(Array);
              photos.should.have.length(10);

              done();
           });
        });

        it('should return without err and with the first 20 pictures', function(done) {
           api.getPhotos(null, 20, function(err, photos, link) {
               if (err) return done(err);

               photos.should.be.instanceOf(Array);
               photos.should.have.length(20);

               done();
           });
        });

        it('should return without err and with the second 10 pictures', function(done) {
           api.getPhotos(2, null, function(err, photos, link) {
               if (err) return done(err);

               photos.should.be.instanceOf(Array);
               photos.should.have.length(10);

               link.should.contain('<https://api.unsplash.com/photos?page=1>; rel="prev",');

               done();
           });
        });
     });

     describe.skip('searchPhotos', function() {
        it('should return without err and with the first 10 pictures from query "beach"', function(done) {
           api.searchPhotos('beach', null, null, null, function(err, photos, link) {
              if (err) return done(err);

              photos.should.be.instanceOf(Array);
              photos.should.have.length(10);

              link.should.contain('query=beach');

              done();
           });
        });

        it('should return without err and with ')
     });
  });

  describe('Categories', function() {
    describe('getAllCategories', function() {
      it('should return without err and an array of categories', function(done) {
        api.getAllCategories(function(err, cats) {
          if (err) return done(err);

          cats.should.be.instanceOf(Array);

          done();
        });
      })
    });

    describe('getCategory', function() {
      it('should return without err and category #2 info', function(done) {
        api.getCategory('2', function(err, category) {
          if (err) return done(err);

          category.should.be.ok;
          category.id.should.equal(2);

          done();
        });
      });

      it('should return with invalid ID error', function(done) {
        api.getCategory('-1', function(err, category) {
          err.should.exist;
          chai.expect(category).to.not.exist;

          done();
        });
      });
    });

    describe('getCategoryPhotos', function() {
      it('should return without err and an array of photos', function(done) {
        api.getCategoryPhotos('2', function(err, photos, link) {
          if (err) return done(err);

          photos.should.be.instanceOf(Array);
          link.should.be.ok;

          done();
        });
      });

      it('should return with an invalid ID error', function(done) {
        api.getCategoryPhotos('-1', function(err, photos, link) {
          err.should.exist;

          chai.expect(photos).to.not.exist;
          chai.expect(link).to.not.exist;

          done();
        });
      });
    });
  });
});<commit_msg>add searchPhotos tests<commit_after>'use strict';

var chai = require('chai');
var api = require('../index.js');

require('dotenv').load();
chai.should();

describe('Unsplash API public endpoints', function() {
  api.init(process.env.CLIENT_ID);

  describe('User', function() {
    describe('getUserPhotos', function() {
      it('should return without err and with an empty array', function(done) {
        api.getUserPhotos('fletcher_hills', function(err, photos) {
          if (err) return done(err);

          photos.should.be.instanceOf(Array);

          done();
        });
      });

      it('should return with invalid username error', function(done) {
        api.getUserPhotos('01234', function(err, photos) {

          err.should.exist;
          chai.expect(photos).to.not.exist;

          done();
        });
      })
    });

    describe('getUserByName', function() {
      it('should return without err and with a user', function(done) {
        api.getUserByName('fletcher_hills', function(err, user) {
          if (err) return done(err);

          user.should.be.ok;

          done();
        });
      });

      it('should return with invalid username error', function(done) {
        api.getUserByName('01234', function(err, user) {

          err.should.exist;
          chai.expect(user).to.not.exist;

          done();
        });
      });
    });
  });

  describe('Photos', function() {
     describe('getPhotos', function() {
        it('should return without err and with the first 10 pictures', function(done) {
           api.getPhotos(null, null, function(err, photos, link) {
              if (err) return done(err);

              photos.should.be.instanceOf(Array);
              photos.should.have.length(10);

              done();
           });
        });

        it('should return without err and with the first 20 pictures', function(done) {
           api.getPhotos(null, 20, function(err, photos, link) {
               if (err) return done(err);

               photos.should.be.instanceOf(Array);
               photos.should.have.length(20);

               done();
           });
        });

        it('should return without err and with the second 10 pictures', function(done) {
           api.getPhotos(2, null, function(err, photos, link) {
               if (err) return done(err);

               photos.should.be.instanceOf(Array);
               photos.should.have.length(10);

               link.should.contain('<https://api.unsplash.com/photos?page=1>; rel="prev",');

               done();
           });
        });
     });

     describe('searchPhotos', function() {
        it('should return without err and with the first 10 pictures from query "beach"', function(done) {
           api.searchPhotos('beach', null, null, null, function(err, photos, link) {
              if (err) return done(err);

              photos.should.be.instanceOf(Array);
              photos.should.have.length(10);

              link.should.contain('query=beach');

              done();
           });
        });

        it('should return first 10 pictures from query "beach" with "nature" category applied', function(done) {
           api.searchPhotos('beach', 4, null, null, function(err, photos, link) {
              if (err) return done(err);

              photos.should.be.instanceOf(Array);
              photos.should.have.length(10);

              link.should.contain('query=beach');
              link.should.contain('category=4');

              done();
           });
        });

        it('should return without err and the second 10 pictures from query "beach"', function(done) {
           api.searchPhotos('beach', null, 2, null, function(err, photos, link) {
              if (err) return done(err);

              photos.should.be.instanceOf(Array);
              photos.should.have.length(10);

              link.should.contain('<https://api.unsplash.com/photos/search?page=1&query=beach>; rel="prev",');

              done();
           });
        });

        it('should return without err and with the first 20 pictures from query "beach"', function(done) {
           api.searchPhotos('beach', null, null, 20, function(err, photos, link) {
              if (err) return done(err);

              photos.should.be.instanceOf(Array);
              photos.should.have.length(20);

              link.should.contain('query=beach');

              done();
           });
        });

        it('should return with invalid query error', function(done) {
           api.searchPhotos(null, null, null, null, function(err, photos, link) {
              err.should.exist;
              chai.expect(photos).to.not.exist;
              chai.expect(link).to.not.exist;

              done();
           });
        });
     });
  });

  describe('Categories', function() {
    describe('getAllCategories', function() {
      it('should return without err and an array of categories', function(done) {
        api.getAllCategories(function(err, cats) {
          if (err) return done(err);

          cats.should.be.instanceOf(Array);

          done();
        });
      })
    });

    describe('getCategory', function() {
      it('should return without err and category #2 info', function(done) {
        api.getCategory('2', function(err, category) {
          if (err) return done(err);

          category.should.be.ok;
          category.id.should.equal(2);

          done();
        });
      });

      it('should return with invalid ID error', function(done) {
        api.getCategory('-1', function(err, category) {
          err.should.exist;
          chai.expect(category).to.not.exist;

          done();
        });
      });
    });

    describe('getCategoryPhotos', function() {
      it('should return without err and an array of photos', function(done) {
        api.getCategoryPhotos('2', function(err, photos, link) {
          if (err) return done(err);

          photos.should.be.instanceOf(Array);
          link.should.be.ok;

          done();
        });
      });

      it('should return with an invalid ID error', function(done) {
        api.getCategoryPhotos('-1', function(err, photos, link) {
          err.should.exist;

          chai.expect(photos).to.not.exist;
          chai.expect(link).to.not.exist;

          done();
        });
      });
    });
  });
});<|endoftext|>


<commit_before>var assert = require('assert');
var os = require('os');
var platform = os.platform();
var ns;
if (platform == 'darwin') {
    ns = require('../src/nsutil/nsosx.js');
}
if (platform == 'linux') {
    ns = require('../src/nsutil/nslinux.js');
}

var apiList = {
    functions: [
        'virtualMemory', 'swapMemory', 'cpuTimes', 'perCpuTimes',
        'cpuCountLogical', 'cpuCountPhysical', 'bootTime', 'diskPartitions',
        'users', 'pids', 'netConnections', 'netIOCounters', 'diskIOCounters'
    ],
    process: [
        'name', 'exe', 'cmdline', 'ppid', 'cwd', 'uids', 'gids',
        'terminal', 'memoryInfo', 'cpuTimes', 'createTime', 'numCtxSwitches',
        'numThreads', 'openFiles', 'connections', 'numFds', 'getNice',
        'setNice', 'status', 'threads', 'memMaps'
    ]
};

describe('[platform] ' + platform, function() {

    // 测试接口是否能跑通，数据正确性不在这里测
    /**/
    apiList.functions.forEach(function(apiName) {
        it ('[function] ' + apiName, function() {
            var r = ns[apiName]();
            if (typeof r == 'undefined') {
                throw new Error('result undefined');
            }
            //console.log(r);
        });
        it ('[function] ' + apiName + ' (async)', function(done) {
            ns[apiName](function(err, res) {
                if (err) {
                    throw new Error('result err');
                }
                if (typeof res == 'undefined') {
                    throw new Error('result undefined');
                }
               // console.log(res);
                done();
            });
        });
    });
    /**/
    describe('[Class] Process', function() {

        var pid = ns.pids()[0];
        //pid = pid[pid.length - 1];
        var proc = ns.Process(pid);
        /**/
        apiList.process.forEach(function(apiName) {
            it ('[method] proc.' + apiName, function() {
                var r;
                if (apiName == 'setNice') {
                    r = proc[apiName](1);
                } else {
                    r = proc[apiName]();
                }
                if (typeof r == 'undefined') {
                    throw new Error('result undefined');
                }
            });
            it ('[method] proc.' + apiName + ' (async)', function(done) {
                if (apiName == 'setNice') {
                    proc[apiName](1, function(err, res) {
                        if (err) {
                            throw new Error('result err');
                        }
                        if (typeof res == 'undefined') {
                            throw new Error('result undefined');
                        }
                        done();
                    });
                } else {
                    proc[apiName](function(err, res) {
                        if (err) {
                            throw new Error('result err');
                        }
                        if (typeof res == 'undefined') {
                            throw new Error('result undefined');
                        }
                        done();
                    });
                }
            });
        });
        /**/

    });
});
<commit_msg>测试增加diskUsage<commit_after>var assert = require('assert');
var os = require('os');
var platform = os.platform();
var ns;
if (platform == 'darwin') {
    ns = require('../src/nsutil/nsosx.js');
}
if (platform == 'linux') {
    ns = require('../src/nsutil/nslinux.js');
}

var apiList = {
    functions: [
        'virtualMemory', 'swapMemory', 'cpuTimes', 'perCpuTimes',
        'cpuCountLogical', 'cpuCountPhysical', 'bootTime', 'diskPartitions',
        'users', 'pids', 'netConnections', 'netIOCounters', 'diskIOCounters',
        'diskUsage'
    ],
    process: [
        'name', 'exe', 'cmdline', 'ppid', 'cwd', 'uids', 'gids',
        'terminal', 'memoryInfo', 'cpuTimes', 'createTime', 'numCtxSwitches',
        'numThreads', 'openFiles', 'connections', 'numFds', 'getNice',
        'setNice', 'status', 'threads', 'memMaps'
    ]
};

describe('[platform] ' + platform, function() {

    // 测试接口是否能跑通，数据正确性不在这里测
    /**/
    apiList.functions.forEach(function(apiName) {
        var p;
        if (apiName == 'diskUsage') p = '/';
        it ('[function] ' + apiName, function() {
            if (p) {
                var r = ns[apiName](p);
            } else {
                var r = ns[apiName]();
            }
            if (typeof r == 'undefined') {
                throw new Error('result undefined');
            }
            //console.log(r);
        });
        it ('[function] ' + apiName + ' (async)', function(done) {
            if (p) {
                ns[apiName](p, function(err, res) {
                    if (err) {
                        throw new Error('result err');
                    }
                    if (typeof res == 'undefined') {
                        throw new Error('result undefined');
                    }
                   // console.log(res);
                    done();
                });
            } else {
                ns[apiName](function(err, res) {
                    if (err) {
                        throw new Error('result err');
                    }
                    if (typeof res == 'undefined') {
                        throw new Error('result undefined');
                    }
                   // console.log(res);
                    done();
                });
            }
        });
    });
    /**/
    describe('[Class] Process', function() {

        var pid = ns.pids()[0];
        //pid = pid[pid.length - 1];
        var proc = ns.Process(pid);
        /**/
        apiList.process.forEach(function(apiName) {
            it ('[method] proc.' + apiName, function() {
                var r;
                if (apiName == 'setNice') {
                    r = proc[apiName](1);
                } else {
                    r = proc[apiName]();
                }
                if (typeof r == 'undefined') {
                    throw new Error('result undefined');
                }
            });
            it ('[method] proc.' + apiName + ' (async)', function(done) {
                if (apiName == 'setNice') {
                    proc[apiName](1, function(err, res) {
                        if (err) {
                            throw new Error('result err');
                        }
                        if (typeof res == 'undefined') {
                            throw new Error('result undefined');
                        }
                        done();
                    });
                } else {
                    proc[apiName](function(err, res) {
                        if (err) {
                            throw new Error('result err');
                        }
                        if (typeof res == 'undefined') {
                            throw new Error('result undefined');
                        }
                        done();
                    });
                }
            });
        });
        /**/

    });
});
<|endoftext|>


<commit_before>module.exports = function(grunt) {
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-handlebars');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-requirejs');

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		clean: {
			cruft: ['**/.DS_Store','**/Thumbs.db'],
      bin: ['bin/*'],
      postoptimize: ['bin/optimized/*.html','!bin/optimized/demo_requirejs.html'],
      nonminifiedVendorJS: {expand: true, cwd:'bin', src: ['**/vendor/**/*.js','!**/vendor/**/*.min.js']}
		},

    copy: {
      js: { files: [ {expand: true, cwd: 'src/', src: ['js/**/*.js'], dest: 'bin/'} ] },
      component_library: { files: [ {expand: true, cwd: 'src/', src: ['component_library/**/*.js'], dest: 'bin/'} ] },
      html: { files: [ {expand: true, cwd: 'src/', src: ['*.html'], dest: 'bin/' } ] }
    },

    less: {
      main: {
        files: {'bin/css/main.css':'src/less/main.less'}
      }
    },

    handlebars: {
      options: {
        namespace: false,
        amd: true
      },
      files: {
        expand: true,
        cwd: 'src/component_library/ui',
        src: ['*.hbs'],
        flatten: true,
        extDot: 'last',
        ext: '.hbs.js',
        dest: 'bin/component_library/ui'
      }
    },

    watch: {
      static_assets: {
        files: ['bin/**/*'],
        options: {
          debounceDelay: 1000,
          livereload: 9000
        },
      },
      html: {
        files: ['src/*.html'],
        tasks: ['copy:html']
      },
      js: {
        files: ['src/**/*.js'],
        tasks: ['copy:js']
      },
      handlebars: {
        files: ['src/component_library/ui/*.hbs'],
        tasks: ['handlebars']
      }
    },

    requirejs: {
      optimized: {
        options: {
          appDir: 'bin/',
          dir: 'bin/optimized',
          mainConfigFile: 'bin/js/main.js',
          removeCombined: true,
          optimize: 'none',
          optimize: 'uglify2',
          uglify2: {
            mangle: true,
            compress: {
              sequences: true,
            }
          },
          modules: [{ name: '../js/main' }]
        }
      }
    }

  });

	grunt.registerTask('server', 'Start the web server.', function() {
		require('./server');
	});

  grunt.registerTask('post-build', ['clean:postoptimize','clean:nonminifiedVendorJS']);

  grunt.registerTask('build', ['handlebars','less','copy','requirejs','post-build']);
  //grunt.registerTask('build', ['handlebars','less','copy']);

	grunt.registerTask('default', [ 'clean', 'build', 'server', 'watch' ]);
};
<commit_msg>Fix components not updating on save<commit_after>module.exports = function(grunt) {
	grunt.loadNpmTasks('grunt-contrib-clean');
	grunt.loadNpmTasks('grunt-contrib-copy');
	grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-handlebars');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-requirejs');

	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		clean: {
			cruft: ['**/.DS_Store','**/Thumbs.db'],
      bin: ['bin/*'],
      postoptimize: ['bin/optimized/*.html','!bin/optimized/demo_requirejs.html'],
      nonminifiedVendorJS: {expand: true, cwd:'bin', src: ['**/vendor/**/*.js','!**/vendor/**/*.min.js']}
		},

    copy: {
      js: { files: [ {expand: true, cwd: 'src/', src: ['js/**/*.js'], dest: 'bin/'} ] },
      component_library: { files: [ {expand: true, cwd: 'src/', src: ['component_library/**/*.js'], dest: 'bin/'} ] },
      html: { files: [ {expand: true, cwd: 'src/', src: ['*.html'], dest: 'bin/' } ] }
    },

    less: {
      main: {
        files: {'bin/css/main.css':'src/less/main.less'}
      }
    },

    handlebars: {
      options: {
        namespace: false,
        amd: true
      },
      files: {
        expand: true,
        cwd: 'src/component_library/ui',
        src: ['*.hbs'],
        flatten: true,
        extDot: 'last',
        ext: '.hbs.js',
        dest: 'bin/component_library/ui'
      }
    },

    watch: {
      static_assets: {
        files: ['bin/**/*'],
        options: {
          debounceDelay: 1000,
          livereload: 9000
        },
      },
      html: {
        files: ['src/*.html'],
        tasks: ['copy:html']
      },
      js: {
        files: ['src/**/*.js'],
        tasks: ['copy:js','copy:component_library']
      },
      handlebars: {
        files: ['src/component_library/ui/*.hbs'],
        tasks: ['handlebars']
      }
    },

    requirejs: {
      optimized: {
        options: {
          appDir: 'bin/',
          dir: 'bin/optimized',
          mainConfigFile: 'bin/js/main.js',
          removeCombined: true,
          optimize: 'none',
          optimize: 'uglify2',
          uglify2: {
            mangle: true,
            compress: {
              sequences: true,
            }
          },
          modules: [{ name: '../js/main' }]
        }
      }
    }

  });

	grunt.registerTask('server', 'Start the web server.', function() {
		require('./server');
	});

  grunt.registerTask('post-build', ['clean:postoptimize','clean:nonminifiedVendorJS']);

  grunt.registerTask('build', ['handlebars','less','copy','requirejs','post-build']);
  //grunt.registerTask('build', ['handlebars','less','copy']);

	grunt.registerTask('default', [ 'clean', 'build', 'server', 'watch' ]);
};
<|endoftext|>


<commit_before>var inspect = require("util").inspect,
    fs = require("fs");

module.exports = function(grunt) {

  var task = grunt.task;
  var file = grunt.file;
  var log = grunt.log;
  var verbose = grunt.verbose;
  var fail = grunt.fail;
  var option = grunt.option;
  var config = grunt.config;
  var template = grunt.template;
  var _ = grunt.util._;

  var templates = {
    doc: _.template( file.read("tpl/.docs.md") ),
    img: _.template( file.read("tpl/.img.md") ),
    fritzing: _.template( file.read("tpl/.fritzing.md") ),
    doclink: _.template( file.read("tpl/.readme.doclink.md") ),
    readme: _.template( file.read("tpl/.readme.md") )
  };

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON("package.json"),
    docs: {
      files: ["programs.json"]
    },
    nodeunit: {
      tests: [
        "test/board.js",
        "test/options.js",
        "test/pins.js",
        "test/capabilities.js",
        // ------------------
        "test/button.js",
        "test/distance.js",
        "test/lcd.js",
        "test/led.js",
        "test/pin.js",
        "test/piezo.js",
        "test/ping.js",
        "test/pir.js",
        "test/sensor.js",
        "test/sonar.js",
        "test/switch.js",
        "test/shiftregister.js"
      ]
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true,
        strict: false,
        globals: {
          exports: true,
          document: true,
          $: true,
          Radar: true,
          WeakMap: true,
          window: true
        }
      },
      files: {
        src: [
          "Gruntfile.js",
          "lib/**/!(johnny-five)*.js",
          "test/**/*.js",
          "eg/**/*.js"
        ]
      }
    },

    jsbeautifier: {
      files: ["lib/**/*.js"],
      options: {
        js: {
          braceStyle: "collapse",
          breakChainedMethods: false,
          e4x: false,
          evalCode: false,
          indentChar: " ",
          indentLevel: 0,
          indentSize: 2,
          indentWithTabs: false,
          jslintHappy: false,
          keepArrayIndentation: false,
          keepFunctionIndentation: false,
          maxPreserveNewlines: 10,
          preserveNewlines: true,
          spaceBeforeConditional: true,
          spaceInParen: false,
          unescapeStrings: false,
          wrapLineLength: 0
        }
      }
    }
  });
  // Default tasks are contrib plugins
  grunt.loadNpmTasks("grunt-contrib-nodeunit");
  grunt.loadNpmTasks("grunt-contrib-jshint");
  grunt.loadNpmTasks("grunt-jsbeautifier");
  // Default task.
  grunt.registerTask("default", ["jshint", "nodeunit"]);

  grunt.registerMultiTask("docs", "generate simple docs from examples", function() {
    // Concat specified files.
    var entries, readme;
    entries = JSON.parse(file.read(file.expand( this.data )));
    readme = [];

    entries.forEach(function( entry ) {

      var values, markdown, eg, md, png, fzz, title,
          hasPng, hasFzz, inMarkdown, filepath, fritzfile, fritzpath;

      if ( Array.isArray(entry) ) {
        // Produces:
        // "### Heading\n"
        readme.push( "\n### " + entry[0] + "\n" );

        // TODO: figure out a way to have tiered subheadings
        // readme.push(
        //   entry.reduce(function( prev, val, k ) {
        //     // Produces:
        //     // "### Board\n"
        //     return prev + (Array(k + 4).join("#")) + " " + val + "\n";
        //   }, "")
        // );
      }
      else {

        filepath = "eg/" + entry;

        eg = file.read( filepath );
        md = "docs/" + entry.replace(".js", ".md");
        png = "docs/breadboard/" + entry.replace(".js", ".png");
        fzz = "docs/breadboard/" + entry.replace(".js", ".fzz");
        title = entry;

        markdown = [];

        // Generate a title string from the file name
        [ [ /^.+\//, "" ],
          [ /\.js/, "" ],
          [ /\-/g, " " ]
        ].forEach(function( args ) {
          title = "".replace.apply( title, args );
        });

        fritzpath = fzz.split("/");
        fritzfile = fritzpath[ fritzpath.length - 1 ];
        inMarkdown = false;

        // Modify code in example to appear as it would if installed via npm
        eg = eg.replace("../lib/johnny-five.js", "johnny-five")
              .split("\n").filter(function( line ) {

          if ( /@markdown/.test(line) ) {
            inMarkdown = !inMarkdown;
            return false;
          }

          if ( inMarkdown ) {
            line = line.trim();
            if ( line ) {
              markdown.push(
                line.replace(/^\/\//, "").trim()
              );
            }
            // Filter out the markdown lines
            // from the main content.
            return false;
          }

          return true;
        }).join("\n");

        hasPng = fs.existsSync(png);
        hasFzz = fs.existsSync(fzz);

        // console.log( markdown );

        values = {
          title: _.titleize(title),
          command: "node " + filepath,
          example: eg,
          file: md,
          markdown: markdown.join("\n"),
          breadboard: hasPng ? templates.img({ png: png }) : "",
          fritzing: hasFzz ? templates.fritzing({ fzz: fzz }) : ""
        };

        // Write the file to /docs/*
        file.write( md, templates.doc(values) );

        // Push a rendered markdown link into the readme "index"
        readme.push( templates.doclink(values) );
      }
    });

    // Write the readme with doc link index
    file.write( "README.md", templates.readme({ doclinks: readme.join("") }) );

    log.writeln("Docs created.");
  });
};
<commit_msg>Setup grunt jsbeautifier<commit_after>var inspect = require("util").inspect,
    fs = require("fs");

module.exports = function(grunt) {

  var task = grunt.task;
  var file = grunt.file;
  var log = grunt.log;
  var verbose = grunt.verbose;
  var fail = grunt.fail;
  var option = grunt.option;
  var config = grunt.config;
  var template = grunt.template;
  var _ = grunt.util._;

  var templates = {
    doc: _.template( file.read("tpl/.docs.md") ),
    img: _.template( file.read("tpl/.img.md") ),
    fritzing: _.template( file.read("tpl/.fritzing.md") ),
    doclink: _.template( file.read("tpl/.readme.doclink.md") ),
    readme: _.template( file.read("tpl/.readme.md") )
  };

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON("package.json"),
    docs: {
      files: ["programs.json"]
    },
    nodeunit: {
      tests: [
        "test/board.js",
        "test/options.js",
        "test/pins.js",
        "test/capabilities.js",
        // ------------------
        "test/button.js",
        "test/distance.js",
        "test/lcd.js",
        "test/led.js",
        "test/pin.js",
        "test/piezo.js",
        "test/ping.js",
        "test/pir.js",
        "test/sensor.js",
        "test/sonar.js",
        "test/switch.js",
        "test/shiftregister.js"
      ]
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true,
        strict: false,
        globals: {
          exports: true,
          document: true,
          $: true,
          Radar: true,
          WeakMap: true,
          window: true
        }
      },
      files: {
        src: [
          "Gruntfile.js",
          "lib/**/!(johnny-five)*.js",
          "test/**/*.js",
          "eg/**/*.js"
        ]
      }
    },

    jsbeautifier: {
      files: ["lib/**/*.js", "eg/**/*.js", "test/**/*.js"],
      options: {
        js: {
          braceStyle: "collapse",
          breakChainedMethods: false,
          e4x: false,
          evalCode: false,
          indentChar: " ",
          indentLevel: 0,
          indentSize: 2,
          indentWithTabs: false,
          jslintHappy: false,
          keepArrayIndentation: false,
          keepFunctionIndentation: false,
          maxPreserveNewlines: 10,
          preserveNewlines: true,
          spaceBeforeConditional: true,
          spaceInParen: false,
          unescapeStrings: false,
          wrapLineLength: 0
        }
      }
    }
  });
  // Default tasks are contrib plugins
  grunt.loadNpmTasks("grunt-contrib-nodeunit");
  grunt.loadNpmTasks("grunt-contrib-jshint");
  grunt.loadNpmTasks("grunt-jsbeautifier");
  // Default task.
  grunt.registerTask("default", ["jshint", "nodeunit"]);

  grunt.registerMultiTask("docs", "generate simple docs from examples", function() {
    // Concat specified files.
    var entries, readme;
    entries = JSON.parse(file.read(file.expand( this.data )));
    readme = [];

    entries.forEach(function( entry ) {

      var values, markdown, eg, md, png, fzz, title,
          hasPng, hasFzz, inMarkdown, filepath, fritzfile, fritzpath;

      if ( Array.isArray(entry) ) {
        // Produces:
        // "### Heading\n"
        readme.push( "\n### " + entry[0] + "\n" );

        // TODO: figure out a way to have tiered subheadings
        // readme.push(
        //   entry.reduce(function( prev, val, k ) {
        //     // Produces:
        //     // "### Board\n"
        //     return prev + (Array(k + 4).join("#")) + " " + val + "\n";
        //   }, "")
        // );
      }
      else {

        filepath = "eg/" + entry;

        eg = file.read( filepath );
        md = "docs/" + entry.replace(".js", ".md");
        png = "docs/breadboard/" + entry.replace(".js", ".png");
        fzz = "docs/breadboard/" + entry.replace(".js", ".fzz");
        title = entry;

        markdown = [];

        // Generate a title string from the file name
        [ [ /^.+\//, "" ],
          [ /\.js/, "" ],
          [ /\-/g, " " ]
        ].forEach(function( args ) {
          title = "".replace.apply( title, args );
        });

        fritzpath = fzz.split("/");
        fritzfile = fritzpath[ fritzpath.length - 1 ];
        inMarkdown = false;

        // Modify code in example to appear as it would if installed via npm
        eg = eg.replace("../lib/johnny-five.js", "johnny-five")
              .split("\n").filter(function( line ) {

          if ( /@markdown/.test(line) ) {
            inMarkdown = !inMarkdown;
            return false;
          }

          if ( inMarkdown ) {
            line = line.trim();
            if ( line ) {
              markdown.push(
                line.replace(/^\/\//, "").trim()
              );
            }
            // Filter out the markdown lines
            // from the main content.
            return false;
          }

          return true;
        }).join("\n");

        hasPng = fs.existsSync(png);
        hasFzz = fs.existsSync(fzz);

        // console.log( markdown );

        values = {
          title: _.titleize(title),
          command: "node " + filepath,
          example: eg,
          file: md,
          markdown: markdown.join("\n"),
          breadboard: hasPng ? templates.img({ png: png }) : "",
          fritzing: hasFzz ? templates.fritzing({ fzz: fzz }) : ""
        };

        // Write the file to /docs/*
        file.write( md, templates.doc(values) );

        // Push a rendered markdown link into the readme "index"
        readme.push( templates.doclink(values) );
      }
    });

    // Write the readme with doc link index
    file.write( "README.md", templates.readme({ doclinks: readme.join("") }) );

    log.writeln("Docs created.");
  });
};
<|endoftext|>


<commit_before>module.exports = function (grunt) {
    'use strict';

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        src_files_js: ['js/so_tag.js'],
        src_files_css: ['css/*.css'],
        src_files_other: ['*.json', '*.php', 'LICENSE', 'README.md', '!package.json'],
        dest_dir_dev: 'build/dev/',
        dest_dir_rel: 'build/release/',
        dest_dir_dual: 'build/dual/',
        uglify: {
            options: {
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            build_release: {
                src: ['<%= src_files_js %>'],
                dest: '<%= dest_dir_rel %>js/so_tag.min.js'
            },
            build_dual: {
                src: ['<%= src_files_js %>'],
                dest: '<%= dest_dir_dual %>js/so_tag.min.js'
            }
        },
        jshint: {
            main: {
                src: ['<%= src_files_js %>']
            },
        },
        copy: {
            build_release: {
                src: ['<%= src_files_other %>'],
                dest: '<%= dest_dir_rel %>',
            },
            build_dev: {
                src: ['<%= src_files_js %>', '<%= src_files_css %>', '<%= src_files_other %>'],
                dest: '<%= dest_dir_dev %>',
            },
            build_dual: {
                src: ['<%= src_files_js %>', '<%= src_files_css %>', '<%= src_files_other %>'],
                dest: '<%= dest_dir_dual %>',
            }
        },
        cssmin: {
            build_release: {
                options : {
                    report: 'gzip'
                },
                expand: true,
                cwd: 'css/',
                src: ['*.css', '!*.min.css'],
                dest: '<%= dest_dir_rel %>/css/',
                ext: '.min.css'
            },
            build_dual: {
                options : {
                    report: 'gzip'
                },
                expand: true,
                cwd: 'css/',
                src: ['*.css', '!*.min.css'],
                dest: '<%= dest_dir_dual %>/css/',
                ext: '.min.css'
            }
        },
        clean: {
            build_release: {
                src: ['<%= dest_dir_rel %>*']
            },
            build_dev: {
                src: ['<%= dest_dir_dev %>*']
            },
            build_dual: {
                src: ['<%= dest_dir_dual %>*']
            }
        compress: {
            build_release: {
                options: {
                    archive: 'build/SOTag.VERSION.zip'
                },
                cwd: '<%= dest_dir_rel %>',
                src: ['**/*'],
                dest: 'SOTag/',
                expand: true
            },
            build_dev: {
                options: {
                    archive: 'build/SOTag.DEV.VERSION.zip'
                },
                cwd: '<%= dest_dir_dev %>',
                src: ['**/*'],
                dest: 'SOTag/',
                expand: true
            },
            build_dual: {
                options: {
                    archive: 'build/SOTag.dual.VERSION.zip'
                },
                cwd: '<%= dest_dir_dual %>',
                src: ['**/*'],
                dest: 'SOTag/',
                expand: true
            }
        }
    });

    // Load the plugin that provides the "uglify" task.
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-compress');

    // Default task(s).
    grunt.registerTask('build_dev', ['clean:build_dev', 'copy:build_dev', 'jshint', 'compress:build_dev']);
    grunt.registerTask('build_release', ['clean:build_release', 'copy:build_release', 'jshint', 'uglify:build_release', 'cssmin:build_release', 'compress:build_release']);
    grunt.registerTask('build_dual', ['clean:build_dual', 'copy:build_dual', 'jshint', 'uglify:build_dual', 'cssmin:build_dual', 'compress:build_dual']);
    grunt.registerTask('default', ['build_dev', 'build_release']);

};
<commit_msg>use real version in archive name<commit_after>module.exports = function (grunt) {
    'use strict';

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        src_files_js: ['js/so_tag.js'],
        src_files_css: ['css/*.css'],
        src_files_other: ['*.json', '*.php', 'LICENSE', 'README.md', '!package.json'],
        dest_dir_dev: 'build/dev/',
        dest_dir_rel: 'build/release/',
        dest_dir_dual: 'build/dual/',
        uglify: {
            options: {
                banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            build_release: {
                src: ['<%= src_files_js %>'],
                dest: '<%= dest_dir_rel %>js/so_tag.min.js'
            },
            build_dual: {
                src: ['<%= src_files_js %>'],
                dest: '<%= dest_dir_dual %>js/so_tag.min.js'
            }
        },
        jshint: {
            main: {
                src: ['<%= src_files_js %>']
            },
        },
        copy: {
            build_release: {
                src: ['<%= src_files_other %>'],
                dest: '<%= dest_dir_rel %>',
            },
            build_dev: {
                src: ['<%= src_files_js %>', '<%= src_files_css %>', '<%= src_files_other %>'],
                dest: '<%= dest_dir_dev %>',
            },
            build_dual: {
                src: ['<%= src_files_js %>', '<%= src_files_css %>', '<%= src_files_other %>'],
                dest: '<%= dest_dir_dual %>',
            }
        },
        cssmin: {
            build_release: {
                options : {
                    report: 'gzip'
                },
                expand: true,
                cwd: 'css/',
                src: ['*.css', '!*.min.css'],
                dest: '<%= dest_dir_rel %>/css/',
                ext: '.min.css'
            },
            build_dual: {
                options : {
                    report: 'gzip'
                },
                expand: true,
                cwd: 'css/',
                src: ['*.css', '!*.min.css'],
                dest: '<%= dest_dir_dual %>/css/',
                ext: '.min.css'
            }
        },
        clean: {
            build_release: {
                src: ['<%= dest_dir_rel %>*']
            },
            build_dev: {
                src: ['<%= dest_dir_dev %>*']
            },
            build_dual: {
                src: ['<%= dest_dir_dual %>*']
            }
        },
        compress: {
            build_release: {
                options: {
                    mode: 'zip',
                    archive: 'build/SOTag.<%= pkg.version %>.zip'
                },
                cwd: '<%= dest_dir_rel %>',
                src: ['**/*'],
                dest: 'SOTag/',
                expand: true
            },
            build_dev: {
                options: {
                    mode: 'zip',
                    archive: 'build/SOTag.DEV.<%= pkg.version %>.zip'
                },
                cwd: '<%= dest_dir_dev %>',
                src: ['**/*'],
                dest: 'SOTag/',
                expand: true
            },
            build_dual: {
                options: {
                    mode: 'zip',
                    archive: 'build/SOTag.FULL.<%= pkg.version %>.zip'
                },
                cwd: '<%= dest_dir_dual %>',
                src: ['**/*'],
                dest: 'SOTag/',
                expand: true
            }
        }
    });

    // Load the plugin that provides the "uglify" task.
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-compress');

    // Default task(s).
    grunt.registerTask('build_dev', ['clean:build_dev', 'copy:build_dev', 'jshint', 'compress:build_dev']);
    grunt.registerTask('build_release', ['clean:build_release', 'copy:build_release', 'jshint', 'uglify:build_release', 'cssmin:build_release', 'compress:build_release']);
    grunt.registerTask('build_dual', ['clean:build_dual', 'copy:build_dual', 'jshint', 'uglify:build_dual', 'cssmin:build_dual', 'compress:build_dual']);
    grunt.registerTask('default', ['build_dev', 'build_release']);

};
<|endoftext|>


<commit_before>var word;
var completed = 0;

$(document).ready(function() {
    init();

    $('#start').click(function() {
        // Hide the start button
        $('#start').css('display', 'none');

        // Show the other elements
        $('#word').css('display', 'inline');
        $('#letterbank').css('display', 'inline');
    });

    $('#newGame').click(function() {
        init();

        $('#newGame').css('display', 'none');

        // Show the other elements
        $('#word').css('display', 'inline');
        $('#guessed').css('display', 'inline');
        $('#letterbank').css('display', 'inline');
    });

    $('#letterbank button').click(function() {
        var guess = $(this).attr('value');

        guessLetter(guess);
    });
});

function init() {
    word = generateWord();
    console.log(word);

    generateButtons();
    generateBlanks();
};

// Generates buttons A-Z for use in guessing
function generateButtons() {
    var snippet = "";

    for (var i = 0; i < 26; i++) {
        snippet += '<button type="button" class="btn btn-default" value="' + String.fromCharCode(65 + i) + '">' + String.fromCharCode(65 + i) + '</button>'
    }

    $('#letterbank').html(snippet);
};

function generateWord() {
    var list = ["HOUSE", "COMPUTER", "MOUSE", "RHETORIC", "HERRING"];

    return list[Math.floor(Math.random() * list.length)];
};

// Takes the given word and generates blanks for that word
function generateBlanks() {
    var snippet = "";

    for (var i = 0; i < word.length; i++) {
        snippet += '
' + '_' + '

';
    }

    $('#word').html(snippet);
};

// Guess a letter
function guessLetter(guess) {
    // Get the position of the guess letter in the word
    var position = getPosition(guess);

    if (position.length === 1) {
        // Reveal the guessed letter
        $('div > #' + position).html(guess);
        completed += 1;

        // Disable button
        $('button[value=' + guess + ']').prop('disabled', 'disabled');
    } else if (position.length > 1) {
        for (var i = 0; i< position.length; i++) {
            // Reveal the guessed letter
            $('div > #' + position[i]).html(guess);
            completed += 1;
        }

        // Disable button
        $('button[value=' + guess + ']').prop('disabled', 'disabled');
    } else {
        // If the letter has not already been guessed
        if ($('#guessed').html().indexOf(guess) === -1) {
            // Disable button
            $('button[value=' + guess + ']').prop('disabled', 'disabled');

            // Add letter to guessed list
            $('#guessed').append(guess);
        }
    }

    if (checkWon()) {
        // New Game
        init();
    }
};

// Find all occurrences of a given letter in the word
function getPosition(letter) {
    var indices = [];

    for (var i = 0; i < word.length; i++) {
        if (letter === word.charAt(i)) {
            indices.push(i);
        }
    }

    return indices;
};

// Check if the player has won
function checkWon() {
    if (completed === word.length) {
        console.log("Winner!");
        alert('You win!');

        return true;
        /*$('#newGame').html('<button type="button" class="btn btn-lg btn-primary">New Game</button>').css('display', 'inline');

        // Hide the other elements
        $('#word').css('display', 'none');
        $('#guessed').css('display', 'none');
        $('#letterbank').css('display', 'none');*/
    }

    return false;
};<commit_msg>Game now resetting properly.<commit_after>var word;
var completed = 0;

$(document).ready(function() {
    init();

    $('#start').click(function() {
        // Hide the start button
        $('#start').css('display', 'none');

        // Show the other elements
        $('#word').css('display', 'inline');
        $('#letterbank').css('display', 'inline');
    });

    $('#newGame').click(function() {
        init();

        $('#newGame').css('display', 'none');

        // Show the other elements
        $('#word').css('display', 'inline');
        $('#guessed').css('display', 'inline');
        $('#letterbank').css('display', 'inline');
    });

    $('#letterbank button').click(function() {
        var guess = $(this).attr('value');

        guessLetter(guess);
    });
});

function init() {
    word = generateWord();
    console.log(word);

    generateButtons();
    generateBlanks();
};

function reset() {
    word = generateWord();
    completed = 0;
    console.log(word);

    generateBlanks();

    // Reset disabled state
    $('#letterbank button').prop('disabled', '');
    $('#guessed').html('');
};

// Generates buttons A-Z for use in guessing
function generateButtons() {
    var snippet = "";

    for (var i = 0; i < 26; i++) {
        snippet += '<button type="button" class="btn btn-default" value="' + String.fromCharCode(65 + i) + '">' + String.fromCharCode(65 + i) + '</button>'
    }

    $('#letterbank').html(snippet);
};

function generateWord() {
    var list = ["HOUSE", "COMPUTER", "MOUSE", "RHETORIC", "HERRING"];

    return list[Math.floor(Math.random() * list.length)];
};

// Takes the given word and generates blanks for that word
function generateBlanks() {
    var snippet = "";

    for (var i = 0; i < word.length; i++) {
        snippet += '
' + '_' + '

';
    }

    $('#word').html(snippet);
};

// Guess a letter
function guessLetter(guess) {
    // Get the position of the guess letter in the word
    var position = getPosition(guess);

    if (position.length === 1) {
        // Reveal the guessed letter
        $('div > #' + position).html(guess);
        completed += 1;

        // Disable button
        $('button[value=' + guess + ']').prop('disabled', 'disabled');
    } else if (position.length > 1) {
        for (var i = 0; i< position.length; i++) {
            // Reveal the guessed letter
            $('div > #' + position[i]).html(guess);
            completed += 1;
        }

        // Disable button
        $('button[value=' + guess + ']').prop('disabled', 'disabled');
    } else {
        // If the letter has not already been guessed
        if ($('#guessed').html().indexOf(guess) === -1) {
            // Disable button
            $('button[value=' + guess + ']').prop('disabled', 'disabled');

            // Add letter to guessed list
            $('#guessed').append(guess);
        }
    }

    if (checkWon()) {
        // New Game
        //init();
        reset();
    }
};

// Find all occurrences of a given letter in the word
function getPosition(letter) {
    var indices = [];

    for (var i = 0; i < word.length; i++) {
        if (letter === word.charAt(i)) {
            indices.push(i);
        }
    }

    return indices;
};

// Check if the player has won
function checkWon() {
    if (completed === word.length) {
        console.log("Winner!");
        alert('You win!');

        return true;
        /*$('#newGame').html('<button type="button" class="btn btn-lg btn-primary">New Game</button>').css('display', 'inline');

        // Hide the other elements
        $('#word').css('display', 'none');
        $('#guessed').css('display', 'none');
        $('#letterbank').css('display', 'none');*/
    }

    return false;
};<|endoftext|>