mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-30 10:56:53 -05:00
672c89e0bc
install nodejs using nvm fix issues with Windows/Linux new line characters update auto-reload-brunch drop bless-brunch resolve related issue #3588
236 lines
6.7 KiB
JavaScript
236 lines
6.7 KiB
JavaScript
var Spade = function Spade() {
|
|
this.stack = [];
|
|
}
|
|
Spade.prototype = {
|
|
track: function(_elem) {
|
|
this.target = _elem;
|
|
|
|
var spade = this;
|
|
|
|
var el = document.createElement("div");
|
|
|
|
keyHook = null;
|
|
if(_elem.textInput && _elem.textInput.getElement) {
|
|
keyHook = _elem.textInput.getElement();
|
|
} else {
|
|
keyHook = _elem;
|
|
}
|
|
keyHook.addEventListener("keydown", function(_event) {spade.createEvent(spade.target)});
|
|
//Maybe this is needed depending on Firefox/other browsers? Duplicate non-diff events get compiled down.
|
|
keyHook.addEventListener("keyup", function(_event) {spade.createEvent(spade.target)});
|
|
_elem.addEventListener("mouseup", function(_event) {spade.createEvent(spade.target)});
|
|
},
|
|
createEvent: function(_target) {
|
|
if(_target.getValue) {
|
|
this.stack.push({
|
|
"startPos":_target.selection.getCursor(),
|
|
"endPos":_target.selection.getSelectionAnchor(),
|
|
"content":_target.getValue(),
|
|
"timestamp":(new Date()).getTime()
|
|
});
|
|
} else {
|
|
this.stack.push({
|
|
"startPos":_target.selectionStart,
|
|
"endPos":_target.selectionEnd,
|
|
"content":_target.value,
|
|
"timestamp":(new Date()).getTime()
|
|
});
|
|
}
|
|
},
|
|
compile: function() {
|
|
var compiledStack = [];
|
|
if(this.stack.length > 0) {
|
|
var startTime = this.stack[0].timestamp;
|
|
var sum = 0;
|
|
var sum2 = 0;
|
|
for(var i = 0; i < this.stack.length; i++) {
|
|
var c = this.stack[i];
|
|
var adjustedTimestamp = c.timestamp - startTime;
|
|
|
|
var tString = ""; //The changed string.
|
|
var fIndex = null; //The first index of changes.
|
|
var eIndex = null; //The last index of changes.
|
|
var dCount = 0; //Amount of character changes.
|
|
if(i >= 1) {
|
|
var p = this.stack[i - 1];
|
|
var isOkay = false;
|
|
for(var key in p) {
|
|
if(key != "timestamp") {
|
|
if(typeof p[key] === "string") {
|
|
if(p[key] !== c[key]) {
|
|
isOkay = true;
|
|
}
|
|
} else {
|
|
for(var key2 in p[key]) {
|
|
if(c[key][key2] !== undefined) {
|
|
if(p[key][key2] !== c[key][key2]) {
|
|
isOkay = true;
|
|
}
|
|
} else {
|
|
console.warn("Warning: c[key][key2] doesn't exist, but p[key][key2] does.");
|
|
isOkay = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(!isOkay) {
|
|
sum2++;
|
|
continue;
|
|
}
|
|
sum++;
|
|
if(p.content != c.content) {
|
|
//Check from the start to the end, which characters are different.
|
|
for(var j = 0; j < Math.max(p.content.length, c.content.length); j++) {
|
|
if(p.content.charAt(j) === c.content.charAt(j)) {
|
|
if(fIndex != null) {
|
|
tString += c.content.charAt(j);
|
|
dCount++;
|
|
}
|
|
} else {
|
|
tString += c.content.charAt(j);
|
|
if(fIndex === null) {
|
|
fIndex = j;
|
|
}
|
|
dCount++;
|
|
}
|
|
}
|
|
//Check from the end to the start, which characters are different.
|
|
for(var j = 0; j < Math.min(p.content.length, c.content.length) - fIndex; j++) {
|
|
if(p.content.charAt(p.content.length - 1 - j) !== c.content.charAt(c.content.length - 1 - j)) {
|
|
if(eIndex == null) {
|
|
eIndex = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//This accounts for the fact when changing from "aa" to "aaa" (for example).
|
|
if(eIndex === null) {
|
|
eIndex = Math.min(p.content.length, c.content.length) - fIndex;
|
|
}
|
|
tString = tString.substring(0, tString.length - eIndex);
|
|
}
|
|
} else {
|
|
tString = c.content;
|
|
fIndex = 0;
|
|
eIndex = tString.length;
|
|
}
|
|
compiledStack.push({
|
|
"timestamp":adjustedTimestamp,
|
|
"difContent":tString,
|
|
"difFIndex":fIndex,
|
|
"difEIndex":eIndex,
|
|
"selFIndex":c.startPos,
|
|
"selEIndex":c.endPos
|
|
});
|
|
}
|
|
} else {
|
|
//Just return the empty array.
|
|
}
|
|
return compiledStack;
|
|
},
|
|
play: function(_stack, _elem) {
|
|
if(_stack.length === 0) {
|
|
console.warn("SPADE: No events to play.")
|
|
return
|
|
}
|
|
if(_elem.setValue) {
|
|
_elem.setValue(_stack[0].difContent);
|
|
} else {
|
|
_elem.value = _stack[0].difContent
|
|
}
|
|
_stack = _stack.slice();
|
|
_stack.shift();
|
|
var curTime, dTime;
|
|
var elapsedTime = 0;
|
|
var prevTime = (new Date()).getTime();
|
|
var playbackInterval = setInterval(function() {
|
|
curTime = (new Date()).getTime();
|
|
dTime = curTime - prevTime;
|
|
dTime *= 1; //Multiply for faster/slower playback speeds.
|
|
elapsedTime += dTime;
|
|
var tArray = _stack.filter(function(_event) {
|
|
return ((_event.timestamp) >= (elapsedTime - dTime)) && ((_event.timestamp) < (elapsedTime));
|
|
});
|
|
for(var i = 0; i < tArray.length; i++) {
|
|
var tEvent = tArray[i];
|
|
var oVal = null;
|
|
if(_elem.getValue) {
|
|
oVal = _elem.getValue();
|
|
} else {
|
|
oVal = _elem.value;
|
|
}
|
|
if(tEvent.difFIndex !== null && tEvent.difEIndex !== null) {
|
|
if(_elem.setValue) {
|
|
_elem.setValue(oVal.substring(0, tEvent.difFIndex) + tEvent.difContent + oVal.substring(oVal.length - tEvent.difEIndex, oVal.length));
|
|
} else {
|
|
_elem.value = oVal.substring(0, tEvent.difFIndex) + tEvent.difContent + oVal.substring(oVal.length - tEvent.difEIndex, oVal.length)
|
|
}
|
|
}
|
|
if(_elem.selection && _elem.selection.moveCursorToPosition) {
|
|
//Maybe this will work someday
|
|
_elem.selection.moveCursorToPosition(tEvent.selFIndex);
|
|
_elem.selection.setSelectionAnchor(tEvent.selEIndex.row, tEvent.selEIndex.column);
|
|
_elem.selection.selectTo(tEvent.selFIndex.row, tEvent.selFIndex.column);
|
|
} else {
|
|
//Likewise
|
|
_elem.focus();
|
|
_elem.setSelectionRange(tEvent.selFIndex, tEvent.selEIndex);
|
|
}
|
|
}
|
|
if(_stack[_stack.length - 1] === undefined || elapsedTime > _stack[_stack.length - 1].timestamp) {
|
|
clearInterval(playbackInterval);
|
|
}
|
|
prevTime = curTime;
|
|
}, 10);
|
|
},
|
|
debugPlay: function(_stack) {
|
|
var area = document.createElement('textarea');
|
|
area.zIndex = 9999;
|
|
area.style.width = "512px";
|
|
area.style.height = "512px";
|
|
area.style.position = "absolute";
|
|
area.style.left = "100px";
|
|
area.style.top = "100px";
|
|
document.body.appendChild(area);
|
|
this.play(_stack, area);
|
|
},
|
|
condense: function(_stack) {
|
|
var compressedArray = [];
|
|
for(var i = 0; i < _stack.length; i++) {
|
|
var u = _stack[i];
|
|
compressedArray.push([
|
|
u.timestamp,
|
|
u.difContent,
|
|
u.difFIndex,
|
|
u.difEIndex,
|
|
u.selFIndex.row,
|
|
u.selFIndex.column,
|
|
u.selEIndex.row,
|
|
u.selEIndex.column
|
|
]);
|
|
}
|
|
return compressedArray;
|
|
},
|
|
expand: function(_array) {
|
|
var uncompressedArray = [];
|
|
for(var i = 0 ; i < _array.length; i++) {
|
|
var c = _array[i];
|
|
uncompressedArray.push({
|
|
"timestamp":c[0],
|
|
"difContent":c[1],
|
|
"difFIndex":c[2],
|
|
"difEIndex":c[3],
|
|
"selFIndex":{
|
|
"row":c[4],
|
|
"column":c[5]
|
|
},
|
|
"selEIndex":{
|
|
"row":c[6],
|
|
"column":c[7]
|
|
},
|
|
});
|
|
}
|
|
return uncompressedArray;
|
|
}
|
|
}
|