Added snap to nearest special char for mobile, mobile detection logic, refactoring of standard directions into constants.
This commit is contained in:
parent
8b5e3139a6
commit
92e413357a
|
@ -5,7 +5,6 @@ java -client -jar closure-compiler.jar \
|
||||||
--js js-lib/controller.js \
|
--js js-lib/controller.js \
|
||||||
--js js-lib/state.js \
|
--js js-lib/state.js \
|
||||||
--js js-lib/launch.js \
|
--js js-lib/launch.js \
|
||||||
--warning_level=VERBOSE --formatting=PRETTY_PRINT --language_in=ECMASCRIPT5 --compilation_level=WHITESPACE_ONLY \
|
--warning_level=VERBOSE --formatting=PRETTY_PRINT --language_in=ECMASCRIPT5 --compilation_level=ADVANCED_OPTIMIZATIONS \
|
||||||
--externs=jquery-1.9-externs.js \
|
--externs=jquery-1.9-externs.js \
|
||||||
> js-compiled.js \
|
> js-compiled.js
|
||||||
&& cp js-compiled.js js-compiled.js~
|
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
// Define namespace for closure compiler but don't make it a requirement.
|
// Define namespace for closure compiler but don't make it a requirement.
|
||||||
try {
|
try {
|
||||||
goog.provide('ascii');
|
goog.provide('ascii');
|
||||||
|
throw 1;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
window.ascii = {};
|
window.ascii = window.ascii || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @const */ var MAX_GRID_WIDTH = 2000;
|
/** @const */ var MAX_GRID_WIDTH = 2000;
|
||||||
|
@ -39,6 +40,11 @@ try {
|
||||||
/** @const */ var KEY_LEFT = '<left>';
|
/** @const */ var KEY_LEFT = '<left>';
|
||||||
/** @const */ var KEY_RIGHT = '<right>';
|
/** @const */ var KEY_RIGHT = '<right>';
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript
|
||||||
|
/** @const */ var TOUCH_ENABLED =
|
||||||
|
'ontouchstart' in window ||
|
||||||
|
'onmsgesturechange' in window;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a 2D vector.
|
* Stores a 2D vector.
|
||||||
*
|
*
|
||||||
|
@ -95,6 +101,13 @@ ascii.Vector.prototype.scale = function(scale) {
|
||||||
return new ascii.Vector(this.x * scale, this.y * scale);
|
return new ascii.Vector(this.x * scale, this.y * scale);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @const */ var DIR_LEFT = new ascii.Vector(-1, 0);
|
||||||
|
/** @const */ var DIR_RIGHT = new ascii.Vector(1, 0);
|
||||||
|
/** @const */ var DIR_UP = new ascii.Vector(0, -1);
|
||||||
|
/** @const */ var DIR_DOWN = new ascii.Vector(0, 1);
|
||||||
|
|
||||||
|
/** @const */ var DIRECTIONS = [ DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN ];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An individual cell within the diagram and it's current value.
|
* An individual cell within the diagram and it's current value.
|
||||||
*
|
*
|
||||||
|
|
|
@ -182,18 +182,18 @@ ascii.DrawText.prototype.handleKey = function(value) {
|
||||||
if (this.currentPosition == null) {
|
if (this.currentPosition == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var nextPosition = this.currentPosition.add(new ascii.Vector(1, 0));
|
var nextPosition = this.currentPosition.add(DIR_RIGHT);
|
||||||
|
|
||||||
if (value == KEY_RETURN || this.state.getCell(nextPosition).isSpecial()) {
|
if (value == KEY_RETURN || this.state.getCell(nextPosition).isSpecial()) {
|
||||||
// Pressed return key or hit box, so clear this cell and new line.
|
// Pressed return key or hit box, so clear this cell and new line.
|
||||||
this.state.clearDraw();
|
this.state.clearDraw();
|
||||||
nextPosition = this.startPosition.add(new ascii.Vector(0, 1));
|
nextPosition = this.startPosition.add(DIR_DOWN);
|
||||||
this.startPosition = nextPosition;
|
this.startPosition = nextPosition;
|
||||||
}
|
}
|
||||||
if (value == KEY_BACKSPACE && this.startPosition.x <= nextPosition.x) {
|
if (value == KEY_BACKSPACE && this.startPosition.x <= nextPosition.x) {
|
||||||
// Pressed backspace key, so clear this cell and go back.
|
// Pressed backspace key, so clear this cell and go back.
|
||||||
this.state.clearDraw();
|
this.state.clearDraw();
|
||||||
nextPosition = this.currentPosition.add(new ascii.Vector(-1, 0));
|
nextPosition = this.currentPosition.add(DIR_LEFT);
|
||||||
if (nextPosition.x < this.startPosition.x) {
|
if (nextPosition.x < this.startPosition.x) {
|
||||||
nextPosition.x = this.startPosition.x;
|
nextPosition.x = this.startPosition.x;
|
||||||
}
|
}
|
||||||
|
@ -202,19 +202,19 @@ ascii.DrawText.prototype.handleKey = function(value) {
|
||||||
}
|
}
|
||||||
if (value == KEY_UP) {
|
if (value == KEY_UP) {
|
||||||
this.state.clearDraw();
|
this.state.clearDraw();
|
||||||
this.startPosition = nextPosition = this.currentPosition.add(new ascii.Vector(0, -1))
|
this.startPosition = nextPosition = this.currentPosition.add(DIR_UP);
|
||||||
}
|
}
|
||||||
if (value == KEY_LEFT) {
|
if (value == KEY_LEFT) {
|
||||||
this.state.clearDraw();
|
this.state.clearDraw();
|
||||||
this.startPosition = nextPosition = this.currentPosition.add(new ascii.Vector(-1, 0))
|
this.startPosition = nextPosition = this.currentPosition.add(DIR_LEFT);
|
||||||
}
|
}
|
||||||
if (value == KEY_RIGHT) {
|
if (value == KEY_RIGHT) {
|
||||||
this.state.clearDraw();
|
this.state.clearDraw();
|
||||||
this.startPosition = nextPosition = this.currentPosition.add(new ascii.Vector(1, 0))
|
this.startPosition = nextPosition = this.currentPosition.add(DIR_RIGHT);
|
||||||
}
|
}
|
||||||
if (value == KEY_DOWN) {
|
if (value == KEY_DOWN) {
|
||||||
this.state.clearDraw();
|
this.state.clearDraw();
|
||||||
this.startPosition = nextPosition = this.currentPosition.add(new ascii.Vector(0, 1))
|
this.startPosition = nextPosition = this.currentPosition.add(DIR_DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.length == 1) {
|
if (value.length == 1) {
|
||||||
|
@ -279,22 +279,25 @@ ascii.DrawMove = function(state) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ascii.DrawMove.prototype.start = function(position) {
|
ascii.DrawMove.prototype.start = function(position) {
|
||||||
this.startPosition = position;
|
this.startPosition = TOUCH_ENABLED
|
||||||
var context = this.state.getContext(position);
|
? this.snapToNearest(position)
|
||||||
var directions = [
|
: position;
|
||||||
new ascii.Vector(1, 0),
|
this.ends = null;
|
||||||
new ascii.Vector(-1, 0),
|
|
||||||
new ascii.Vector(0, 1),
|
// If this isn't a special cell then quit, or things get weird.
|
||||||
new ascii.Vector(0, -1)];
|
if (!this.state.getCell(this.startPosition).isSpecial()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var context = this.state.getContext(this.startPosition);
|
||||||
|
|
||||||
var ends = [];
|
var ends = [];
|
||||||
for (var i in directions) {
|
for (var i in DIRECTIONS) {
|
||||||
var midPoints = this.followLine(position, directions[i]);
|
var midPoints = this.followLine(this.startPosition, DIRECTIONS[i]);
|
||||||
for (var k in midPoints) {
|
for (var k in midPoints) {
|
||||||
var midPoint = midPoints[k];
|
var midPoint = midPoints[k];
|
||||||
|
|
||||||
// Clockwise is a lie, it is true if we move vertically first.
|
// Clockwise is a lie, it is true if we move vertically first.
|
||||||
var clockwise = (directions[i].x != 0);
|
var clockwise = (DIRECTIONS[i].x != 0);
|
||||||
|
|
||||||
var midPointContext = this.state.getContext(midPoint);
|
var midPointContext = this.state.getContext(midPoint);
|
||||||
// Special case, a straight line with no turns.
|
// Special case, a straight line with no turns.
|
||||||
|
@ -303,13 +306,13 @@ ascii.DrawMove.prototype.start = function(position) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Continue following lines from the midpoint.
|
// Continue following lines from the midpoint.
|
||||||
for (var j in directions) {
|
for (var j in DIRECTIONS) {
|
||||||
if (directions[i].add(directions[j]).length() == 0 ||
|
if (DIRECTIONS[i].add(DIRECTIONS[j]).length() == 0 ||
|
||||||
directions[i].add(directions[j]).length() == 2) {
|
DIRECTIONS[i].add(DIRECTIONS[j]).length() == 2) {
|
||||||
// Don't go back on ourselves, or don't carry on in same direction.
|
// Don't go back on ourselves, or don't carry on in same direction.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var secondEnds = this.followLine(midPoint, directions[j]);
|
var secondEnds = this.followLine(midPoint, DIRECTIONS[j]);
|
||||||
// Ignore any directions that didn't go anywhere.
|
// Ignore any directions that didn't go anywhere.
|
||||||
if (secondEnds.length == 0) {
|
if (secondEnds.length == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -321,7 +324,7 @@ ascii.DrawMove.prototype.start = function(position) {
|
||||||
}
|
}
|
||||||
this.ends = ends;
|
this.ends = ends;
|
||||||
// Redraw the new lines after we have cleared the existing ones.
|
// Redraw the new lines after we have cleared the existing ones.
|
||||||
this.move(position);
|
this.move(this.startPosition);
|
||||||
};
|
};
|
||||||
|
|
||||||
ascii.DrawMove.prototype.move = function(position) {
|
ascii.DrawMove.prototype.move = function(position) {
|
||||||
|
@ -368,6 +371,41 @@ ascii.DrawMove.prototype.followLine = function(startPosition, direction) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a given position, finds the nearest cell that is of any interest to the
|
||||||
|
* move tool, e.g. a corner or a line. Will look up to 1 cell in each direction
|
||||||
|
* including diagonally.
|
||||||
|
* @return {ascii.Vector}
|
||||||
|
*/
|
||||||
|
ascii.DrawMove.prototype.snapToNearest = function(position) {
|
||||||
|
if (this.state.getCell(position).isSpecial()) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
var allDirections = DIRECTIONS.concat([
|
||||||
|
DIR_LEFT.add(DIR_UP),
|
||||||
|
DIR_LEFT.add(DIR_DOWN),
|
||||||
|
DIR_RIGHT.add(DIR_UP),
|
||||||
|
DIR_RIGHT.add(DIR_DOWN)]);
|
||||||
|
|
||||||
|
var bestDirection = null;
|
||||||
|
var bestContextSum = 0;
|
||||||
|
for (var i in allDirections) {
|
||||||
|
// Find the most connected cell, essentially.
|
||||||
|
var newPos = position.add(allDirections[i]);
|
||||||
|
var contextSum = this.state.getContext(newPos).sum();
|
||||||
|
if (this.state.getCell(newPos).isSpecial()
|
||||||
|
&& contextSum > bestContextSum) {
|
||||||
|
bestDirection = allDirections[i];
|
||||||
|
bestContextSum = contextSum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bestDirection == null) {
|
||||||
|
// Didn't find anything, so just return the current cell.
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
return position.add(bestDirection);
|
||||||
|
}
|
||||||
|
|
||||||
ascii.DrawMove.prototype.getCursor = function(position) {
|
ascii.DrawMove.prototype.getCursor = function(position) {
|
||||||
if (this.state.getCell(position).isSpecial()) {
|
if (this.state.getCell(position).isSpecial()) {
|
||||||
return 'pointer';
|
return 'pointer';
|
||||||
|
|
|
@ -125,10 +125,10 @@ ascii.State.prototype.getDrawValue = function(position) {
|
||||||
* @return {ascii.CellContext}
|
* @return {ascii.CellContext}
|
||||||
*/
|
*/
|
||||||
ascii.State.prototype.getContext = function(position) {
|
ascii.State.prototype.getContext = function(position) {
|
||||||
var left = this.getCell(position.add(new ascii.Vector(-1, 0))).isSpecial();
|
var left = this.getCell(position.add(DIR_LEFT)).isSpecial();
|
||||||
var right = this.getCell(position.add(new ascii.Vector(1, 0))).isSpecial();
|
var right = this.getCell(position.add(DIR_RIGHT)).isSpecial();
|
||||||
var up = this.getCell(position.add(new ascii.Vector(0, -1))).isSpecial();
|
var up = this.getCell(position.add(DIR_UP)).isSpecial();
|
||||||
var down = this.getCell(position.add(new ascii.Vector(0, 1))).isSpecial();
|
var down = this.getCell(position.add(DIR_DOWN)).isSpecial();
|
||||||
return new ascii.CellContext(left, right, up, down);
|
return new ascii.CellContext(left, right, up, down);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue