<commit_before>import Telescope from 'meteor/nova:lib';
import Folders from "./collection.js";
import Users from 'meteor/nova:users';

const canInsert = user => Users.canDo(user, "folders.new");
const canEdit = user => Users.canDo(user, "folders.edit.all");

// folder schema
Folders.schema = new SimpleSchema({
  name: {
    type: String,
    insertableIf: canInsert,
    editableIf: canEdit,
    publish: true
  },
  description: {
    type: String,
    optional: true,
    insertableIf: canInsert,
    editableIf: canEdit,
    publish: true,
    autoform: {
      rows: 3
    }
  },
  order: {
    type: Number,
    optional: true,
    insertableIf: canInsert,
    editableIf: canEdit,
    publish: true
  },
  slug: {
    type: String,
    optional: true,
    insertableIf: canInsert,
    editableIf: canEdit,
    publish: true
  },
  image: {
    type: String,
    optional: true,
    insertableIf: canInsert,
    editableIf: canEdit,
    publish: true
  }
  //parentId: {
  //  type: String,
  //  optional: true,
  //  insertableIf: canInsert,
  //  editableIf: canEdit,
  //  publish: true,
  //  autoform: {
  //    options: function () {
  //      var folders = Folders.find().map(function (folder) {
  //        return {
  //          value: folder._id,
  //          label: folder.name
  //        };
  //      });
  //      return folders;
  //    }
  //  }
  //}
});

// Meteor.startup(function(){
//   Folders.internationalize();
// });

Folders.attachSchema(Folders.schema);

Telescope.settings.collection.addField([
  {
    fieldName: 'foldersBehavior',
    fieldSchema: {
      type: String,
      optional: true,
      autoform: {
        group: 'folders',
        instructions: 'Let users filter by one or multiple folders at a time.',
        options: function () {
          return [
            {value: "single", label: "folders_behavior_one_at_a_time"},
            {value: "multiple", label: "folders_behavior_multiple"}
          ];
        }
      }
    }
  },
  {
    fieldName: 'hideEmptyFolders',
    fieldSchema: {
      type: Boolean,
      optional: true,
      autoform: {
        group: 'folders',
        instructions: 'Hide empty folders in navigation'
      }
    }
  }
]);<commit_msg>add nova-tags copy from nova-categories.<commit_after>import Telescope from 'meteor/nova:lib';
import Folders from "./collection.js";
import Users from 'meteor/nova:users';

const canInsert = user => Users.canDo(user, "folders.new");
const canEdit = user => Users.canDo(user, "folders.edit.all");

// folder schema
Folders.schema = new SimpleSchema({
    name: {
        type: String,
        insertableIf: canInsert,
        editableIf: canEdit,
        publish: true
    },
    description: {
        type: String,
        optional: true,
        insertableIf: canInsert,
        editableIf: canEdit,
        publish: true,
        autoform: {
            rows: 3
        }
    },
    order: {
        type: Number,
        optional: true,
        insertableIf: canInsert,
        editableIf: canEdit,
        publish: true
    },
    slug: {
        type: String,
        optional: true,
        insertableIf: canInsert,
        editableIf: canEdit,
        publish: true
    },
    image: {
        type: String,
        optional: true,
        insertableIf: canInsert,
        editableIf: canEdit,
        publish: true
    },
    /**
     The timestamp of comment creation
     */
    createdAt: {
        type: Date,
        optional: true,
        publish: false
    },
    /**
     The timestamp of the comment being posted. For now, comments are always created and posted at the same time
     */
    postedAt: {
        type: Date,
        optional: true,
        publish: true,
    },
    /**
     The comment author's `_id`
     */
    userId: {
        type: String,
        optional: true,
        publish: true,
        join: {
            joinAs: "user",
            collection: () => Meteor.users
        }
    },
    /**
     Whether the comment is deleted. Delete comments' content doesn't appear on the site.
     */
    isDeleted: {
        type: Boolean,
        optional: true,
        publish: true,
    },
    userIP: {
        type: String,
        optional: true,
        publish: false
    },
    userAgent: {
        type: String,
        optional: true,
        publish: false
    },
});

// Meteor.startup(function(){
//   Folders.internationalize();
// });

Folders.attachSchema(Folders.schema);

Telescope.settings.collection.addField([
    {
        fieldName: 'foldersBehavior',
        fieldSchema: {
            type: String,
            optional: true,
            autoform: {
                group: 'folders',
                instructions: 'Let users filter by one or multiple folders at a time.',
                options: function () {
                    return [
                        {value: "single", label: "folders_behavior_one_at_a_time"},
                        {value: "multiple", label: "folders_behavior_multiple"}
                    ];
                }
            }
        }
    },
    {
        fieldName: 'hideEmptyFolders',
        fieldSchema: {
            type: Boolean,
            optional: true,
            autoform: {
                group: 'folders',
                instructions: 'Hide empty folders in navigation'
            }
        }
    }
]);<|endoftext|>


<commit_before>var clicks = 0, presses = 0;
var img, img2, rad;
var bg = [];
var writer;

var canvas0, canvas1, canvas2;
var text0;
var burgers = [], burgerYs = [], burgerVs = [];
var img0, imgRot = 0;
var flower, flowerRot = 0;
var input;

var setup = function() {
	println("setup");

	// canvas0
	canvas0 = createCanvas(displayWidth(), 0.6*displayHeight());
	canvas0.mousePressed(mousePressed0);

	// canvas1
	canvas1 = createCanvas(500, displayHeight()*0.8);
	canvas1.position(0.25*canvas0.width, displayHeight()*0.2);

	// burgers
	for (var i=0; i<1; i++) {
		var b = createImage("http://24.media.tumblr.com/tumblr_mckjod8K3T1rjiujyo1_500.png");
		b.size(100, AUTO);
		burgerYs.push(random(-b.height, displayHeight()+b.height));
		burgerVs.push(random(1, 4));
		b.position(random(displayWidth()-b.width), burgerYs[i]);
		b.mousePressed(burgerHide);
		burgers.push(b);
	}

	// text
	text0 = createElement("hello world");
	text0.id("test0");
	text0.class("text");
	text0.size(500, 200);
	text0.position(canvas0.width-text0.width, canvas0.height*0.1);
	text0.mouseOver(boldText);
	text0.mouseOut(unboldText);
	text0.style('font-size: 80px; color:white;');

	// images
	flower = createImage("http://subno.net/wp-content/uploads/2013/07/pink-rose-white-backgroundrose-transparent-png-isolated-flower-roses-various-colours-for-pt3kbx0t.png");
	flower.size(400, AUTO);
	flower.position(100, canvas0.height - flower.height*0.5);
	flower.mousePressed(flowerMove);

	img0 = createImage("http://media.tumblr.com/fecdc135ce5bdf0016bcd71da93d2ecb/tumblr_inline_mkr3wrfR2m1qz4rgp.png");
	img0.size(AUTO, 300);
	img0.position(displayWidth()*0.5, canvas0.height-200);
	img0.mousePressed(imgPressed);

	// canvas2
	canvas2 = createCanvas(150, 150);
	canvas2.mousePressed(mousePressed2);
	canvas2.position(flower.x+flower.width/2-canvas2.width/2, flower.y+flower.height/2-canvas2.height/2);

	// input
	input = createElement('<input style="width:300px; font-size:24px;" id="filename" type="text" value="what is your name?" onchange="inputKey(value)">');
	input.position(50, 200);

	//colorMode(HSV);
	//printMatrix();
	writer = new PrintWriter("name1");
};

var draw = function() {

	context(canvas0);
	drawCanvas0();

	context(canvas1);
	drawCanvas1();

	context(canvas2);
	//background(255, 200, 10);
	noStroke();
	fill(200, 30, 0);
	ellipse(width/2, height/2, width, height);
	fill(200, 80, 10);
	strokeWeight(20);
	stroke(0, 100, 0, 50);
	ellipse(width/2, height/2, 0.75*width, 0.75*height);

	// burgers
	for (var i=0; i<burgers.length; i++) {
		burgerYs[i]+=burgerVs[i];
		if (burgerYs[i] > displayHeight() + burgers[i].height) burgerYs[i] = -burgers[i].height;
		burgers[i].position(burgers[i].x, burgerYs[i]);
	}

	// flower
	flowerRot += 1;
	flower.style("-webkit-transform: rotate("+flowerRot+"deg);");
};

var drawCanvas0 = function() {
	bg = [255*sin(.008*frameCount), 255*sin(.003*frameCount), 255*sin(.01*frameCount)];
	fill(bg[0], bg[1], bg[2]);
	noStroke();
	rect(0, 0, width, height);

	strokeWeight(15);
	stroke(255, 100, 0, 100);
	var c0 = [255, 255, 255];
	var c1 = [0, 0, 0];
	var c2 = lerpColor(c0, c1, 0.8);
	fill(c2[0], c2[1], c2[2]);

	for (var i=-500; i<canvas0.width; i+=100) {
		for (var j=-100; j<canvas0.height; j+=100) {
			//translate(width/2, height/4);
			pushMatrix();
			shearX(PI/4);
			rect(i, 50+j, 50, 70);
			popMatrix();
		}
	}

};

var drawCanvas1 = function() {

	//background(50, 50, 200);
	strokeWeight(10);
	for (var i=10; i<canvas1.width; i+=50) {
		for (var j=10; j<canvas1.height; j+=50) {
			stroke(0, 255-j/20, 200, 100);
			fill(bg[0], bg[1], bg[2]+i/4);
			rect(i, j, 30, 30);
		}
	}
};

// Individual elt mouse functions, attached in setup
var mousePressed0 = function(e) {
	// whatevs
	println("0 pressed");
};

// these get added by createCanvas
var mousePressed1 = function(e) {
	// whatevs
	println("1 pressed");
};

// these get added by createCanvas
var mousePressed2 = function(e) {
	// whatevs
	println("2 pressed");
};

var boldText = function(e) {
	println("0 over");
	text0.style('font-weight: bold');
};
var unboldText = function(e) {
	println("0 out");
	text0.style('font-weight: normal');
};

var imgPressed = function(e) {
	imgRot += 60;
	img0.style("-webkit-transform: rotate("+imgRot+"deg);");
};

var burgerHide = function(e, obj) {
	obj.hide();
}

var flowerMove = function(e, obj) {
	console.log(obj);
	obj.position(obj.x+random(-100, 100), obj.y+random(-100, 100));
}

var inputKey = function(text, obj) {
	text0.html("hello "+text+"!");
};

var mousePressed = function(e) {
	println("mouse pressed");
	//save("hi");
	//writer.close();
	//saveStrings(['hi', 'blah']);
	//console.log(e);
	clicks++;
};

var keyPressed = function(e) {
	keyCode = e.keyCode || e.which;
	key = String.fromCharCode(keyCode);
	println("key pressed "+keyCode+" "+key);
	writer.print(key);
	//alert('key pressed '+keyCode);
	presses++;
};

var keyReleased = function(e) {
	keyCode = e.keyCode || e.which;
	key = String.fromCharCode(keyCode);
};

var keyTyped = function(e) {
};

<commit_msg>tweaks<commit_after>var clicks = 0, presses = 0;
var img, img2, rad;
var bg = [];
var writer;

var canvas0, canvas1, canvas2;
var text0;
var burgers = [], burgerYs = [], burgerVs = [];
var imgs = [], imgRot = 0;
var flower, flowerRot = 0;
var input;

