How to tell TinyMCE UndoManager to ignore changes until explicitly notified to resume? - tinymce

Is it possible to use TinyMCE's UndoManager.ignore() when the callback is an asynchronous process?
What I am looking for is a way to "start ignoring" and a way to "stop ignoring".
(The background is that I have an async post-process that modifies the editor content, but I don't want those modifications to be part of the Undo/Redo stack, since they are not user-generated.)
This doesn't work, because the ignore() block callback finishes promise is resolved:
editor.undoManager.ignore(function() {
doAsyncProcess(editor).then(function() {
// doesn't work
});
}
What I want is something like this:
editor.undoManager.startIgnoring();
doAsyncProcess(editor).then(function() {
editor.undoManager.stopIgnoring();
});
but of course those APIs do not exist. Is there a workaround for this?

What I am looking for is a way to "start ignoring" and a way to "stop
ignoring".
It is hardly implementable. Mainly, because it may break something. Imagine the situation when something outside your process that needs a new undo level happened during that 'ignore time'.
Generally, all editor content operations within TinyMCE need to be synchronous. So the solution there is to normally get all the data needed asynchronously and then apply the update once it’s all been fetched.

Related

How to convert RxSwift's Single to Observable and ignore `complete` event?

The case is following.
I have a Single that I receive from a third-party API.
I want to transform this single to Observable, but the issue is Single transformed to Observable still completes my observable chain after emitting a value which I don't want to happen. I want that my observable never completes.
The question is is there any way easier than 'single.flatMap{ Observable.just($0)}' to do what I want?
I'd love to see some more code, because single.flatMap { Observable.just($0) } will not stop a completion event from happening so if you think it does, then something's wrong.
Frankly, .flatMap { Observable.just($0) } does nothing at all, i.e., you could remove it completely and not change your code at all.
That said, the most obvious way to stop a completed event is single.concat(Observable.never()).

Group multiple undo levels into on batch in TinyMCE

I am writing a custom plugin for TinyMCE. One of the new buttons makes a number of DOM manipulations in the document. The default undo behavior creates a few undo levels in the middle of the changes. If the user hits the undo button after using the plugin, he/she then sees a document with the operation partially reversed and really not in a proper state.
It looks like there used to be a pair of instance commands called mceBeginUndoLevel / mceEndUnoLevel (removed in version 3.3) that let a developer start/end a large undo batch that would be undone in a single operation....but I don't see anything in the docs that replaces that feature.
Some forum postings suggest using editor.undoManager.add() as a replacement, and that works for cases where you want more levels of undo during an operation, but I actually want less.
There is also a undoManager.onBeforeAdd event that you can hook into, but looking at the source for the undoManager, I don't think that hooking there will let you abort an undo snapshot.
So, is there a proper way to batch undo operations that I'm not seeing using the existing API? If not, my only other option seems to be patching the undoManager to allow the onBeforeAdd hook to abort a snapshot.
I suggest overwriting the current UndoManager. It is just a rather small file.
That's what we needed to do in order to suppress the creation of some unwanted undosteps.

ember.js route render: dom manipulation with setTimeout()?

if i wanted to call a jquery plugin (which inserts a table into the dom, for example) after a view has been rendered, are there a possibilities except doing this with window.setTimeout()?
This code does the job (1ms timeout; thats weird):
Route.HomeRoute = Ember.Route.extend({
renderTemplate: function() {
this.render("home"); // render the home view
window.setTimeout(function() {
$(".tables").insertTables(); // this would add a table
}, 1);
}
})
But this code doesn't work:
Route.HomeRoute = Ember.Route.extend({
renderTemplate: function() {
this.render("home"); // render the home view
$(".tables").insertTables(); // this would add a table
}
});
I know that there's Ember.View.didInsertElement(), but therefore i have to set a callback on the parent View, and was just wondering, why the code example above doesn't work as expected.
Many thanks!
I don't know wether my answer is 100% accurate, but i guess this is how it can be explained:
I guess the problem is, that you think that the render() method does its job synchronously. But this is not the case. Instead it schedules the rendering of the HomeView. The rendering is scheduled into the RunLoop of Ember. In the second example your code schedules the rendering and then immediately tries to access its DOM Elements (i guess .tables is part of the home template). But the View is not rendered at this time! The first example works, because there is 1ms timeout involved. During this timeout the Ember RunLoop will kick in and starts its magic. It performs the rendering and afterwards when the CPU is free again, your timeout function can be called.
Actually what you want to do here is: do something on my DOM, when the View was successfully rendered. This can be done in Ember, without the use of setTimeout. The following code accesses the RunLoop and schedules a function to be performed at the end of the RunLoop.
Ember.run.next(function() {
$(".tables").insertTables(); // this would add a table
});
Here is an article on the RunLoop, which is important to understand, if you want to understand those details of Ember:
- Article by machty
Last but not least: It seams totally awkward to do such DOM Manipulation in the Route. Your Route should always be free, of such things. Element and Selectors and jQuery Plugins should only be used in the View layer. Everything else seems bad. Maybe you want to share more details about why you chose this approach? There is likely a better solution that this one.
The reason why the second example doesn't work is probably due to the Ember.js Run Loop. this.render schedules the dom insertion for later in the current run loop.
DOM insertion is done at the end of the run loop, and by using setTimeout, you are calling the plugin after the run loop ends, therefore guaranteeing that the template was injected into the DOM. (no need for the 1ms, 0ms would probably work)
You might say this run loop thing is very complicated, especially for an Ember.js beginner. The thing is, ideally, it is supposed to be transparent to the app developer. The reason why you are encountering its side effects, is because DOM manipulation should not be handled in the router.
My first reaction was to tell you to use didInsertElement, or any code or hook inside the View, because that's where DOM manipulation should happen. But it seems you are aware of that and cannot use it for some reason (which I can't confirm or deny because I don't have enough information).
My advice to you, try your best to do it in didInsertElement.

Zend_Controller_Action _forward use (or abuse) cases

While developing a web app using ZF, I had an haha! moment regarding the _forward method in Zend_Controller_Action. As stated in the Programmer's Reference Guide, when calling the _forward method inside an action, the requested action will not be executed until the current action completes. This begs the question:
When would you use the _forward action to intentionally make sure your current action completes before starting another, aside from form processing (although you would probably place the _forward request at the end of the action anyway)? What are some clear cut examples of this? Any pitfalls or advantages to using this approach as apposed to an ActionStack?
_forward() just replaces module/controller/action parameters in Request object.
It just allows to change your mind on the go (without another request).
This has different consequences, depending on which dispatch loop state it is called. Some time setDispatched() is needed to execute.
Consider those scenarios:
First:
$this->_forward('some')
Second:
return $this->_forward('some');
Third:
$this->someAction();
// ececuted?
Fourth:
return $this->someAction();
// executed?
I really only use _forward for two reasons:
I want to redirect but don't want the user's URL to change.
I want to pass some (non-string) object to another action.
$this->_forward('index', null, null, array('create_task_form' => $form));
In each case, the target action can stand by itself, without the originator, and usually just marshals up the display.
When would you use the _forward action to intentionally make sure your current action completes before starting another
I don't think it's used to let the current action complete before _forward() is used. That looks more like a call to your domain logic (model, service, something like that) than handling a request which is what an action is for.
yourAction
if(conditionsAreNotMet()) {
return _forward(anotherAction);
}
I think _forward() is provided to have an early exit point in your action (which logic is all focused on one thing, for example presenting news); without the need of performing another request (like _redirect()) and thus putting more load on the web server.

What's a good maintainable way to name methods that are intended to be called by IBActions?

I am creating function (for example) to validate content, then if it is valid, close the view, if it is not, present further instructions to the user. (Or other such actions.) When I go to name it, I find myself wondering, should I call it -doneButtonPressed or -validateViewRepairAndClose? Would it be better to name the method after what UI action calls it, or name it after what it does? Sometimes it seems simple, things like -save are pretty clear cut, other times, and I can't thing of a specific example right off, but I know some have seemed like naming them after what they do is just so long and confusing it seems better to just call them xButtonPressed where x is the word on the button.
It's a huge problem!!! I have lost sleep over this.
Purely FWIW ... my vote is for "theSaveButton" "theButtonAtTheTopRight" "userClickedTheLaunchButton" "doubleClickedOnTheRedBox" and so on.
Generally we name all those routines that way. However .. often I just have them go straight to another routine "launchTheRocket" "saveAFile" and so on.
Has this proved useful? It has because often you want to launch the rocket yourself ... in that case call the launchTheRocket routine, versus the user pressing the button that then launches the rocket. If you want to launch the rocket yourself, and you call userClickedTheLaunchButton, it does not feel right and looks more confusing in the code. (Are you trying to specifically simulate a press on the screen, or?) Debugging and so on is much easier when they are separate, so you know who called what.
It has proved slightly useful for example in gathering statistics. The user has requested a rocket launch 198 times, and overall we've launched the rocket 273 times.
Furthermore -- this may be the clincher -- say from another part of your code you are launching the rocket, using the launch-the-rocket message. It makes it much clearer that you are actually doing that rather than something to do with the button. Conversely the userClickedTheLaunchButton concept could change over time, it might normally launch the rocket but sometimes it might just bring up a message, or who knows what.
Indeed, clicking the button may also trigger ancillary stuff (perhaps an animation or the like) and that's the perfect place to do that, inside 'clickedTheButton', as well as then calling the gutsy function 'launchTheRocket'.
So I actually advocate the third even more ridiculously complicated solution of having separate "userDidThis" functions, and then having separate "startANewGame" functions. Even if that means normally the former does almost nothing, just calling the latter!
BTW another naming option would be combining the two... "topButtonLaunchesRockets" "glowingCubeConnectsSocialWeb" etc.
Finally! Don't forget you might typically set them up as an action, which changes everything stylistically.
[theYellowButton addTarget:.. action:#selector(launchRockets) ..];
[theGreenButton addTarget:.. action:#selector(cleanUpSequence) ..];
[thatAnimatingButtonSallyBuiltForUs addTarget:.. action:#selector(resetAll) ..];
[redGlowingArea addTarget:.. action:#selector(tryGetRatingOnAppStore) ..];
perhaps that's the best way, documentarily wise! This is one of the best questions ever asked on SO, thanks!
I would also go with something along the lines of xButtonPressed: or handleXTap: and then call another method from within the handler.
- (IBAction)handleDoneTap:(id)sender {
[self closeView];
}
- (void)closeView {
if ([self validate]) {
// save and close
}
else {
// display error information
}
}