TinyMCE autosave plugin and localStorage - tinymce

By default, TinyMCE's autosave plugin stores the editor's text in localStorage. Is there a way to tell it to use a different storage engine? Ultimately what I want to do is set up a listener on the storeDraft event so I can persist the contents to our server so the user can access the contents even after the autosave_retention limit has been surpassed. I know that I can set the autosave_rentention to 0 but even when I do I can see that it still writes the data to localStorage -- it just removes it (though, sometimes not immediately and it seems like a page reload short circuits that in some cases).
So basically, I'd like to hit 2 birds with one stone. I'd like to stop TinyMCE from storing the data in localStorage and, if I can specify a different "data store", then perhaps I can point it to my ajax handler which will persist to the back end.
Any advice would be greatly appreciated!
thnx,
Christoph

The autosave plugin is designed to work with local storage and has no option to change to a different storage mechanism. If you want to store the data on your server you would typically that with some custom code that uses either (a) TinyMCE events or (b) a timer to get the editor's current content and then send it to the server.
If you want to use TinyMCE events (https://www.tiny.cloud/docs/advanced/events/#editorevents) to trigger this process you would have code along these lines:
tinymce.init({
selector: "textarea",
...
setup: function (editor) {
editor.on('init change NodeChange Dirty', function (e) {
// 1. use getContent() to extract the editor's current HTML
// 2. send the HTML to your server
});
}
});
If you want to use a basic timer (e.g. setTimeout()) you would use that to trigger the same two actions as the sample code above.
In theory you could modify the autosave plugin to send data to your server as opposed to storing the data in local storage but I think you can do what you need in a far simpler way without needing to dig into the ~200 lines of code in the existing plugin.

Related

How to check if a form is fully loaded?

I have forms that contain controls in my application under test. These controls load data in their own threads.
I would like to add a block until the form is fully loaded.
How is this done?
I think the cleanest way to do that is to listen to AsyncContentLoadedEvent.
An other way, which assumes you know which components needs to be loaded, is to search the UI Automation Tree for the AutomationElement(s) directly (FindAll, FindFirst, TreeWalker).
If all AElements are available it means it's loaded. You could consider the childCount or various AutomationElementProperties to verify that. Of course several Patterns (e.g. ValuePattern) could be additionally used to verify the state of the AElements.
Alternativly to AsyncContentLoadedEvent, you could check out if your application uses some kind of UI Element for showing the current status of the loading process (HelpTextProperty, Icon, Label, etc..).
In such case I would simple query this certain AElement for it's current value/name/.. (or also color (not directly supported by UI Automation and requires some workaround)). and wait until it has the required state

jQuery File Upload's change callback returns nothing

Everything about the uploader is working perfectly, but one callback seems to do nothing:
.bind('fileuploadchange', function (e, data) {
console.log("foo");
})
Binding to the change event never returns anything... so my question:
1) Is this a bug? I'm using the most recent version.
2) Is there another/better way to detect when files are manually removed from the upload queue (something more elegant than reading DOM elements)?
There might be a bit of misunderstanding in what the fileuploadchange event does.
The admittedly limited documentation for the change event states:
Callback for change events of the fileInput collection.
That means it's an event callback for the native change event of all the file input elements of the fileupload widget.
This event only fires if the user selects one or more files via the file picker dialog that is displayed after clicking on the file input button.
Technically, the basic fileupload library doesn't keep track of a queue.
It's up to the UI implementation to handle this, via the various callbacks provided by the basic library.
Until the user actually starts the file upload, there is technically nothing the basic library could keep track of.
And as soon as a file upload is started, the done and fail events are your basic building blocks.
By the way, the sample UI implementation handles the removal of items that have not been started yet by triggering a manual fail event.

How do you set up an Optimizely test for a single-page app?

I have a single-page web app that presents a multi-step photo management "wizard", split up across several discrete steps (photo upload, styling, annotation, publishing) via a tab strip. On switching steps I set the URL hash to #publishing-step (or whichever step was activated).
How do I set up Optimizely tests to run on the various discrete steps of the wizard?
The browser never leaves the page, so it only gets a single window.load event. Its DOM isn't getting scrapped or regenerated, but just switches what page elements are visible at any one time via display: none or block, so the part I am trying to figure out is really mostly about in what way I go about the Optimizely test setup itself - it's fine (and likely necessary) if all edits get applied at once.
This thing unfortunately has to work in IE9, so I can't use history.pushState to get pretty discrete urls for each step.
There's actually several ways you could go about doing this, and which option you choose will largely depend on what's easiest for you AND how you plan to analyze the data.
If you want to use Optimizely's analytics dashboard:
I would recommend creating one experiment which will activate a bunch of other experiments at different times. The activation experiment will be targeted to everyone and run immediately when they get to your wizard. The other experiments will be set up with manual activation and triggered by this experiment.
The activation experiment would have code like:
window.optimizely = window.optimizely || [];
function hashChanged() {
if(location.hash === 'publishing-step') {
window.optimizely.push(['activate', 0000000000]);
}
if(location.hash === 'checkout-step') {
window.optimizely.push(['activate', 1111111111]);
}
}
window.addEventListener('hashchange', hashChanged, false);
Or you could call window.optimizely.push(['activate', xxxxxxxxx]); directly from your site's code instead of creating an activation experiment and listening for hashchange.
If you want to use a 3rd party analytics tool like Google Analytics:
You could do this all in one experiment with code similar to above, but in each "if" section instead of activating an experiment, you could run your variation code that makes changes to the wizard and sends special tracking information to your analytics sweet for later reporting. You'll have to do your own statistical significance calculation for this method (as Optimizely's data won't be "clean"), but this method actually works out better usually if properly configured.
Alternatively you could use the method outlined above but still try to use the Optimizely analytics dashboard by creating custom events on your experiment and sending data to them using calls like window.optimizely.push(["trackEvent", "eventName"]);
This article may also be helpful to you.
You'll probably need to do this yourself, using Optimizely's JS API to trigger actions on their end and tell it what your users did: https://www.optimizely.com/docs/api