var setup = function() {
	println("setup");

	// canvas0
	canvas0 = createCanvas(displayWidth(), 0.6*displayHeight());
	canvas0.mousePressed(mousePressed0);

	// canvas1
	canvas1 = createCanvas(500, displayHeight()*0.8);
	canvas1.position(0.25*canvas0.width, displayHeight()*0.2);

	// burgers
	for (var i=0; i<20; i++) {
		var b = createImage("http://24.media.tumblr.com/tumblr_mckjod8K3T1rjiujyo1_500.png");
		b.size(100, AUTO);
		burgerYs.push(random(-b.height, displayHeight()+b.height));
		burgerVs.push(random(1, 4));
		b.position(random(displayWidth()-b.width), burgerYs[i]);
		b.mousePressed(burgerHide);
		burgers.push(b);
	}

	// text
	text0 = createElement("hello world");
	text0.id("test0");
	text0.class("text");
	text0.size(500, 200);
	text0.position(canvas0.width-text0.width, canvas0.height*0.1);
	text0.mouseOver(boldText);
	text0.mouseOut(unboldText);
	text0.style('font-size: 80px; color:white;');

	// images
	flower = createImage("http://25.media.tumblr.com/7f13c09f459ada46f117c3d7b9140391/tumblr_mm7j0p4RLg1spro0no1_500.gif");
	flower.size(500, AUTO);
	flower.position(100, canvas0.height - flower.height*0.5);
	flower.mousePressed(flowerMove);

	for (var i=0; i<8; i++) {
		var img = createImage("http://25.media.tumblr.com/6cde29708d8c92336066f83c7645920b/tumblr_mknxj3uAvz1s9b4wqo1_500.png");
		img.size(AUTO, 20*i+random(130, 170));
		img.position(flower.x+flower.width*0.75+i*displayWidth()/8, canvas0.height-img.height/2+random(-30, 30));
		img.mousePressed(imgPressed);
		imgs.push(img);
	}

	// canvas2
	canvas2 = createCanvas(100, 100);
	canvas2.mousePressed(mousePressed2);
	canvas2.position(flower.x+flower.width/2-canvas2.width/2, flower.y+flower.height/2-canvas2.height/2);

	// input
	input = createElement('<input style="width:300px; font-size:24px;" id="filename" type="text" value="what is your name?" onchange="inputKey(value)">');
	input.position(50, 200);

	//colorMode(HSV);
	//printMatrix();
	writer = new PrintWriter("name1");
};

var draw = function() {

	context(canvas0);
	drawCanvas0();

	context(canvas1);
	drawCanvas1();

	context(canvas2);
	drawCanvas2();

	// burgers
	for (var i=0; i<burgers.length; i++) {
		burgerYs[i]+=burgerVs[i];
		if (burgerYs[i] > displayHeight() + burgers[i].height) burgerYs[i] = -burgers[i].height;
		burgers[i].position(burgers[i].x, burgerYs[i]);
	}

	// flower
	flowerRot += 1;
	flower.style("-webkit-transform: rotate("+flowerRot+"deg);");
};

var drawCanvas0 = function() {
	bg = [255*sin(.008*frameCount), 255*sin(.003*frameCount), 255*sin(.01*frameCount)];
	fill(bg[0], bg[1], bg[2]);
	noStroke();
	rect(0, 0, width, height);

	strokeWeight(15);
	stroke(255, 100, 0, 100);
	var c0 = [255, 255, 255];
	var c1 = [0, 0, 0];
	var c2 = lerpColor(c0, c1, 0.8);
	fill(c2[0], c2[1], c2[2]);

	for (var i=-500; i<canvas0.width; i+=100) {
		for (var j=-100; j<canvas0.height; j+=100) {
			//translate(width/2, height/4);
			pushMatrix();
			shearX(PI/4);
			rect(i, 50+j, 50, 70);
			popMatrix();
		}
	}

};

var drawCanvas1 = function() {

	//background(50, 50, 200);
	strokeWeight(10);
	for (var i=10; i<canvas1.width; i+=50) {
		for (var j=10; j<canvas1.height; j+=50) {
			stroke(0, 255-j/20, 200, 100);
			fill(bg[0], bg[1], bg[2]+i/4);
			rect(i, j, 30, 30);
		}
	}
};

var drawCanvas2 = function() {
	//background(255, 200, 10);
	noStroke();
	fill(200, 30, 200);
	ellipse(width/2, height/2, width, height);
	fill(200, 80, 10);
	strokeWeight(30);
	stroke(0, 100, 0, 50);
	ellipse(width/2, height/2, 0.5*width, 0.5*height);
};

// Individual elt mouse functions, attached in setup
var mousePressed0 = function(e) {
	// whatevs
	println("0 pressed");
};

// these get added by createCanvas
var mousePressed1 = function(e) {
	// whatevs
	println("1 pressed");
};

// these get added by createCanvas
var mousePressed2 = function(e) {
	// whatevs
	println("2 pressed");
};

var boldText = function(e) {
	println("0 over");
	text0.style('font-weight: bold');
};
var unboldText = function(e) {
	println("0 out");
	text0.style('font-weight: normal');
};

var imgPressed = function(e, obj) {
	imgRot += random(-20, 20);
	obj.style("-webkit-transform: rotate("+imgRot+"deg);");
	obj.position(obj.x+random(-30, 30), obj.y+random(-30, 30));
};

var burgerHide = function(e, obj) {
	obj.hide();
}

var flowerMove = function(e, obj) {
	console.log(obj);
	obj.size(obj.width+20, obj.height+20);
	obj.position(obj.x-10, obj.y-10);
}

var inputKey = function(text, obj) {
	text0.html("hello "+text+"!");
};

var mousePressed = function(e) {
	println("mouse pressed");
	//save("hi");
	//writer.close();
	//saveStrings(['hi', 'blah']);
	//console.log(e);
	clicks++;
};

var keyPressed = function(e) {
	keyCode = e.keyCode || e.which;
	key = String.fromCharCode(keyCode);
	println("key pressed "+keyCode+" "+key);
	writer.print(key);
	//alert('key pressed '+keyCode);
	presses++;
};

var keyReleased = function(e) {
	keyCode = e.keyCode || e.which;
	key = String.fromCharCode(keyCode);
};

var keyTyped = function(e) {
};

<|endoftext|>


<commit_before>'use strict';

// This global var must be injected by the background page when creating this
// window. It will be read by the functions here, but will not be modified.
// See background.js for details.
//
// var TV_OPTS = {};

// Global vars with the current state.
var SOCKET_ID = null;
var SELF_IP = null;
var STATUS = {
	'connection_successful': null,  // null, true, false.
	'access_granted': null,  // null, true, false.
	'error': null  // null, String
};
var RECV_CALLBACK = null;
var IS_ALREADY_HANDLING_CLICK = false;

// error is the error message string.
function STATUS_reset(error) {
	STATUS.connection_successful = null;
	STATUS.access_granted = null;
	STATUS.error = null;
	if (error) {
		STATUS.error = error;
	}
	if (RECV_CALLBACK) {
		RECV_CALLBACK();
	}
}

//////////////////////////////////////////////////////////////////////
// Network-related functions, thin wrappers around Chrome API.

// Creates a new socket and connects to it.
// Chrome requires two API calls, which are encapsulated in here.
function easy_connect(ip, port, success_callback, failure_callback) {
	chrome.sockets.tcp.create({
		// bufferSize should be a power of two.
		// Given the extremely simple protocol implemented here, we can use a
		// very small buffer size.
		'bufferSize': 256
	}, function(createInfo) {
		chrome.sockets.tcp.connect(createInfo.socketId,
 		   ip, port, function(result) {
			   if (result < 0 || chrome.runtime.lastError) {
				   if (failure_callback) failure_callback(createInfo, result, chrome.runtime.lastError.message);
			   } else {
				   if (success_callback) success_callback(createInfo, result);
			   }
		   });
	});
}

// Chrome API requires an ArrayBuffer. This wrapper function is more lenient
// and accepts either an ArrayBuffer or a TypedArray (such as Uint8Array).
function easy_send(socketId, data, success_callback, failure_callback) {
	if (data.buffer) {  // If data is a TypedArray or DataView.
		data = data.buffer;  // Get the ArrayBuffer behind it.
	}
	chrome.sockets.tcp.send(socketId, data, function(sendInfo) {
		if (sendInfo.resultCode < 0 || chrome.runtime.lastError) {
			if (failure_callback) failure_callback(sendInfo.resultCode, chrome.runtime.lastError.message);
		} else if (sendInfo.resultCode == 0 && sendInfo.bytesSent != data.byteLength) {
			if (failure_callback) failure_callback(sendInfo.resultCode, 'Sent only ' + sendInfo.bytesSent + ' of ' + data.length + ' bytes.');
		} else {
			if (success_callback) success_callback();
		}
	});
}

//////////////////////////////////////////////////////////////////////
// Convenience functions, just to make the code easier to write without
// worrying about details.
//
// For convenience, only a single socket is kept open.

// Disconnects the current socket.
// Does nothing it there is no active socket.
// Disconnecting DOES NOT change STATUS. It is by design, to let the user see
// the last known status.
function disconnect(callback) {
	if (SOCKET_ID !== null) {
		// console.log('Disconnecting SOCKET_ID = ' + SOCKET_ID);
		chrome.sockets.tcp.close(SOCKET_ID, function() {
			// console.log('Disconnected.');
			SOCKET_ID = null;
			if (callback) callback();
		});
	} else {
		if (callback) callback();
	}
}

// Connects the socket.
// Automatically disconnects any previous socket.
function connect(callback, failure_callback) {
	disconnect(function() {
		// console.log('Starting up connection to ', TV_OPTS.tv_ip, TV_OPTS.tv_port);
		easy_connect(TV_OPTS.tv_ip, TV_OPTS.tv_port, function(socketInfo, result) {
			SOCKET_ID = socketInfo.socketId;
			SELF_IP = socketInfo.localAddress;
			STATUS.error = null;
			// console.log('Connected. SOCKET_ID = ' + SOCKET_ID + ', SELF_IP = ' + SELF_IP);
			if (callback) callback();
		}, function(socketInfo, result, message) {
			console.error('Connection error: ', result, message);
			STATUS_reset('Connection error: ' + message);
			if (failure_callback) failure_callback();
		});
	});
}

// Sends a packet.
function send(data, callback, failure_callback) {
	if (SOCKET_ID === null) {
		//throw 'Programming error! Socket is not connected!';
		// console.log('Not sending because there is no socket.');
		if (failure_callback) failure_callback();
		return;
	}
	// console.log('Sending a packet.');
	easy_send(SOCKET_ID, data, function() {
		// console.log('Sent a packet.');
		STATUS.error = null;
		if (callback) callback();
	}, function(result, message) {
		console.error('Send error: ', result, message);
		STATUS_reset('Send error: ' + message);
		if (failure_callback) failure_callback();
	});
}

// Receives a packet.
function on_receive_handler(info) {
	if (info.socketId != SOCKET_ID) {
		return;
	}

	var response = unpack_auth_response(info.data);
	var auth_response = understand_auth_response(response);
	console.log('Received: ', info.socketId, response.header, response.magic_string, response.payload, auth_response);

	if (response.header >= 0 && response.header <= 2) {
		STATUS.connection_successful = true;
	} else {
		STATUS.connection_successful = false;
	}

	if (auth_response == AuthResponse.GRANTED) {
		STATUS.access_granted = true;
	} else if (auth_response == AuthResponse.DENIED) {
		STATUS.access_granted = false;
	}

	if (RECV_CALLBACK) {
		RECV_CALLBACK();
	}

	if (auth_response == AuthResponse.DENIED) {
		//disconnect();
	}
}

