Jump to content

Form Save Reminder


Soma
 Share

Recommended Posts

Sounds cool, I look forward to checking this one out. We will get something setup in the core for the type of monitoring that you need so that you don't have to bundle the InputfieldTinyMCE.js if you don't want to.

Link to comment
Share on other sites

Thanks Ryan for the help. I think this would be nice feature to have implemented by default somehow as installed module(?).

Hehe apeisa, seems so...

Just updated this module, and attached new version to first post. I recognized that I messed up something and wouldn't work as intended. Also updated check for sortable changes.

Link to comment
Share on other sites

Just attached the working latest version 2. See first post.

- works for all inputfiledtypes

- works for tinymce

- works for sortable fields

- should be crossbrowser save, although not really tested yet other than latest safari, chrome, firefox

Tried to attach the same hook also to "template/edit?id=" and "field/edit?id=" pages, but js didn't get included.

I can manage when using Page::render, the js gets attached as the first js, even before jquery core. So it wouldn't work, thats why I chosed Process::execute.

Is that right, that I might should use str_replace version to add js on bottom of js list?

Link to comment
Share on other sites

Hi Soma. Looking great, just got a change to try it out and seems to work nicely … and very useful too! A few comments:

1. Rather than including a separately copy of InputfieldTinyMCE.js, I recommend adding this to your PageEditCheckState.js (in your ready handler):

var TinyMCE_change = function(ed) {
    if(ed.isDirty) {
        // the data changed 
        addCheck(); 
    }
};  

// modify PW's JS config data for each TinyMCE instance
$(".InputfieldTinyMCE textarea").each(function() {
    config[this.id].onchange_callback = TinyMCE_change;
}); 

2. May not be entirely necessary, but you may be able to confine your input checks to those in an Inputfields form, just to keep it out of any other forms that might be on the page (like search engine, etc.):

