Why is it not possible to undo smiley or BB codes that one may have clicked on accidentally in a post they are trying to create?
Hmm... I've never noticed that before, but, it makes sense to me now that I consider it (what's happening is that the undo history of the
textarea is being cleared/reset each time its contents are changed programmatically: when you insert something into a post/PM by using the toolbar, then either an SMF-provided JavaScript function named
replaceText or one named
surroundText is invoked, and, in either case, the
textarea gets modified in such a way that the undo history is wiped; though, strictly speaking, I'm only considering the non-IE paths, and so maybe undo/redo did actually work correctly back in the day on Internet Explorer, but, that's neither here nor there).
Or can our script guy (PowerGlove) make some patch?

I can.


--- baseline/Themes/default/script.js 2006-11-01 07:46:11.000000000 +0000
+++ modified/Themes/default/script.js 2025-05-30 10:34:10.000000000 +0000
@@ -113,6 +113,14 @@
// Replaces the currently selected text with the passed text.
function replaceText(text, textarea)
{
+ // First, attempt to use the execCommand interface (it's deprecated, but, it doesn't wipe the undo history, which is nice).
+ if (typeof(document.execCommand) != "undefined")
+ {
+ textarea.focus();
+ if (document.execCommand("insertText", false, text))
+ return;
+ }
+
// Attempt to create a text range (IE).
if (typeof(textarea.caretPos) != "undefined" && textarea.createTextRange)
{
@@ -167,13 +175,11 @@
// Mozilla text range wrap.
else if (typeof(textarea.selectionStart) != "undefined")
{
- var begin = textarea.value.substr(0, textarea.selectionStart);
var selection = textarea.value.substr(textarea.selectionStart, textarea.selectionEnd - textarea.selectionStart);
- var end = textarea.value.substr(textarea.selectionEnd);
var newCursorPos = textarea.selectionStart;
var scrollPos = textarea.scrollTop;
- textarea.value = begin + text1 + selection + text2 + end;
+ replaceText(text1 + selection + text2, textarea);
if (textarea.setSelectionRange)
{
(Between the three different ways that I can think of to fix this, I think the above way makes the most sense in the context of the existing code. It's not perfect, but, it's much lighter than trying to spoof input events or maintain a non-native undo history, and, if the deprecated interface that it relies on does actually get removed at some point, then the logic will just more-or-less return to the state that it's currently in.)
(I'm not going to bug theymos with a PM about this one, so, hopefully he bumps into this post naturally. I didn't test this change very carefully, because that's always the most time-consuming part of the process, and it doesn't make much sense for me to allocate a huge block of time to doing cross-browser testing for a proposed change that theymos might never even see, let alone merge. If he merges it and it turns out that I've overlooked something, like maybe selection-preservation not working exactly how it used to, then the change can be undone and I'll attempt to revise/improve it at that point.)