function on_receive_error_handler(info) {
	if (info.socketId != SOCKET_ID) {
		return;
	}

	if (info.resultCode == -100) {
		// NET_CONNECTION_CLOSED, which is not an error.
		disconnect();
		return;
	}

	console.error('Error received: ', info.resultCode);
	STATUS_reset('Error received: ' + info.resultCode);
	disconnect();
}

//////////////////////////////////////////////////////////////////////
// High-level send-key functions.

function send_key(key_code, callback, failure_callback) {
	connect(function() {
		var auth_data = build_auth_packet(SELF_IP, TV_OPTS.unique_id, TV_OPTS.display_name);
		send(auth_data, function() {
			var key_packet = build_key_packet(key_code);
			send(key_packet, callback, failure_callback);
		}, failure_callback);
	}, failure_callback);
}

function send_multiple_keys_single_connection(keys, callback) {
	// Making a copy of the array, so that this function can make changes to
	// the copied array without changing the original one.
	var keys = keys.slice();

	var failure_callback = callback;

	function _send_multiple_keys_recursive() {
		if (keys.length < 1) {
			if (callback) callback();
			return;
		}

		var key = keys.shift();
		var key_packet = build_key_packet(key);
		send(key_packet, _send_multiple_keys_recursive, failure_callback);
	}

	connect(function() {
		var auth_data = build_auth_packet(SELF_IP, TV_OPTS.unique_id, TV_OPTS.display_name);
		send(auth_data, _send_multiple_keys_recursive, failure_callback);
	}, failure_callback);
}

function send_multiple_keys_multiple_connections(keys, callback) {
	// Making a copy of the array, so that this function can make changes to
	// the copied array without changing the original one.
	var keys = keys.slice();

	var failure_callback = callback;

	function _send_multiple_keys_recursive() {
		if (keys.length < 1) {
			if (callback) callback();
			return;
		}

		var key = keys.shift();
		send_key(key, function() {
			setTimeout(_send_multiple_keys_recursive, 50);
		}, failure_callback);
	}
	_send_multiple_keys_recursive();
}

//////////////////////////////////////////////////////////////////////
// Layout stuff.

function create_button_grid_from_layout(layout) {
	var section = document.createElement('section');
	section.classList.add('tvremote', 'grid');

	if (layout.fontSize) {
		section.style.fontSize = layout.fontSize;
	}

	var i, j, cell;
	var divrow, span, button;
	for (i = 0; i < layout.rows.length; i++) {
		divrow = document.createElement('div');
		divrow.classList.add('row');
		section.appendChild(divrow);

		for (j = 0; j < layout.rows[i].cells.length; j++) {
			cell = layout.rows[i].cells[j];

			if (cell.label === null) {
				span = document.createElement('span');
				span.classList.add('cell', 'empty');
				divrow.appendChild(span);
				continue;
			}

			button = document.createElement('button');
			button.appendChild(document.createTextNode(cell.label));
			button.dataset.key = cell.key;
			button.classList.add('cell', 'tvremotebutton');
			divrow.appendChild(button);

			if (cell.css) {
				button.className += ' ' + cell.css;
			}
		}
	}

	return section;
}

function build_layout(layout) {
	var layout_container = document.getElementById('layout_container');

	// Constructing the buttons.
	layout_container.innerHTML = '';

	if (layout.layout == 'grid') {
		layout_container.appendChild(create_button_grid_from_layout(layout));
	} else {
		alert('Invalid value: "layout": "' + layout.layout + '"');
	}
}

//////////////////////////////////////////////////////////////////////

function tvremote_key_click_handler(ev) {
	if (IS_ALREADY_HANDLING_CLICK) {
		// Ideally, the clicks would be queued. But the easiest solution is to
		// just ignore them.
		return;
	}

	var key = ev.target.dataset.key;
	if (key) {
		ev.preventDefault();
		ev.stopPropagation();

		IS_ALREADY_HANDLING_CLICK = true;

		// Splitting the comma-separated list. Also trimming the whitespace.
		var keys = key.split(',');
		var i;
		for (i = 0; i < keys.length; i++) {
			keys[i] = keys[i].trim();
		}

		if (TV_OPTS.macro_behavior === 'multiple_connections') {
			send_multiple_keys_multiple_connections(keys, function() {
				IS_ALREADY_HANDLING_CLICK = false;
			});
		} else if (TV_OPTS.macro_behavior === 'single_connection') {
			send_multiple_keys_single_connection(keys, function() {
				IS_ALREADY_HANDLING_CLICK = false;
			});
		} else {
			STATUS.error = '(Internal error) Unknown macro_behavior value: ' + TV_OPTS.macro_behavior;
			console.error(STATUS.error);
			update_status_ui();
		}
	}
}

function close_window() {
	window.close();
}

function open_options() {
	document.getElementById('options_button').blur();
	chrome.runtime.getBackgroundPage(function(background) {
		background.open_options_window();
	});
}

// Inserts a ZWSP character in sensible places, to make the text look better
// when broken.
// https://en.wikipedia.org/wiki/Zero-width_space
function insert_ZWSP(s) {
	return s.replace(/(:+)/g, '$1\u200B').replace(/(_+|\.+)/g, '\u200B$1');
}

function update_status_ui() {
	var status_container = document.getElementById('status_container');
	var status_label = document.getElementById('status_label');
	// var status_icon = document.getElementById('status_icon');

	status_container.classList.remove('gray', 'yellow', 'green', 'red');
	if (STATUS.error) {
		status_container.classList.add('red');
		status_label.value = insert_ZWSP(STATUS.error);
	} else if (STATUS.connection_successful === true) {
		if (STATUS.access_granted === true) {
			status_container.classList.add('green');
			status_label.value = 'Working correctly.';
		} else if (STATUS.access_granted === false) {
			status_container.classList.add('red');
			status_label.value = 'TV remote control access was DENIED.';
		} else {
			status_container.classList.add('yellow');
			status_label.value = 'Connection to the TV is working.';
		}
	} else if (STATUS.connection_successful === false) {
		status_container.classList.add('red');
		status_label.value = 'Connection failed.';
	} else {
		status_container.classList.add('gray');
		status_label.value = 'Not connected.';
	}
}

//////////////////////////////////////////////////////////////////////
// Initialization.

function init(tab_id, bgpage) {
	// Single click handler for all TV remote buttons.
	var layout_container = document.getElementById('layout_container');
	layout_container.addEventListener('click', tvremote_key_click_handler);

	build_layout(LAYOUT);

	// Status indicator.
	RECV_CALLBACK = update_status_ui;
	update_status_ui();

	// Close button.
	var close_button = document.getElementById('close_button');
	close_button.addEventListener('click', close_window);

	// Options button.
	var options_button = document.getElementById('options_button');
	options_button.addEventListener('click', open_options);

	// Handling TCP responses using the convoluted Chrome API.
	chrome.sockets.tcp.onReceive.addListener(on_receive_handler);
	chrome.sockets.tcp.onReceiveError.addListener(on_receive_error_handler);
}

// This script is being included with the "defer" attribute, which means it
// will only be executed after the document has been parsed.
init();
<commit_msg>Removing a leftover console.log.<commit_after>'use strict';

// This global var must be injected by the background page when creating this
// window. It will be read by the functions here, but will not be modified.
// See background.js for details.
//
// var TV_OPTS = {};

// Global vars with the current state.
var SOCKET_ID = null;
var SELF_IP = null;
var STATUS = {
	'connection_successful': null,  // null, true, false.
	'access_granted': null,  // null, true, false.
	'error': null  // null, String
};
var RECV_CALLBACK = null;
var IS_ALREADY_HANDLING_CLICK = false;

// error is the error message string.
function STATUS_reset(error) {
	STATUS.connection_successful = null;
	STATUS.access_granted = null;
	STATUS.error = null;
	if (error) {
		STATUS.error = error;
	}
	if (RECV_CALLBACK) {
		RECV_CALLBACK();
	}
}

//////////////////////////////////////////////////////////////////////
// Network-related functions, thin wrappers around Chrome API.

// Creates a new socket and connects to it.
// Chrome requires two API calls, which are encapsulated in here.
function easy_connect(ip, port, success_callback, failure_callback) {
	chrome.sockets.tcp.create({
		// bufferSize should be a power of two.
		// Given the extremely simple protocol implemented here, we can use a
		// very small buffer size.
		'bufferSize': 256
	}, function(createInfo) {
		chrome.sockets.tcp.connect(createInfo.socketId,
 		   ip, port, function(result) {
			   if (result < 0 || chrome.runtime.lastError) {
				   if (failure_callback) failure_callback(createInfo, result, chrome.runtime.lastError.message);
			   } else {
				   if (success_callback) success_callback(createInfo, result);
			   }
		   });
	});
}

// Chrome API requires an ArrayBuffer. This wrapper function is more lenient
// and accepts either an ArrayBuffer or a TypedArray (such as Uint8Array).
function easy_send(socketId, data, success_callback, failure_callback) {
	if (data.buffer) {  // If data is a TypedArray or DataView.
		data = data.buffer;  // Get the ArrayBuffer behind it.
	}
	chrome.sockets.tcp.send(socketId, data, function(sendInfo) {
		if (sendInfo.resultCode < 0 || chrome.runtime.lastError) {
			if (failure_callback) failure_callback(sendInfo.resultCode, chrome.runtime.lastError.message);
		} else if (sendInfo.resultCode == 0 && sendInfo.bytesSent != data.byteLength) {
			if (failure_callback) failure_callback(sendInfo.resultCode, 'Sent only ' + sendInfo.bytesSent + ' of ' + data.length + ' bytes.');
		} else {
			if (success_callback) success_callback();
		}
	});
}

//////////////////////////////////////////////////////////////////////
// Convenience functions, just to make the code easier to write without
// worrying about details.
//
// For convenience, only a single socket is kept open.

// Disconnects the current socket.
// Does nothing it there is no active socket.
// Disconnecting DOES NOT change STATUS. It is by design, to let the user see
// the last known status.
function disconnect(callback) {
	if (SOCKET_ID !== null) {
		// console.log('Disconnecting SOCKET_ID = ' + SOCKET_ID);
		chrome.sockets.tcp.close(SOCKET_ID, function() {
			// console.log('Disconnected.');
			SOCKET_ID = null;
			if (callback) callback();
		});
	} else {
		if (callback) callback();
	}
}

// Connects the socket.
// Automatically disconnects any previous socket.
function connect(callback, failure_callback) {
	disconnect(function() {
		// console.log('Starting up connection to ', TV_OPTS.tv_ip, TV_OPTS.tv_port);
		easy_connect(TV_OPTS.tv_ip, TV_OPTS.tv_port, function(socketInfo, result) {
			SOCKET_ID = socketInfo.socketId;
			SELF_IP = socketInfo.localAddress;
			STATUS.error = null;
			// console.log('Connected. SOCKET_ID = ' + SOCKET_ID + ', SELF_IP = ' + SELF_IP);
			if (callback) callback();
		}, function(socketInfo, result, message) {
			console.error('Connection error: ', result, message);
			STATUS_reset('Connection error: ' + message);
			if (failure_callback) failure_callback();
		});
	});
}