GWT - Is it possible to create new HTML elements (from the server) or i can just to update the ones loaded on the client?

Im new about this technology, but I would like to know if is possible to create new object (html elements, such div/span/and so on...) dinamically on server and send it to the client, or if i can just load the ones made on client-side when i develop it in the application.
I don't ask how to do it (i think its a delicate argument), but if I can, and (if yes) where i can get some stuff/example/tutorial to do this.
Example
What i usually do :
...
public void onSuccess(Boolean result) {
if(result) {
myFunction();
}
}
...
myFunction() {
InlineLabel label=new InlineLabel();
this.add(label)
}
What im looking for :
...
public void onSuccess(InlineLabel result) {
this.add(result)
}
So, i don't need to load in advance the Object, but load them only if i click on some button (or if i perform an action). This will save a lot of code (that is inutil, if i don't do any action) loaded (as JavaScript) on the client.
As usual, thanks for your time!
GWT does not support the pattern you showed, but you can achieve a similar effect with "code splitting": read http://code.google.com/webtoolkit/doc/latest/DevGuideCodeSplitting.html
With code splitting, the client only downloads the script it needs right away (configured by the developer). If, for example, the user navigates to a more complex area of the UI that requires more widgets, additional code will be downloaded.
I'm not entirely sure I understand your question, but please feel free to amend your question or post a comment if I've missed the mark.
The host page
A GWT app is loaded in the following (simplified) process:
A host page (HTML) is loaded
A bootstrapping script is loaded
A compiled app script is loaded
The host page can contain any HTML you want. The only requirement is that you include a <script> element that loads the GWT bootstrapping script.
As a result, you can have the server return a page that contains any server-generated markup you like.
Server-rendered HTML at runtime
Once your app is running, you can send off asynchronous requests in your code to retrieve arbitrary data from the server. One option is to retrieve server-generated HTML and insert it into your application.
For this option, you'll want to instantiate an HTML widget, then use its setHTML method to insert the server-generated markup into the widget.
Client-generated
As an alternative, you can retrieve structured data from the server via GWT RPC. Objects created on a Java-based server are serialised by GWT on the server and deserialised on the client back into regular objects. You can then pull data out of these objects using accessor methods (getName, getId, etc.). At this point, you have several options:
Generate some HTML using StringBuilder and the like, then use setHTML on an HTML widget.
Generate DOM elements with the DOM class
Set the data into widgets and add them to panels or the root panel.

How to show previous url after user has canceled dialog with message from Activity#mayStop()?

In our app we need to check if the data is saved when we are in a particular place before navigating away from it. So the user should be able to negate a browser back button request. But by the time that the history value change event is received the url has already been changed. The History class doesn't seem to have a way to restore the url back. Anybody have any ideas?
In GWT 2.1 you get Activities and Places. And activity has a maystop method, which is exactly what you want, if I understand you correctly.
Use a window.onunload or window.onbeforeunload javascript callback to confrim/save state.
onbeforeunload example
I haven't actually implemented this behavior yet, but here is my plan and maybe it will work for you.
1) Each time you receive an onHistoryChanged event and decide to allow it, save the current historyToken in an instance variable somewhere.
2) Keep track of activity on the page that should block navigation. Use a data structure that can keep track of multiple activities, like multiple file uploads, multiple edits, etc.
3) When you receive a new onHistoryChanged event, if your data structure from #2 indicates that it's not safe to navigate, avoid changing the page and restore the historyToken that you saved in #1. I'm assuming that you can do this either by:
a) Calling History.newItem(oldHistoryToken, false) or
b) Calling History.newItem(oldHistoryToken, true) and keeping a flag to force the next onHistoryChanged to be ignored.
Again, I haven't actually implemented this so let me know how it works out.
If you have links that allow the user to leave the app and you want to prevent that as well, you'll need to also add an onbeforeunload.
Have a look at the PlaceManagerImpl class from the gwt-platform framework. Especially the onValueChange() method and the methods dealing with the onLeaveQuestion field.
Hope that helps.
In this issue report, t.broyer explains in his comment that such behavior was planned during design of Places framework. The most important part is:
mayStop was a mistake, or it should have only been called when unloading the app, not for internal navigation within the app.
So probably it's better to not use it at all...