$('input,textarea,select', 'form > ul.Inputfields').live('input change',function() {

or

$('input,textarea,select,form', 'form#ProcessPageEdit').live('input change',function() {

3. It looks like your callbacks are getting called on every character pressed. Just wondering about overhead of doing this. Why not just do the 'change' event for text/textarea fields?

Link to comment
Share on other sites

Tried to attach the same hook also to "template/edit?id=" and "field/edit?id=" pages, but js didn't get included.

I can manage when using Page::render, the js gets attached as the first js, even before jquery core. So it wouldn't work, thats why I chosed Process::execute.

Is that right, that I might should use str_replace version to add js on bottom of js list?

I think that the way you are doing it is fine. The only reason it's not working with Template and Field edit is because those are a little different from PageEdit in that one process (ProcessTemplate and ProcessField) handles all the listing and editing functions. Whereas Page's are broader in scope, so the listing and editing are broken out into different Processes. As a result, the 'execute' function on both ProcessTemplate and ProcessField is being used to handle the 'list' action. For either one of those, you actually want to hook into the 'executeEdit' function rather than 'execute'.

Link to comment
Share on other sites

Thanks a lot Ryan for your time getting closer into this.

Exactly something like this I was looking for to overwrite tinymce onchange event afterwards... Thanks for the example, works great! Didn't know what isDirty was... Now the tinyMCE.js isn't needed anymore.

You're right that it creates a overhead using "input" and live. I was playing around and thought live would be nice if there would be something attached later to the dom... may not. BUT I changed swoped "live" with "one", now it gets only executed first time. And I also implemented your suggestion on the selector having a form > ul.Inputfield context. (BTW didn't work before getting the actual checkin from github. Did the missing closing ul on checkboxes may cause it not working. Well now it does! )

Thanks for the detailed insight on why the hook doesn't work for other edit pages. I got it working now and attached the Check to all edit pages, Page,Templates,Fields,Users,Permissions,Roles,Modules ...

I attached the latest version. Just minor, but I'm not good in giving good names. Do you think PageEditCheckState ist ok? Ans it's description?

Thanks again for your help!

Link to comment
Share on other sites

Didn't know what isDirty was...

Here's a little more info about the onchange_callback as well as the isDirty property (I meant to paste this in before):

http://www.tinymce.com/wiki.php/Configuration:onchange_callback

I doubt that the "live" is adding much overhead, though don't know for sure–but if one() works there that seems better. It was more the "input" event that I thought would be overhead heavy since it triggers on every character you type. I was just wondering if using 'input' (rather than just 'change') is necessary? (it may be, but wanted to check)

Do you think PageEditCheckState ist ok? Ans it's description?

I'm not sure I understand the current name because 'Check State' can mean a lot of things, and it's handling more than just the PageEdit form? I would probably use something like FormChangeMonitor or FormSaveReminder or something like that? But whatever you think is best. Your current name is certainly better than something like my PageLinkAbstractor module. :)

Link to comment
Share on other sites

Hey Ryan. Thanks for the infos. I didn't recognize first but this tinymce onchange_callback isn't working the way we need when hitting "save" button. It shows the confirm dialog although nothing has changed. Same problem as I got before with using onchange. Somehow tinymce changes something when hitting save button, before leaving page. That's why I used "onKeyUp" and "onExecCommand".  So I tried to find a solution, but I found only execcommand_callback which only works for when any command was used. So entering text doesn't work. There's no onkeyup_callback or something. Any help appreciated. Thanks.

// tinyMCE check if content has changed
var TinyMCE_change = function(ed) {
        addCheck();
};  
// modify PW's JS config data for each TinyMCE instance
$(".InputfieldTinyMCE textarea").each(function() {
    config[this.id].execcommand_callback = TinyMCE_change;
});
Link to comment
Share on other sites

Something like onkeyup may not be ideal not only because of the overhead but because those events may or may not represent changes (arrow keys being an example).

Are you using the ed.isDirty check? My understanding is that is necessary in order to really tell if it changed. Below is quoted from the TinyMCE page on the onchange_callback:

We strongly recommend users to utilize the isDirty method to determine if the editor contents were changed or not since this is much more exact because it doesn't need undo levels/blurring, etc. It is important to note that the onchange callback will not fire on each keystroke due to performance considerations. Executing the onchange callback all the time is just a bad design practice and it wastes the users CPU. It's better to check the isDirty state before leaving the page in a document onbeforeunload event. This is how the autosave plugin functions. The isDirty approach is the recommended way of tracking if an editor instance has been modified or not.

Also, make sure that you are just monitoring TinyMCE and not also the textarea separately. If the field is using TinyMCE, you will want your other code to ignore the textarea.  These are just ideas and you may have already tried this stuff, but I'll keep thinking here too. TinyMCE is always a hassle no matter what we try to do with it, but thankfully it's always great once things work. :)

Link to comment
Share on other sites

Yes I tried the ed.isDirty, and it must be returning true, although nothing has changed... there must be something happening maybe onunload when pressing "save" on page. Because save button is excluded from the check and when hitting removes the onbeforeunload from the window. So my guess is that tinymce does something in between or right after that... strange

Edit: If I remove the tinymce check, it works as desired. Another guess is, which you suggested, that it may change the hidden textarea before unloading... thus invoking the other form field check aka textarea... need to test a little more.

Link to comment
Share on other sites

I'm interested to know what you find here. I'm no expert with JS debugging, so ignore this if it sounds obvious. Placing a console.log(event) in your onchange event handler may make it easy to find, but might not help much if the page gets immediately loaded/reloaded. So an old fashioned alert() after a console.log of the event will pause everything and might make it possible to see what is doing the change.

Link to comment
Share on other sites

Thanks for the suggestions, but I didn't even bother to check what changes, fact was it changed (though only if save button pressed)

But I've been able to come up with a simple solution: I needed to somehow make the check not getting attached when pressing save. So after unsuccessfully trying to set the callback to null or anything, I tried using a flag, so when pressing button, it would be set to false and thus the tinymce check ed.isDirty would fail to continue... finally.

I just released the first initial version here: http://processwire.com/talk/index.php/topic,505.0.html

Thanks for the support.

Link to comment
Share on other sites

  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...