// Sends a packet.
function send(data, callback, failure_callback) {
	if (SOCKET_ID === null) {
		//throw 'Programming error! Socket is not connected!';
		// console.log('Not sending because there is no socket.');
		if (failure_callback) failure_callback();
		return;
	}
	// console.log('Sending a packet.');
	easy_send(SOCKET_ID, data, function() {
		// console.log('Sent a packet.');
		STATUS.error = null;
		if (callback) callback();
	}, function(result, message) {
		console.error('Send error: ', result, message);
		STATUS_reset('Send error: ' + message);
		if (failure_callback) failure_callback();
	});
}

// Receives a packet.
function on_receive_handler(info) {
	if (info.socketId != SOCKET_ID) {
		return;
	}

	var response = unpack_auth_response(info.data);
	var auth_response = understand_auth_response(response);
	// console.log('Received: ', info.socketId, response.header, response.magic_string, response.payload, auth_response);

	if (response.header >= 0 && response.header <= 2) {
		STATUS.connection_successful = true;
	} else {
		STATUS.connection_successful = false;
	}

	if (auth_response == AuthResponse.GRANTED) {
		STATUS.access_granted = true;
	} else if (auth_response == AuthResponse.DENIED) {
		STATUS.access_granted = false;
	}

	if (RECV_CALLBACK) {
		RECV_CALLBACK();
	}

	if (auth_response == AuthResponse.DENIED) {
		//disconnect();
	}
}

function on_receive_error_handler(info) {
	if (info.socketId != SOCKET_ID) {
		return;
	}

	if (info.resultCode == -100) {
		// NET_CONNECTION_CLOSED, which is not an error.
		disconnect();
		return;
	}

	console.error('Error received: ', info.resultCode);
	STATUS_reset('Error received: ' + info.resultCode);
	disconnect();
}

//////////////////////////////////////////////////////////////////////
// High-level send-key functions.

function send_key(key_code, callback, failure_callback) {
	connect(function() {
		var auth_data = build_auth_packet(SELF_IP, TV_OPTS.unique_id, TV_OPTS.display_name);
		send(auth_data, function() {
			var key_packet = build_key_packet(key_code);
			send(key_packet, callback, failure_callback);
		}, failure_callback);
	}, failure_callback);
}

function send_multiple_keys_single_connection(keys, callback) {
	// Making a copy of the array, so that this function can make changes to
	// the copied array without changing the original one.
	var keys = keys.slice();

	var failure_callback = callback;

	function _send_multiple_keys_recursive() {
		if (keys.length < 1) {
			if (callback) callback();
			return;
		}

		var key = keys.shift();
		var key_packet = build_key_packet(key);
		send(key_packet, _send_multiple_keys_recursive, failure_callback);
	}

	connect(function() {
		var auth_data = build_auth_packet(SELF_IP, TV_OPTS.unique_id, TV_OPTS.display_name);
		send(auth_data, _send_multiple_keys_recursive, failure_callback);
	}, failure_callback);
}

function send_multiple_keys_multiple_connections(keys, callback) {
	// Making a copy of the array, so that this function can make changes to
	// the copied array without changing the original one.
	var keys = keys.slice();

	var failure_callback = callback;

	function _send_multiple_keys_recursive() {
		if (keys.length < 1) {
			if (callback) callback();
			return;
		}

		var key = keys.shift();
		send_key(key, function() {
			setTimeout(_send_multiple_keys_recursive, 50);
		}, failure_callback);
	}
	_send_multiple_keys_recursive();
}

//////////////////////////////////////////////////////////////////////
// Layout stuff.

function create_button_grid_from_layout(layout) {
	var section = document.createElement('section');
	section.classList.add('tvremote', 'grid');

	if (layout.fontSize) {
		section.style.fontSize = layout.fontSize;
	}

	var i, j, cell;
	var divrow, span, button;
	for (i = 0; i < layout.rows.length; i++) {
		divrow = document.createElement('div');
		divrow.classList.add('row');
		section.appendChild(divrow);

		for (j = 0; j < layout.rows[i].cells.length; j++) {
			cell = layout.rows[i].cells[j];

			if (cell.label === null) {
				span = document.createElement('span');
				span.classList.add('cell', 'empty');
				divrow.appendChild(span);
				continue;
			}

			button = document.createElement('button');
			button.appendChild(document.createTextNode(cell.label));
			button.dataset.key = cell.key;
			button.classList.add('cell', 'tvremotebutton');
			divrow.appendChild(button);

			if (cell.css) {
				button.className += ' ' + cell.css;
			}
		}
	}

	return section;
}

function build_layout(layout) {
	var layout_container = document.getElementById('layout_container');

	// Constructing the buttons.
	layout_container.innerHTML = '';

	if (layout.layout == 'grid') {
		layout_container.appendChild(create_button_grid_from_layout(layout));
	} else {
		alert('Invalid value: "layout": "' + layout.layout + '"');
	}
}

//////////////////////////////////////////////////////////////////////

function tvremote_key_click_handler(ev) {
	if (IS_ALREADY_HANDLING_CLICK) {
		// Ideally, the clicks would be queued. But the easiest solution is to
		// just ignore them.
		return;
	}

	var key = ev.target.dataset.key;
	if (key) {
		ev.preventDefault();
		ev.stopPropagation();

		IS_ALREADY_HANDLING_CLICK = true;

		// Splitting the comma-separated list. Also trimming the whitespace.
		var keys = key.split(',');
		var i;
		for (i = 0; i < keys.length; i++) {
			keys[i] = keys[i].trim();
		}

		if (TV_OPTS.macro_behavior === 'multiple_connections') {
			send_multiple_keys_multiple_connections(keys, function() {
				IS_ALREADY_HANDLING_CLICK = false;
			});
		} else if (TV_OPTS.macro_behavior === 'single_connection') {
			send_multiple_keys_single_connection(keys, function() {
				IS_ALREADY_HANDLING_CLICK = false;
			});
		} else {
			STATUS.error = '(Internal error) Unknown macro_behavior value: ' + TV_OPTS.macro_behavior;
			console.error(STATUS.error);
			update_status_ui();
		}
	}
}

function close_window() {
	window.close();
}

function open_options() {
	document.getElementById('options_button').blur();
	chrome.runtime.getBackgroundPage(function(background) {
		background.open_options_window();
	});
}

// Inserts a ZWSP character in sensible places, to make the text look better
// when broken.
// https://en.wikipedia.org/wiki/Zero-width_space
function insert_ZWSP(s) {
	return s.replace(/(:+)/g, '$1\u200B').replace(/(_+|\.+)/g, '\u200B$1');
}

function update_status_ui() {
	var status_container = document.getElementById('status_container');
	var status_label = document.getElementById('status_label');
	// var status_icon = document.getElementById('status_icon');

	status_container.classList.remove('gray', 'yellow', 'green', 'red');
	if (STATUS.error) {
		status_container.classList.add('red');
		status_label.value = insert_ZWSP(STATUS.error);
	} else if (STATUS.connection_successful === true) {
		if (STATUS.access_granted === true) {
			status_container.classList.add('green');
			status_label.value = 'Working correctly.';
		} else if (STATUS.access_granted === false) {
			status_container.classList.add('red');
			status_label.value = 'TV remote control access was DENIED.';
		} else {
			status_container.classList.add('yellow');
			status_label.value = 'Connection to the TV is working.';
		}
	} else if (STATUS.connection_successful === false) {
		status_container.classList.add('red');
		status_label.value = 'Connection failed.';
	} else {
		status_container.classList.add('gray');
		status_label.value = 'Not connected.';
	}
}

//////////////////////////////////////////////////////////////////////
// Initialization.

function init(tab_id, bgpage) {
	// Single click handler for all TV remote buttons.
	var layout_container = document.getElementById('layout_container');
	layout_container.addEventListener('click', tvremote_key_click_handler);

	build_layout(LAYOUT);

	// Status indicator.
	RECV_CALLBACK = update_status_ui;
	update_status_ui();

	// Close button.
	var close_button = document.getElementById('close_button');
	close_button.addEventListener('click', close_window);

	// Options button.
	var options_button = document.getElementById('options_button');
	options_button.addEventListener('click', open_options);

	// Handling TCP responses using the convoluted Chrome API.
	chrome.sockets.tcp.onReceive.addListener(on_receive_handler);
	chrome.sockets.tcp.onReceiveError.addListener(on_receive_error_handler);
}

// This script is being included with the "defer" attribute, which means it
// will only be executed after the document has been parsed.
init();
<|endoftext|>


<commit_before>var Twit = require('twit');
<<<<<<>>>>>> master

var T = new Twit({
    consumer_key: credentials.consumer_key,
    consumer_secret: credentials.consumer_secret,
    access_token: credentials.access_token,
    access_token_secret: credentials.access_token_secret
});

console.log("Reading in the last 20 tweets with search: #collectiveacademy");
T.get('search/tweets', { q: 'collectiveacademy', count: 20 }, function(err, reply) {
    if (err) {
        console.dir(err);
    } else {
        for (var i = 0; i < reply.statuses.length; i++) {
              var status = reply.statuses[i];

              toWrite += '  username: ' + status.user.name;
              toWrite += '  time/date: ' + status.created_at;
              toWrite += "

";

//            if (i===reply.statuses.length) toWrite += "'><";
//            console.log('*************************');
//            console.log('  username: ' + status.user.name);
//            console.log('   ' + status.text);
//            console.log('  time/date: ' + status.created_at);
//            console.log('*************************');
//            console.log(status);

        }
//
    }
});

var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080);

server.route({path: '/', method:'GET', handler: function handler(request, reply) {
 reply("<title>"+ "Sup"+"</title>" + toWrite + "");
   }

});

server.start();
console.log("server going");
<commit_msg>Update twittest.js<commit_after>var Twit = require('twit');

var Hapi = require('hapi');

var toWrite = "";

var credentials = require('./credentials.js');

var T = new Twit({
    consumer_key: credentials.consumer_key,
    consumer_secret: credentials.consumer_secret,
    access_token: credentials.access_token,
    access_token_secret: credentials.access_token_secret
});

console.log("Reading in the last 20 tweets with search: #collectiveacademy");
T.get('search/tweets', { q: 'collectiveacademy', count: 20 }, function(err, reply) {
    if (err) {
        console.dir(err);
    } else {
        for (var i = 0; i < reply.statuses.length; i++) {
              var status = reply.statuses[i];

              toWrite += '  username: ' + status.user.name;
              toWrite += '  time/date: ' + status.created_at;
              toWrite += "

";

//            if (i===reply.statuses.length) toWrite += "'><";
//            console.log('*************************');
//            console.log('  username: ' + status.user.name);
//            console.log('   ' + status.text);
//            console.log('  time/date: ' + status.created_at);
//            console.log('*************************');
//            console.log(status);

        }
//
    }
});

var server = Hapi.createServer('localhost', Number(process.argv[2]) || 8080);

server.route({path: '/', method:'GET', handler: function handler(request, reply) {
 reply("<title>"+ "Sup"+"</title>" + toWrite + "");
   }

});

server.start();
console.log("server going");
<|endoftext|>


