Skip to content

Commit

Permalink
Merge pull request summernote#600 from HackerWins/feature/history-in-…
Browse files Browse the repository at this point in the history
…a-line

Feature/history in a line
  • Loading branch information
hackerwins committed Sep 16, 2014
2 parents 728b8dc + adf3bfc commit 1785095
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 167 deletions.
130 changes: 78 additions & 52 deletions dist/summernote.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Copyright 2013 Alan Hong. and outher contributors
* summernote may be freely distributed under the MIT license./
*
* Date: 2014-09-14T04:54Z
* Date: 2014-09-15T07:34Z
*/
(function (factory) {
/* global define */
Expand Down Expand Up @@ -517,6 +517,8 @@
return isInline(node) && !ancestor(node, isPara);
};

var isBody = makePredByNodeName('BODY');

/**
* blank HTML for cursor position
*/
Expand Down Expand Up @@ -966,7 +968,7 @@
* @param {Node} node
*/
var makeOffsetPath = function (ancestor, node) {
var ancestors = list.initial(listAncestor(node, func.eq(ancestor)));
var ancestors = listAncestor(node, func.eq(ancestor));
return $.map(ancestors, position).reverse();
};

Expand All @@ -979,7 +981,11 @@
var fromOffsetPath = function (ancestor, aOffset) {
var current = ancestor;
for (var i = 0, len = aOffset.length; i < len; i++) {
current = current.childNodes[aOffset[i]];
if (current.childNodes.length <= aOffset[i]) {
current = current.childNodes[current.childNodes.length - 1];
} else {
current = current.childNodes[aOffset[i]];
}
}
return current;
};
Expand Down Expand Up @@ -1172,6 +1178,7 @@
isPurePara: isPurePara,
isInline: isInline,
isBodyInline: isBodyInline,
isBody: isBody,
isParaInline: isParaInline,
isList: isList,
isTable: makePredByNodeName('TABLE'),
Expand Down Expand Up @@ -2260,6 +2267,9 @@
var selection = document.getSelection();
if (selection.rangeCount === 0) {
return null;
} else if (dom.isBody(selection.anchorNode)) {
// Firefox: returns entire body as range on initialization. We won't never need it.
return null;
}

var nativeRng = selection.getRangeAt(0);
Expand Down Expand Up @@ -2686,9 +2696,9 @@
for (var idx = 0, len = commands.length; idx < len; idx ++) {
this[commands[idx]] = (function (sCmd) {
return function ($editable, value) {
recordUndo($editable);

document.execCommand(sCmd, false, value);

recordUndo($editable);
};
})(commands[idx]);
}
Expand All @@ -2705,9 +2715,10 @@
if (rng.isCollapsed() && rng.isOnCell()) {
table.tab(rng);
} else {
recordUndo($editable);
typing.insertTab($editable, rng, options.tabsize);
triggerOnChange($editable);

recordUndo($editable);
}
};

Expand All @@ -2727,45 +2738,50 @@
* @param {Node} $editable
*/
this.insertParagraph = function ($editable) {
recordUndo($editable);
typing.insertParagraph($editable);
triggerOnChange($editable);

recordUndo($editable);
};

/**
* @param {jQuery} $editable
*/
this.insertOrderedList = function ($editable) {
recordUndo($editable);
bullet.insertOrderedList($editable);
triggerOnChange($editable);

recordUndo($editable);
};

/**
* @param {jQuery} $editable
*/
this.insertUnorderedList = function ($editable) {
recordUndo($editable);
bullet.insertUnorderedList($editable);
triggerOnChange($editable);

recordUndo($editable);
};

/**
* @param {jQuery} $editable
*/
this.indent = function ($editable) {
recordUndo($editable);
bullet.indent($editable);
triggerOnChange($editable);

recordUndo($editable);
};

/**
* @param {jQuery} $editable
*/
this.outdent = function ($editable) {
recordUndo($editable);
bullet.outdent($editable);
triggerOnChange($editable);

recordUndo($editable);
};

/**
Expand All @@ -2776,14 +2792,14 @@
*/
this.insertImage = function ($editable, sUrl, filename) {
async.createImage(sUrl, filename).then(function ($image) {
recordUndo($editable);

$image.css({
display: '',
width: Math.min($editable.width(), $image.width())
});
range.create().insertNode($image[0]);
triggerOnChange($editable);

recordUndo($editable);
}).fail(function () {
var callbacks = $editable.data('callbacks');
if (callbacks.onImageUploadError) {
Expand All @@ -2798,8 +2814,6 @@
* @param {String} sUrl
*/
this.insertVideo = function ($editable, sUrl) {
recordUndo($editable);

// video url patterns(youtube, instagram, vimeo, dailymotion, youku)
var ytRegExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var ytMatch = sUrl.match(ytRegExp);
Expand Down Expand Up @@ -2857,6 +2871,8 @@
$video.attr('frameborder', 0);
range.create().insertNode($video[0]);
triggerOnChange($editable);

recordUndo($editable);
}
};

Expand All @@ -2867,10 +2883,10 @@
* @param {String} tagName
*/
this.formatBlock = function ($editable, tagName) {
recordUndo($editable);

tagName = agent.isMSIE ? '<' + tagName + '>' : tagName;
document.execCommand('FormatBlock', false, tagName);

recordUndo($editable);
};

this.formatPara = function ($editable) {
Expand All @@ -2895,8 +2911,6 @@
* @param {String} value - px
*/
this.fontSize = function ($editable, value) {
recordUndo($editable);

document.execCommand('fontSize', false, 3);
if (agent.isFF) {
// firefox: <font size="3"> to <span style='font-size={value}px;'>, buggy
Expand All @@ -2907,6 +2921,8 @@
return this.style.fontSize === 'medium';
}).css('font-size', value + 'px');
}

recordUndo($editable);
};

/**
Expand All @@ -2915,11 +2931,12 @@
* @param {String} value
*/
this.lineHeight = function ($editable, value) {
recordUndo($editable);
style.stylePara(range.create(), {
lineHeight: value
});
triggerOnChange($editable);

recordUndo($editable);
};

/**
Expand All @@ -2932,12 +2949,12 @@
this.unlink = function ($editable) {
var rng = range.create();
if (rng.isOnAnchor()) {
recordUndo($editable);

var anchor = dom.ancestor(rng.sc, dom.isAnchor);
rng = range.createFromNode(anchor);
rng.select();
document.execCommand('unlink');

recordUndo($editable);
}
};

Expand All @@ -2956,8 +2973,6 @@
var isNewWindow = linkInfo.newWindow;
var rng = linkInfo.range;

recordUndo($editable);

if (options.onCreateLink) {
linkUrl = options.onCreateLink(linkUrl);
}
Expand All @@ -2973,6 +2988,8 @@

range.createFromNode(anchor).select();
triggerOnChange($editable);

recordUndo($editable);
};

/**
Expand Down Expand Up @@ -3021,20 +3038,20 @@
var oColor = JSON.parse(sObjColor);
var foreColor = oColor.foreColor, backColor = oColor.backColor;

recordUndo($editable);

if (foreColor) { document.execCommand('foreColor', false, foreColor); }
if (backColor) { document.execCommand('backColor', false, backColor); }
};

this.insertTable = function ($editable, sDim) {
recordUndo($editable);
};

this.insertTable = function ($editable, sDim) {
var dimension = sDim.split('x');
var rng = range.create();
rng = rng.deleteContents();
rng.insertNode(table.createTable(dimension[0], dimension[1]));
triggerOnChange($editable);

recordUndo($editable);
};

/**
Expand All @@ -3043,9 +3060,9 @@
* @param {jQuery} $target
*/
this.floatMe = function ($editable, value, $target) {
recordUndo($editable);

$target.css('float', value);

recordUndo($editable);
};

/**
Expand All @@ -3055,12 +3072,12 @@
* @param {jQuery} $target - target element
*/
this.resize = function ($editable, value, $target) {
recordUndo($editable);

$target.css({
width: $editable.width() * value + 'px',
height: ''
});

recordUndo($editable);
};

/**
Expand Down Expand Up @@ -3095,9 +3112,9 @@
* @param {jQuery} $target - target element
*/
this.removeMedia = function ($editable, value, $target) {
recordUndo($editable);

$target.detach();

recordUndo($editable);
};
};

Expand All @@ -3106,45 +3123,51 @@
* @class
*/
var History = function () {
var undoStack = [], redoStack = [];
var stack = [], stackOffset = 0;

var makeSnapshot = function ($editable) {
var editable = $editable[0];
var rng = range.create();
var emptyBookmark = {s: {path: [0], offset: 0}, e: {path: [0], offset: 0}};

return {
contents: $editable.html(),
bookmark: rng.bookmark(editable)
bookmark: (rng ? rng.bookmark(editable) : emptyBookmark)
};
};

var applySnapshot = function ($editable, snapshot) {
$editable.html(snapshot.contents);
// FIXME: Still buggy, use marker tag
// range.createFromBookmark($editable[0], snapshot.bookmark).select();
if (snapshot.contents !== null) {
$editable.html(snapshot.contents);
}
if (snapshot.bookmark !== null) {
range.createFromBookmark($editable[0], snapshot.bookmark).select();
}
};

this.undo = function ($editable) {
var snapshot = makeSnapshot($editable);
if (!undoStack.length) {
return;
if (0 < stackOffset) {
stackOffset--;
applySnapshot($editable, stack[stackOffset]);
}
applySnapshot($editable, undoStack.pop());
redoStack.push(snapshot);
};

this.redo = function ($editable) {
var snapshot = makeSnapshot($editable);
if (!redoStack.length) {
return;
if (stack.length - 1 > stackOffset) {
stackOffset++;
applySnapshot($editable, stack[stackOffset]);
}
applySnapshot($editable, redoStack.pop());
undoStack.push(snapshot);
};

this.recordUndo = function ($editable) {
redoStack = [];
undoStack.push(makeSnapshot($editable));
// Wash out stack after stackOffset
if (stack.length > stackOffset) {
stack = stack.slice(0, stackOffset);
}

// Create new snapshot and push it to the end
stack.push(makeSnapshot($editable));
stackOffset++;
};
};

Expand Down Expand Up @@ -4266,7 +4289,10 @@
}

// History
layoutInfo.editable.data('NoteHistory', new History());
var history = new History();
// Create first undo stack
history.recordUndo(layoutInfo.editable);
layoutInfo.editable.data('NoteHistory', history);

// basic event callbacks (lowercase)
// enter, focus, blur, keyup, keydown
Expand Down
4 changes: 2 additions & 2 deletions dist/summernote.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit 1785095

Please sign in to comment.