<commit_before>/**
 * typology.js - a type checking library for Node.js and the browser,
 *
 * Version: 0.1.0
 * Sources: http://github.com/jacomyal/typology
 * Doc:     http://github.com/jacomyal/typology#readme
 *
 * License:
 * --------
 * Copyright © 2014 Alexis Jacomy (@jacomyal), Guillaume Plique (@Yomguithereal)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * The Software is provided "as is", without warranty of any kind, express or
 * implied, including but not limited to the warranties of merchantability,
 * fitness for a particular purpose and noninfringement. In no event shall the
 * authors or copyright holders be liable for any claim, damages or other
 * liability, whether in an action of contract, tort or otherwise, arising
 * from, out of or in connection with the software or the use or other dealings
 * in the Software.
 */
;(function(global) {
  'use strict';

  var k,
      className,
      classes = (
        'Boolean Number String Function Array Date RegExp Object'
      ).split(' '),
      class2type = {},
      nativeTypes = ['*'],
      customTypes = {};

  // Fill types
  for (k in classes) {
    className = classes[k];
    nativeTypes.push(className.toLowerCase());
    class2type['[object ' + className + ']'] = className.toLowerCase();
  }

  var types = {
    version: '0.1.0',
    add: function(a1, a2) {
      var o,
          k,
          a,
          id,
          tmp,
          type;

      // Polymorphism:
      if (arguments.length === 1) {
        if (this.get(a1) === 'object') {
          o = a1;
          id = o.id;
          type = o.type;
        } else
          throw new Error('If types.add is called with one argument, ' +
                          'this one has to be an object.');
      } else if (arguments.length === 2) {
        if (typeof a1 !== 'string' || !a1)
          throw new Error('If types.add is called with more than one ' +
                          'argument, the first one must be the string id.');
        else
          id = a1;

        type = a2;
      } else
        throw new Error('types.add has to be called ' +
                        'with one or three arguments.');

      if (this.get(id) !== 'string' || id.length === 0)
        throw new Error('A type requires an string id.');

      if (customTypes[id] !== undefined && customTypes[id] !== 'proto')
        throw new Error('The type "' + id + '" already exists.');

      if (~nativeTypes.indexOf(id))
        throw new Error('"' + id + '" is a reserved type name.');

      customTypes[id] = 1;

      // Check given prototypes:
      a = (o || {}).proto || [];
      a = Array.isArray(a) ? a : [a];
      tmp = {};
      for (k in a)
        if (customTypes[a[k]] === undefined) {
          customTypes[a[k]] = 1;
          tmp[a[k]] = 1;
        }

      if ((this.get(type) !== 'function') && !this.isValid(type))
        throw new Error('A type requires a valid definition. ' +
                        'This one can be a preexistant type or else ' +
                        'a function testing given objects.');

      // Effectively add the type:
      customTypes[id] = (o === undefined) ?
        {
          id: id,
          type: type
        } :
        {};

      if (o !== undefined)
        for (k in o)
          customTypes[id][k] = o[k];

      // Delete prototypes:
      for (k in tmp)
        if (k !== id)
          delete customTypes[k];
    },
    has: function(key) {
      return !!customTypes[key];
    },
    get: function(obj) {
      return (obj === null || obj === undefined) ?
        String(obj) :
        class2type[Object.prototype.toString.call(obj)] || 'object';
    },
    check: function(obj, type) {
      var a,
          i,
          k,
          typeOf = this.get(obj);

      if (this.get(type) === 'string') {
        a = type.replace(/^\?/, '').split(/\|/);
        for (i in a)
          if (nativeTypes.indexOf(a[i]) < 0 && !(a[i] in customTypes)) {
            throw new Error('Invalid type.');
            return false;
          }

        if (obj === null || obj === undefined)
          return !!type.match(/^\?/, '');
        else
          type = type.replace(/^\?/, '');

        for (i in a)
          if (customTypes[a[i]])
            if (
              (typeof customTypes[a[i]].type === 'function') ?
              (customTypes[a[i]].type(obj) === true) :
              this.check(obj, customTypes[a[i]].type)
            )
              return true;

        return !!(~a.indexOf('*') || ~a.indexOf(typeOf));
      } else if (this.get(type) === 'object') {
        if (typeOf !== 'object')
          return false;
        for (k in type)
          if (!this.check(obj[k], type[k]))
            return false;

        for (k in obj)
          if (type[k] === undefined)
            return false;

        return true;
      } else if (this.get(type) === 'array') {
        if (typeOf !== 'array')
          return false;

        if (type.length !== 1) {
          throw new Error('Invalid type.');
        }

        for (k in obj)
          if (!this.check(obj[k], type[0]))
            return false;

        return true;
      } else
        return false;
    },
    isValid: function(type) {
      var a,
          k,
          i;

      if (this.get(type) === 'string') {
        a = type.replace(/^\?/, '').split(/\|/);
        for (i in a)
          if (nativeTypes.indexOf(a[i]) < 0 && !(a[i] in customTypes))
            return false;
        return true;

      } else if (this.get(type) === 'object') {
        for (k in type)
          if (!this.isValid(type[k]))
            return false;
        return true;

      } else if (this.get(type) === 'array')
        return type.length === 1 ?
          this.isValid(type[0]) :
          false;
      else
        return false;
    }
  };

  // Add a type "type" to shortcut the isValid method:
  types.add('type', function(v) {
    return types.isValid(v);
  });

  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports)
      exports = module.exports = types;
    exports.types = types;
  }
  global.types = types;
})(this);
<commit_msg>minor gjslint fix<commit_after>/**
 * typology.js - a type checking library for Node.js and the browser,
 *
 * Version: 0.1.0
 * Sources: http://github.com/jacomyal/typology
 * Doc:     http://github.com/jacomyal/typology#readme
 *
 * License:
 * --------
 * Copyright © 2014 Alexis Jacomy (@jacomyal), Guillaume Plique (@Yomguithereal)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * The Software is provided "as is", without warranty of any kind, express or
 * implied, including but not limited to the warranties of merchantability,
 * fitness for a particular purpose and noninfringement. In no event shall the
 * authors or copyright holders be liable for any claim, damages or other
 * liability, whether in an action of contract, tort or otherwise, arising
 * from, out of or in connection with the software or the use or other dealings
 * in the Software.
 */
(function(global) {
  'use strict';

  var k,
      className,
      classes = (
        'Boolean Number String Function Array Date RegExp Object'
      ).split(' '),
      class2type = {},
      nativeTypes = ['*'],
      customTypes = {};

  // Fill types
  for (k in classes) {
    className = classes[k];
    nativeTypes.push(className.toLowerCase());
    class2type['[object ' + className + ']'] = className.toLowerCase();
  }

  var types = {
    version: '0.1.0',
    add: function(a1, a2) {
      var o,
          k,
          a,
          id,
          tmp,
          type;

      // Polymorphism:
      if (arguments.length === 1) {
        if (this.get(a1) === 'object') {
          o = a1;
          id = o.id;
          type = o.type;
        } else
          throw new Error('If types.add is called with one argument, ' +
                          'this one has to be an object.');
      } else if (arguments.length === 2) {
        if (typeof a1 !== 'string' || !a1)
          throw new Error('If types.add is called with more than one ' +
                          'argument, the first one must be the string id.');
        else
          id = a1;

        type = a2;
      } else
        throw new Error('types.add has to be called ' +
                        'with one or three arguments.');

      if (this.get(id) !== 'string' || id.length === 0)
        throw new Error('A type requires an string id.');

      if (customTypes[id] !== undefined && customTypes[id] !== 'proto')
        throw new Error('The type "' + id + '" already exists.');

      if (~nativeTypes.indexOf(id))
        throw new Error('"' + id + '" is a reserved type name.');

      customTypes[id] = 1;

      // Check given prototypes:
      a = (o || {}).proto || [];
      a = Array.isArray(a) ? a : [a];
      tmp = {};
      for (k in a)
        if (customTypes[a[k]] === undefined) {
          customTypes[a[k]] = 1;
          tmp[a[k]] = 1;
        }

      if ((this.get(type) !== 'function') && !this.isValid(type))
        throw new Error('A type requires a valid definition. ' +
                        'This one can be a preexistant type or else ' +
                        'a function testing given objects.');

      // Effectively add the type:
      customTypes[id] = (o === undefined) ?
        {
          id: id,
          type: type
        } :
        {};

      if (o !== undefined)
        for (k in o)
          customTypes[id][k] = o[k];

      // Delete prototypes:
      for (k in tmp)
        if (k !== id)
          delete customTypes[k];
    },
    has: function(key) {
      return !!customTypes[key];
    },
    get: function(obj) {
      return (obj === null || obj === undefined) ?
        String(obj) :
        class2type[Object.prototype.toString.call(obj)] || 'object';
    },
    check: function(obj, type) {
      var a,
          i,
          k,
          typeOf = this.get(obj);

      if (this.get(type) === 'string') {
        a = type.replace(/^\?/, '').split(/\|/);
        for (i in a)
          if (nativeTypes.indexOf(a[i]) < 0 && !(a[i] in customTypes)) {
            throw new Error('Invalid type.');
            return false;
          }

        if (obj === null || obj === undefined)
          return !!type.match(/^\?/, '');
        else
          type = type.replace(/^\?/, '');

        for (i in a)
          if (customTypes[a[i]])
            if (
              (typeof customTypes[a[i]].type === 'function') ?
              (customTypes[a[i]].type(obj) === true) :
              this.check(obj, customTypes[a[i]].type)
            )
              return true;

        return !!(~a.indexOf('*') || ~a.indexOf(typeOf));
      } else if (this.get(type) === 'object') {
        if (typeOf !== 'object')
          return false;
        for (k in type)
          if (!this.check(obj[k], type[k]))
            return false;

        for (k in obj)
          if (type[k] === undefined)
            return false;

        return true;
      } else if (this.get(type) === 'array') {
        if (typeOf !== 'array')
          return false;

        if (type.length !== 1) {
          throw new Error('Invalid type.');
        }

        for (k in obj)
          if (!this.check(obj[k], type[0]))
            return false;

        return true;
      } else
        return false;
    },
    isValid: function(type) {
      var a,
          k,
          i;

      if (this.get(type) === 'string') {
        a = type.replace(/^\?/, '').split(/\|/);
        for (i in a)
          if (nativeTypes.indexOf(a[i]) < 0 && !(a[i] in customTypes))
            return false;
        return true;

      } else if (this.get(type) === 'object') {
        for (k in type)
          if (!this.isValid(type[k]))
            return false;
        return true;

      } else if (this.get(type) === 'array')
        return type.length === 1 ?
          this.isValid(type[0]) :
          false;
      else
        return false;
    }
  };

  // Add a type "type" to shortcut the isValid method:
  types.add('type', function(v) {
    return types.isValid(v);
  });

  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports)
      exports = module.exports = types;
    exports.types = types;
  }
  global.types = types;
})(this);
<|endoftext|>


<commit_before>// Underscore.js
// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the terms of the MIT license.
// Portions of Underscore are inspired by or borrowed from Prototype.js,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore

(function() {
  // ------------------------- Baseline setup ---------------------------------

  // Establish the root object, "window" in the browser, or "global" on the server.
  var root = this;

  // Save the previous value of the "_" variable.
  var previousUnderscore = root._;

  // Establish the object that gets thrown to break out of a loop iteration.
  var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__';

  // Quick regexp-escaping function, because JS doesn't have RegExp.escape().
  var escapeRegExp = function(s) { return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); };

  // Save bytes in the minified (but not gzipped) version:
  var ArrayProto = Array.prototype, ObjProto = Object.prototype;

  // Create quick reference variables for speed access to core prototypes.
  var slice                 = ArrayProto.slice,
      unshift               = ArrayProto.unshift,
      toString              = ObjProto.toString,
      hasOwnProperty        = ObjProto.hasOwnProperty,
      propertyIsEnumerable  = ObjProto.propertyIsEnumerable;

  // All ECMA5 native implementations we hope to use are declared here.
  var
    nativeForEach      = ArrayProto.forEach,
    nativeMap          = ArrayProto.map,
    nativeReduce       = ArrayProto.reduce,
    nativeReduceRight  = ArrayProto.reduceRight,
    nativeFilter       = ArrayProto.filter,
    nativeEvery        = ArrayProto.every,
    nativeSome         = ArrayProto.some,
    nativeIndexOf      = ArrayProto.indexOf,
    nativeLastIndexOf  = ArrayProto.lastIndexOf,
    nativeIsArray      = Array.isArray,
    nativeKeys         = Object.keys;

  // Create a safe reference to the Underscore object for use below.
  var _ = function(obj) { return new wrapper(obj); };

  // Export the Underscore object for CommonJS.
  if (typeof exports !== 'undefined') exports._ = _;

  // Export underscore to global scope.
  root._ = _;

  // Current version.
  _.VERSION = '1.0.2';

  // ------------------------ Collection Functions: ---------------------------

  // The cornerstone, an each implementation.
  // Handles objects implementing forEach, arrays, and raw objects.
  // Delegates to JavaScript 1.6's native forEach if available.
  var each = _.forEach = function(obj, iterator, context) {
    try {
      if (nativeForEach && obj.forEach === nativeForEach) {
        obj.forEach(iterator, context);
      } else if (_.isNumber(obj.length)) {
        for (var i = 0, l = obj.length; i < l; i++) iterator.call(context, obj[i], i, obj);
      } else {
        for (var key in obj) {
          if (hasOwnProperty.call(obj, key)) iterator.call(context, obj[key], key, obj);
        }
      }
    } catch(e) {
      if (e != breaker) throw e;
    }
    return obj;
  };

  // Return the results of applying the iterator to each element.
  // Delegates to JavaScript 1.6's native map if available.
  _.map = function(obj, iterator, context) {
    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
    var results = [];
    each(obj, function(value, index, list) {
      results.push(iterator.call(context, value, index, list));
    });
    return results;
  };

  // Reduce builds up a single result from a list of values, aka inject, or foldl.
  // Delegates to JavaScript 1.8's native reduce if available.
  _.reduce = function(obj, memo, iterator, context) {
    if (nativeReduce && obj.reduce === nativeReduce) return obj.reduce(_.bind(iterator, context), memo);
    each(obj, function(value, index, list) {
      memo = iterator.call(context, memo, value, index, list);
    });
    return memo;
  };

  // The right-associative version of reduce, also known as foldr. Uses
  // Delegates to JavaScript 1.8's native reduceRight if available.
  _.reduceRight = function(obj, memo, iterator, context) {
    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) return obj.reduceRight(_.bind(iterator, context), memo);
    var reversed = _.clone(_.toArray(obj)).reverse();
    return _.reduce(reversed, memo, iterator, context);
  };

  // Return the first value which passes a truth test.
  _.detect = function(obj, iterator, context) {
    var result;
    each(obj, function(value, index, list) {
      if (iterator.call(context, value, index, list)) {
        result = value;
        _.breakLoop();
      }
    });
    return result;
  };

  // Return all the elements that pass a truth test.
  // Delegates to JavaScript 1.6's native filter if available.
  _.filter = function(obj, iterator, context) {
    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
    var results = [];
    each(obj, function(value, index, list) {
      iterator.call(context, value, index, list) && results.push(value);
    });
    return results;
  };

  // Return all the elements for which a truth test fails.
  _.reject = function(obj, iterator, context) {
    var results = [];
    each(obj, function(value, index, list) {
      !iterator.call(context, value, index, list) && results.push(value);
    });
    return results;
  };

  // Determine whether all of the elements match a truth test.
  // Delegates to JavaScript 1.6's native every if available.
  _.every = function(obj, iterator, context) {
    iterator = iterator || _.identity;
    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
    var result = true;
    each(obj, function(value, index, list) {
      if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
    });
    return result;
  };

  // Determine if at least one element in the object matches a truth test.
  // Delegates to JavaScript 1.6's native some if available.
  _.some = function(obj, iterator, context) {
    iterator = iterator || _.identity;
    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
    var result = false;
    each(obj, function(value, index, list) {
      if (result = iterator.call(context, value, index, list)) _.breakLoop();
    });
    return result;
  };

  // Determine if a given value is included in the array or object using '==='.
  _.include = function(obj, target) {
    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
    var found = false;
    each(obj, function(value) {
      if (found = value === target) _.breakLoop();
    });
    return found;
  };

  // Invoke a method with arguments on every item in a collection.
  _.invoke = function(obj, method) {
    var args = _.rest(arguments, 2);
    return _.map(obj, function(value) {
      return (method ? value[method] : value).apply(value, args);
    });
  };

  // Convenience version of a common use case of map: fetching a property.
  _.pluck = function(obj, key) {
    return _.map(obj, function(value){ return value[key]; });
  };

  // Return the maximum item or (item-based computation).
  _.max = function(obj, iterator, context) {
    if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
    var result = {computed : -Infinity};
    each(obj, function(value, index, list) {
      var computed = iterator ? iterator.call(context, value, index, list) : value;
      computed >= result.computed && (result = {value : value, computed : computed});
    });
    return result.value;
  };

  // Return the minimum element (or element-based computation).
  _.min = function(obj, iterator, context) {
    if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
    var result = {computed : Infinity};
    each(obj, function(value, index, list) {
      var computed = iterator ? iterator.call(context, value, index, list) : value;
      computed < result.computed && (result = {value : value, computed : computed});
    });
    return result.value;
  };

  // Sort the object's values by a criterion produced by an iterator.
  _.sortBy = function(obj, iterator, context) {
    return _.pluck(_.map(obj, function(value, index, list) {
      return {
        value : value,
        criteria : iterator.call(context, value, index, list)
      };
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }), 'value');
  };

  // Use a comparator function to figure out at what index an object should
  // be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iterator) {
    iterator = iterator || _.identity;
    var low = 0, high = array.length;
    while (low < high) {
      var mid = (low + high) >> 1;
      iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
    }
    return low;
  };

  // Convert anything iterable into a real, live array.
  _.toArray = function(iterable) {
    if (!iterable)                return [];
    if (iterable.toArray)         return iterable.toArray();
    if (_.isArray(iterable))      return iterable;
    if (_.isArguments(iterable))  return slice.call(iterable);
    return _.values(iterable);
  };

  // Return the number of elements in an object.
  _.size = function(obj) {
    return _.toArray(obj).length;
  };

  // -------------------------- Array Functions: ------------------------------

  // Get the first element of an array. Passing "n" will return the first N
  // values in the array. Aliased as "head". The "guard" check allows it to work
  // with _.map.
  _.first = function(array, n, guard) {
    return n && !guard ? slice.call(array, 0, n) : array[0];
  };

  // Returns everything but the first entry of the array. Aliased as "tail".
  // Especially useful on the arguments object. Passing an "index" will return
  // the rest of the values in the array from that index onward. The "guard"
   //check allows it to work with _.map.
  _.rest = function(array, index, guard) {
    return slice.call(array, _.isUndefined(index) || guard ? 1 : index);
  };

  // Get the last element of an array.
  _.last = function(array) {
    return array[array.length - 1];
  };

  // Trim out all falsy values from an array.
  _.compact = function(array) {
    return _.filter(array, function(value){ return !!value; });
  };

  // Return a completely flattened version of an array.
  _.flatten = function(array) {
    return _.reduce(array, [], function(memo, value) {
      if (_.isArray(value)) return memo.concat(_.flatten(value));
      memo.push(value);
      return memo;
    });
  };

  // Return a version of the array that does not contain the specified value(s).
  _.without = function(array) {
    var values = _.rest(arguments);
    return _.filter(array, function(value){ return !_.include(values, value); });
  };

  // Produce a duplicate-free version of the array. If the array has already
  // been sorted, you have the option of using a faster algorithm.
  _.uniq = function(array, isSorted) {
    return _.reduce(array, [], function(memo, el, i) {
      if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
      return memo;
    });
  };

  // Produce an array that contains every item shared between all the
  // passed-in arrays.
  _.intersect = function(array) {
    var rest = _.rest(arguments);
    return _.filter(_.uniq(array), function(item) {
      return _.every(rest, function(other) {
        return _.indexOf(other, item) >= 0;
      });
    });
  };

  // Zip together multiple lists into a single array -- elements that share
  // an index go together.
  _.zip = function() {
    var args = _.toArray(arguments);
    var length = _.max(_.pluck(args, 'length'));
    var results = new Array(length);
    for (var i = 0; i < length; i++) results[i] = _.pluck(args, String(i));
    return results;
  };

  // If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
  // we need this function. Return the position of the first occurence of an
  // item in an array, or -1 if the item is not included in the array.
  // Delegates to JavaScript 1.8's native indexOf if available.
  _.indexOf = function(array, item) {
    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
    for (var i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
    return -1;
  };

  // Delegates to JavaScript 1.6's native lastIndexOf if available.
  _.lastIndexOf = function(array, item) {
    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
    var i = array.length;
    while (i--) if (array[i] === item) return i;
    return -1;
  };

  // Generate an integer Array containing an arithmetic progression. A port of
  // the native Python range() function. See:
  // http://docs.python.org/library/functions.html#range
  _.range = function(start, stop, step) {
    var a     = _.toArray(arguments);
    var solo  = a.length <= 1;
    var start = solo ? 0 : a[0], stop = solo ? a[0] : a[1], step = a[2] || 1;
    var len   = Math.ceil((stop - start) / step);
    if (len <= 0) return [];
    var range = new Array(len);
    for (var i = start, idx = 0; true; i += step) {
      if ((step > 0 ? i - stop : stop - i) >= 0) return range;
      range[idx++] = i;
    }
  };

  // ----------------------- Function Functions: ------------------------------

  // Create a function bound to a given object (assigning 'this', and arguments,
  // optionally). Binding with arguments is also known as 'curry'.
  _.bind = function(func, obj) {
    var args = _.rest(arguments, 2);
    return function() {
      return func.apply(obj || {}, args.concat(_.toArray(arguments)));
    };
  };

  // Bind all of an object's methods to that object. Useful for ensuring that
  // all callbacks defined on an object belong to it.
  _.bindAll = function(obj) {
    var funcs = _.rest(arguments);
    if (funcs.length == 0) funcs = _.functions(obj);
    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
    return obj;
  };

  // Delays a function for the given number of milliseconds, and then calls
  // it with the arguments supplied.
  _.delay = function(func, wait) {
    var args = _.rest(arguments, 2);
    return setTimeout(function(){ return func.apply(func, args); }, wait);
  };

  // Defers a function, scheduling it to run after the current call stack has
  // cleared.
  _.defer = function(func) {
    return _.delay.apply(_, [func, 1].concat(_.rest(arguments)));
  };

  // Returns the first function passed as an argument to the second,
  // allowing you to adjust arguments, run code before and after, and
  // conditionally execute the original function.
  _.wrap = function(func, wrapper) {
    return function() {
      var args = [func].concat(_.toArray(arguments));
      return wrapper.apply(wrapper, args);
    };
  };

  // Returns a function that is the composition of a list of functions, each
  // consuming the return value of the function that follows.
  _.compose = function() {
    var funcs = _.toArray(arguments);
    return function() {
      var args = _.toArray(arguments);
      for (var i=funcs.length-1; i >= 0; i--) {
        args = [funcs[i].apply(this, args)];
      }
      return args[0];
    };
  };

  // ------------------------- Object Functions: ------------------------------

  // Retrieve the names of an object's properties.
  // Delegates to ECMA5's native Object.keys
  _.keys = nativeKeys || function(obj) {
    if (_.isArray(obj)) return _.range(0, obj.length);
    var keys = [];
    for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key);
    return keys;
  };

  // Retrieve the values of an object's properties.
  _.values = function(obj) {
    return _.map(obj, _.identity);
  };

  // Return a sorted list of the function names available on the object.
  _.functions = function(obj) {
    return _.filter(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
  };

  // Extend a given object with all the properties in passed-in object(s).
  _.extend = function(obj) {
    each(_.rest(arguments), function(source) {
      for (var prop in source) obj[prop] = source[prop];
    });
    return obj;
  };

  // Create a (shallow-cloned) duplicate of an object.
  _.clone = function(obj) {
    if (_.isArray(obj)) return obj.slice(0);
    return _.extend({}, obj);
  };

  // Invokes interceptor with the obj, and then returns obj.
  // The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
  _.tap = function(obj, interceptor) {
    interceptor(obj);
    return obj;
  };

  // Perform a deep comparison to check if two objects are equal.
  _.isEqual = function(a, b) {
    // Check object identity.
    if (a === b) return true;
    // Different types?
    var atype = typeof(a), btype = typeof(b);
    if (atype != btype) return false;
    // Basic equality test (watch out for coercions).
    if (a == b) return true;
    // One is falsy and the other truthy.
    if ((!a && b) || (a && !b)) return false;
    // One of them implements an isEqual()?
    if (a.isEqual) return a.isEqual(b);
    // Check dates' integer values.
    if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
    // Both are NaN?
    if (_.isNaN(a) && _.isNaN(b)) return true;
    // Compare regular expressions.
    if (_.isRegExp(a) && _.isRegExp(b))
      return a.source     === b.source &&
             a.global     === b.global &&
             a.ignoreCase === b.ignoreCase &&
             a.multiline  === b.multiline;
    // If a is not an object by this point, we can't handle it.
    if (atype !== 'object') return false;
    // Check for different array lengths before comparing contents.
    if (a.length && (a.length !== b.length)) return false;
    // Nothing else worked, deep compare the contents.
    var aKeys = _.keys(a), bKeys = _.keys(b);
    // Different object sizes?
    if (aKeys.length != bKeys.length) return false;
    // Recursive comparison of contents.
    for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
    return true;
  };

  // Is a given array or object empty?
  _.isEmpty = function(obj) {
    if (_.isArray(obj)) return obj.length === 0;
    for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
    return true;
  };

  // Is a given value a DOM element?
  _.isElement = function(obj) {
    return !!(obj && obj.nodeType == 1);
  };

  // Is a given value an array?
  // Delegates to ECMA5's native Array.isArray
  _.isArray = nativeIsArray || function(obj) {
    return !!(obj && obj.concat && obj.unshift && !obj.callee);
  };

  // Is a given variable an arguments object?
  _.isArguments = function(obj) {
    return obj && obj.callee;
  };

  // Is a given value a function?
  _.isFunction = function(obj) {
    return !!(obj && obj.constructor && obj.call && obj.apply);
  };

  // Is a given value a string?
  _.isString = function(obj) {
    return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
  };

  // Is a given value a number?
  _.isNumber = function(obj) {
    return (obj === +obj) || (toString.call(obj) === '[object Number]');
  };

  // Is a given value a boolean?
  _.isBoolean = function(obj) {
    return obj === true || obj === false;
  };

  // Is a given value a date?
  _.isDate = function(obj) {
    return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
  };

  // Is the given value a regular expression?
  _.isRegExp = function(obj) {
    return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
  };

  // Is the given value NaN -- this one is interesting. NaN != NaN, and
  // isNaN(undefined) == true, so we make sure it's a number first.
  _.isNaN = function(obj) {
    return _.isNumber(obj) && isNaN(obj);
  };

  // Is a given value equal to null?
  _.isNull = function(obj) {
    return obj === null;
  };

  // Is a given variable undefined?
  _.isUndefined = function(obj) {
    return typeof obj == 'undefined';
  };

  // -------------------------- Utility Functions: ----------------------------

  // Run Underscore.js in noConflict mode, returning the '_' variable to its
  // previous owner. Returns a reference to the Underscore object.
  _.noConflict = function() {
    root._ = previousUnderscore;
    return this;
  };

  // Keep the identity function around for default iterators.
  _.identity = function(value) {
    return value;
  };

  // Run a function n times.
  _.times = function (n, iterator, context) {
    for (var i = 0; i < n; i++) iterator.call(context, i);
  };

  // Break out of the middle of an iteration.
  _.breakLoop = function() {
    throw breaker;
  };

  // Add your own custom functions to the Underscore object, ensuring that
  // they're correctly added to the OOP wrapper as well.
  _.mixin = function(obj) {
    each(_.functions(obj), function(name){
      addToWrapper(name, _[name] = obj[name]);
    });
  };

  // Generate a unique integer id (unique within the entire client session).
  // Useful for temporary DOM ids.
  var idCounter = 0;
  _.uniqueId = function(prefix) {
    var id = idCounter++;
    return prefix ? prefix + id : id;
  };

  // By default, Underscore uses ERB-style template delimiters, change the
  // following template settings to use alternative delimiters.
  _.templateSettings = {
    start       : '<%',
    end         : '%>',
    interpolate : /<%=(.+?)%>/g
  };

  // JavaScript templating a-la ERB, pilfered from John Resig's
  // "Secrets of the JavaScript Ninja", page 83.
  // Single-quote fix from Rick Strahl's version.
  // With alterations for arbitrary delimiters.
  _.template = function(str, data) {
    var c  = _.templateSettings;
    var endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g");
    var fn = new Function('obj',
      'var p=[],print=function(){p.push.apply(p,arguments);};' +
      'with(obj){p.push(\'' +
      str.replace(/[\r\t\n]/g, " ")
         .replace(endMatch,"\t")
         .split("'").join("\\'")
         .split("\t").join("'")
         .replace(c.interpolate, "',$1,'")
         .split(c.start).join("');")
         .split(c.end).join("p.push('")
         + "');}return p.join('');");
    return data ? fn(data) : fn;
  };

  // ------------------------------- Aliases ----------------------------------

  _.each     = _.forEach;
  _.foldl    = _.inject       = _.reduce;
  _.foldr    = _.reduceRight;
  _.select   = _.filter;
  _.all      = _.every;
  _.any      = _.some;
  _.head     = _.first;
  _.tail     = _.rest;
  _.methods  = _.functions;

  // ------------------------ Setup the OOP Wrapper: --------------------------

  // If Underscore is called as a function, it returns a wrapped object that
  // can be used OO-style. This wrapper holds altered versions of all the
  // underscore functions. Wrapped objects may be chained.
  var wrapper = function(obj) { this._wrapped = obj; };

  // Helper function to continue chaining intermediate results.
  var result = function(obj, chain) {
    return chain ? _(obj).chain() : obj;
  };

  // A method to easily add functions to the OOP wrapper.
  var addToWrapper = function(name, func) {
    wrapper.prototype[name] = function() {
      var args = _.toArray(arguments);
      unshift.call(args, this._wrapped);
      return result(func.apply(_, args), this._chain);
    };
  };

  // Add all of the Underscore functions to the wrapper object.
  _.mixin(_);

  // Add all mutator Array functions to the wrapper.
  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    var method = ArrayProto[name];
    wrapper.prototype[name] = function() {
      method.apply(this._wrapped, arguments);
      return result(this._wrapped, this._chain);
    };
  });

  // Add all accessor Array functions to the wrapper.
  each(['concat', 'join', 'slice'], function(name) {
    var method = ArrayProto[name];
    wrapper.prototype[name] = function() {
      return result(method.apply(this._wrapped, arguments), this._chain);
    };
  });

  // Start chaining a wrapped Underscore object.
  wrapper.prototype.chain = function() {
    this._chain = true;
    return this;
  };

  // Extracts the result from a wrapped and chained object.
  wrapper.prototype.value = function() {
    return this._wrapped;
  };

})();
<commit_msg>* underoop.js: oops<commit_after><|endoftext|>


<commit_before>/**
 * instant.js
 *
 * @license MIT
 * @author Timm Albers (http://timmalbers.de)
 * @version 1.1.0
 */
const instant = (function() {
	var model;
	var views = [];
	var renderJobs = [];
	var config = {
		compile: function(source) {
			return Handlebars.compile(source)
		},
		render: function(template, model) {
			return template(model);
		}
	};

	/**
	 * Inititalize Handlebars.
	 */
	(function() {
		Handlebars.registerHelper('blank', function(context, options) {
			return context;
		});
	})();

	/**
	 * Initialize action listeners.
	 */
	(function() {
		$('body').on('input', function(e) {
			var $focusedElement = $(':focus');
			var focusedElementId = $focusedElement.attr('data-instant-id');
			var caretPosition = $focusedElement.caret();

			var $target = $(e.target);
			var path = $target.attr('data-instant-attribute')
					.split('.');
			var newValue = $target.text() || $target.val();

			// Update model.
			var value = model;
			for(var i in path) {
				if(path.length-1 == i) {
					if(value) {
						if(value[path[i]].hasOwnProperty('text')) {
							value[path[i]].setProperty(newValue);
						} else if(value[path[i]] !== newValue) {
							value[path[i]] = newValue;
						}
					}
				} else {
					value = value[path[i]];
				}
			}

			$focusedElement = $('[data-instant-id=' + focusedElementId + ']');
			$focusedElement.focus().caret(caretPosition);
		});
	})();

	/**
	 * Attaches a property change listener recursivly to the given object.
	 *
	 * @param <Object> o
	 */
	var attachPropertyChangeListener = function(o) {
		// Walk through propertys.
		for(var property in o) {
			if(o.hasOwnProperty(property)) {
				// Recursion.
				if(typeof o[property] === 'object') {
					attachPropertyChangeListener(o[property]);
				} else {
					// Attach the listener.
					(function() {
						var value = o[property];
						Object.defineProperty(o, property, {
							get: function() {
								return value;
							},
							set: function(value_) {
								value = value_
								render();
								return value;
							}
						});
					})();
				}
			}
		}
	};

	/**
	 * Inserts the library specific tags into the DOM.
	 *
	 * @param <String> source
	 * @return <String> result
	 */
	var insertInstantAttributes = function(source) {
		source = source.replace(/.[^<]*data-bind-.[^>]*.[^>]*>/g, function(match) {
			var path = [];

			// TODO calculate parent path

			var attributeName = match
					.replace(/.*\{\{/, '')
					.replace(/\}\}.*/, '');
			path.push(attributeName);

			return match
					.replace(/>/, ' data-instant-attribute="' + path.join('.') + '">')
					.replace(/>/, ' data-instant-id="' + ('' + Math.random()).replace(/0./, '') + '">');
		});

		return source;
	};

	/**
	 * Parse the DOM, search for views and initialize those.
	 */
	var updateViews = function() {
		views = [];

		$('script[type="text/template"]').each(function() {
			views.push({
				name: $(this).attr('data-view'),
				// TODO
				template: config.compile(insertInstantAttributes($(this).html()))
			});
		});
	};

	/**
	 * Renders the compiled templates.
	 *
	 * @param template (optional)
	 */
	var render = function(template) {
		if(renderJobs.length && model) {
			for(var i = 0; i < renderJobs.length; i++) {
				var template = renderJobs[i].template;

				if(typeof template === 'function') {
					renderJobs[i].toString = function() {
						return config.render(template, model);
					};
				}
			}

			renderJobs = [];
		}

		if(template) {
			if(model) {
				return config.render(template, model);
			} else {
				var renderJob = {
					template: template
				};
				renderJobs.push(renderJob);

				return renderJob;
			}
		} else {
			for(var i in views) {
				var html = config.render(views[i].template, model);

				$(':not(script)[data-view="' + views[i].name + '"]').each(function() {
					$(this).html(html);
				});
			}
		}
	};

	return {
		/**
		 * Sets and initializes the model. Can ben used once; or multiple times to overwrite the set model.
		 *
		 * @param <Object> model
		 * @return <Object> instant.js
		 */
		model: function(model_) {
			attachPropertyChangeListener(model_);
			model = model_;

			updateViews();
			render();

			// Return instant for method chaining.
			return instant;
		},

		/**
		 * Sets the compiler function.
		 *
		 * @param <Function> compiler
		 * @return <Object> instant.js
		 */
		compiler: function(compiler) {
			config.compile = compiler;

			// Return instant for method chaning.
			return instant;
		},

		/**
		 * Sets the renderer function.
		 *
		 * @param <Function> renderer
		 * @return <Object> instant.js
		 */
		renderer: function(renderer) {
			config.render = renderer;

			// Return instant for method chaning.
			return instant;
	    },

		/**
		 * Sets the document title.
		 *
		 * @param <String> title
		 * @return <String> title
		 */
		docTitle: function(title) {
			$(document).attr('title', title);

			return title;
		},

		/**
		 * Listens for changes of the current attribute.
		 *
		 * @param <String> att
		 * @param <Function> callback
		 * @return <String> att
		 */
		listen: function(att, callback_) {
			var o = {
				text: att,
				// TODO
				setProperty: function(value) {
					var result = callback_(value);
					if(result) value = result;
					this.text = value;
				},
				toString: function() {
					return this.text;
				}
			};

			// TODO
			(function() {
				var value = att;
				var callback = callback_;
				Object.defineProperty(o, 'text', {
					get: function() {
						return value;
					},
					set: function(value_) {
						console.log('rkwje');
						alert("kj");
						// value = value_;

						// callback();
						return value;
					}
				});
			})();

			return o;
		},

		// TODO
		template: function(viewName) {
			updateViews();
			var template = '';
			for(var i in views) {
				if(views[i].name === viewName) template = views[i].template;
			}

			return render(template);
		}
	};
})();<commit_msg>Removed Handlebars blank helper. Fixes #3<commit_after>/**
 * instant.js
 *
 * @license MIT
 * @author Timm Albers (http://timmalbers.de)
 * @version 1.1.0
 */
const instant = (function() {
	var model;
	var views = [];
	var renderJobs = [];
	var config = {
		compile: function(source) {
			return Handlebars.compile(source)
		},
		render: function(template, model) {
			return template(model);
		}
	};

	/**
	 * Initialize action listeners.
	 */
	(function() {
		$('body').on('input', function(e) {
			var $focusedElement = $(':focus');
			var focusedElementId = $focusedElement.attr('data-instant-id');
			var caretPosition = $focusedElement.caret();

			var $target = $(e.target);
			var path = $target.attr('data-instant-attribute')
					.split('.');
			var newValue = $target.text() || $target.val();

			// Update model.
			var value = model;
			for(var i in path) {
				if(path.length-1 == i) {
					if(value) {
						if(value[path[i]].hasOwnProperty('text')) {
							value[path[i]].setProperty(newValue);
						} else if(value[path[i]] !== newValue) {
							value[path[i]] = newValue;
						}
					}
				} else {
					value = value[path[i]];
				}
			}

			$focusedElement = $('[data-instant-id=' + focusedElementId + ']');
			$focusedElement.focus().caret(caretPosition);
		});
	})();

	/**
	 * Attaches a property change listener recursivly to the given object.
	 *
	 * @param <Object> o
	 */
	var attachPropertyChangeListener = function(o) {
		// Walk through propertys.
		for(var property in o) {
			if(o.hasOwnProperty(property)) {
				// Recursion.
				if(typeof o[property] === 'object') {
					attachPropertyChangeListener(o[property]);
				} else {
					// Attach the listener.
					(function() {
						var value = o[property];
						Object.defineProperty(o, property, {
							get: function() {
								return value;
							},
							set: function(value_) {
								value = value_
								render();
								return value;
							}
						});
					})();
				}
			}
		}
	};

	/**
	 * Inserts the library specific tags into the DOM.
	 *
	 * @param <String> source
	 * @return <String> result
	 */
	var insertInstantAttributes = function(source) {
		source = source.replace(/.[^<]*data-bind-.[^>]*.[^>]*>/g, function(match) {
			var path = [];

			// TODO calculate parent path

			var attributeName = match
					.replace(/.*\{\{/, '')
					.replace(/\}\}.*/, '');
			path.push(attributeName);

			return match
					.replace(/>/, ' data-instant-attribute="' + path.join('.') + '">')
					.replace(/>/, ' data-instant-id="' + ('' + Math.random()).replace(/0./, '') + '">');
		});

		return source;
	};

	/**
	 * Parse the DOM, search for views and initialize those.
	 */
	var updateViews = function() {
		views = [];

		$('script[type="text/template"]').each(function() {
			views.push({
				name: $(this).attr('data-view'),
				// TODO
				template: config.compile(insertInstantAttributes($(this).html()))
			});
		});
	};

	/**
	 * Renders the compiled templates.
	 *
	 * @param template (optional)
	 */
	var render = function(template) {
		if(renderJobs.length && model) {
			for(var i = 0; i < renderJobs.length; i++) {
				var template = renderJobs[i].template;

				if(typeof template === 'function') {
					renderJobs[i].toString = function() {
						return config.render(template, model);
					};
				}
			}

			renderJobs = [];
		}

		if(template) {
			if(model) {
				return config.render(template, model);
			} else {
				var renderJob = {
					template: template
				};
				renderJobs.push(renderJob);

				return renderJob;
			}
		} else {
			for(var i in views) {
				var html = config.render(views[i].template, model);

				$(':not(script)[data-view="' + views[i].name + '"]').each(function() {
					$(this).html(html);
				});
			}
		}
	};

	return {
		/**
		 * Sets and initializes the model. Can ben used once; or multiple times to overwrite the set model.
		 *
		 * @param <Object> model
		 * @return <Object> instant.js
		 */
		model: function(model_) {
			attachPropertyChangeListener(model_);
			model = model_;

			updateViews();
			render();

			// Return instant for method chaining.
			return instant;
		},

		/**
		 * Sets the compiler function.
		 *
		 * @param <Function> compiler
		 * @return <Object> instant.js
		 */
		compiler: function(compiler) {
			config.compile = compiler;

			// Return instant for method chaning.
			return instant;
		},

		/**
		 * Sets the renderer function.
		 *
		 * @param <Function> renderer
		 * @return <Object> instant.js
		 */
		renderer: function(renderer) {
			config.render = renderer;

			// Return instant for method chaning.
			return instant;
	    },

		/**
		 * Sets the document title.
		 *
		 * @param <String> title
		 * @return <String> title
		 */
		docTitle: function(title) {
			$(document).attr('title', title);

			return title;
		},

		/**
		 * Listens for changes of the current attribute.
		 *
		 * @param <String> att
		 * @param <Function> callback
		 * @return <String> att
		 */
		listen: function(att, callback_) {
			var o = {
				text: att,
				// TODO
				setProperty: function(value) {
					var result = callback_(value);
					if(result) value = result;
					this.text = value;
				},
				toString: function() {
					return this.text;
				}
			};

			// TODO
			(function() {
				var value = att;
				var callback = callback_;
				Object.defineProperty(o, 'text', {
					get: function() {
						return value;
					},
					set: function(value_) {
						console.log('rkwje');
						alert("kj");
						// value = value_;

						// callback();
						return value;
					}
				});
			})();

			return o;
		},

		// TODO
		template: function(viewName) {
			updateViews();
			var template = '';
			for(var i in views) {
				if(views[i].name === viewName) template = views[i].template;
			}

			return render(template);
		}
	};
})();<|endoftext|>


<commit_before>'use strict'

import { h, Component } from 'preact';
import LogoutButton from '../components/LogoutButton.js';
import Realtime from '../components/Realtime.js';
import DatePicker from '../components/DatePicker.js';
import CountWidget from '../components/CountWidget.js';
import Table from '../components/Table.js';

import { bind } from 'decko';

class Dashboard extends Component {
  constructor(props) {
    super(props)

    this.state = {
      period: (window.location.hash.substring(2) || 'week'),
      before: 0,
      after: 0,
    }
  }

  @bind
  changePeriod(s) {
    this.setState({ period: s.period, before: s.before, after: s.after })
    window.history.replaceState(this.state, null, `#!${s.period}`)
  }

  render(props, state) {
    return (

Fathom

<Realtime onError={this.props.onLogout} />

·

<LogoutButton onSuccess={this.props.onLogout} />

          <DatePicker onChange={this.changePeriod} value={state.period} />

            <CountWidget title="Unique visitors" endpoint="stats/site/visitors" before={state.before} after={state.after} />
            <CountWidget title="Page views" endpoint="stats/site/pageviews" before={state.before} after={state.after} />
            <CountWidget title="Avg time on site" endpoint="stats/site/duration" format="duration" before={state.before} after={state.after} />
            <CountWidget title="Bounce rate" endpoint="stats/site/bounces" format="percentage" before={state.before} after={state.after} />

  )}
}

export default Dashboard
<commit_msg>access props through function arg<commit_after>'use strict'

import { h, Component } from 'preact';
import LogoutButton from '../components/LogoutButton.js';
import Realtime from '../components/Realtime.js';
import DatePicker from '../components/DatePicker.js';
import CountWidget from '../components/CountWidget.js';
import Table from '../components/Table.js';

import { bind } from 'decko';

class Dashboard extends Component {
  constructor(props) {
    super(props)

    this.state = {
      period: (window.location.hash.substring(2) || 'week'),
      before: 0,
      after: 0,
    }
  }

  @bind
  changePeriod(s) {
    this.setState({ period: s.period, before: s.before, after: s.after })
    window.history.replaceState(this.state, null, `#!${s.period}`)
  }

  render(props, state) {
    return (

Fathom

<Realtime onError={props.onLogout} />

·

<LogoutButton onSuccess={props.onLogout} />

          <DatePicker onChange={this.changePeriod} value={state.period} />

            <CountWidget title="Unique visitors" endpoint="stats/site/visitors" before={state.before} after={state.after} />
            <CountWidget title="Page views" endpoint="stats/site/pageviews" before={state.before} after={state.after} />
            <CountWidget title="Avg time on site" endpoint="stats/site/duration" format="duration" before={state.before} after={state.after} />
            <CountWidget title="Bounce rate" endpoint="stats/site/bounces" format="percentage" before={state.before} after={state.after} />

  )}
}

export default Dashboard
<|endoftext|>