Can anyone help fit Autosave into WYSIWYG?

Events happening in the community are now at Drupal community events on www.drupal.org.
liquidcms's picture

Hey gang,

I am (more or less) the maintainer of the Autosave module. I think this is pretty important module for anyone using Drupal for any sort of web based publishing system. Surprised not more people stressing that i haven't ported to Drupal 6 yet.

[FYI - Autosave saves your node edit form in the background in case your browser dies you don't lose your work. When you return to edit; if there was a saved copy it will ask if you want to use that or keep the last submitted copy]

The D5 version of Autosave was tied in to TinyMCE; meaning either it worked with no JS editor or it worked with Tiny.

I am just trying to finish the port to D6 and at the same time cleaning up the code and making an attempt to remove dependency on TinyMCE (i.e. people are asking for it to work with FCK and ideally it should work with any JS editor).

The reason for current editor dependency is that the module (via ajax) basically stores a serialized version of the node form. The problem is that Tiny (and i suspect other editors) use an iframe "copy" of the node form and i guess at some point sync these up on node load and submit. But, this sync doesn't occur continually; so when the autosave ajax hits; the only form it sees is the one with the "real" form fields which are the values that were originally loaded at node load and not the iframe fields that the user has been adding new content to.

I am not a huge jq expert; but if someone out there could think of a slick way to have the autosave "Save" routine drill down to see if there is a hidden iframe form; and save those values (or possibly just update the hidden "real" fields) - i think this module could then become editor independent.

Could possibly provide some funding for this work as well.

Comments

tiny/fck structures

liquidcms's picture

Just to help things along; i have mapped out the structure for both FCK and Tiny (3.0). Example is for the Body field.

FCK

body-field-wrapper
edit-body-wrapper
  label
  iframe
  resizable text area (div)
    span
      textarea edit-body  [real field content] hidden
      iframe
       iframe
        body
         [editable content]

Tiny

body-field-wrapper
edit-body-wrapper
  label
  textarea edit-body  [real field content] hidden
  edit=body-parent
   iframe
    body
     [editable content]

even though these structures aren't too close; seems like there should be a reasonably simple jq method to simply do an update to the [real field content] prior to autosave saving the form.

Using editor APIs to get the textarea data?

markus_petrux's picture

TinyMCE provides getContent(), FCKeditor provides GetData(), Yahoo! Editor provides saveHTML(). I do not know about others.

I used these methods in the Dirty Forms module. See this particular code at the end of:

http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/dirtyforms/...

Though DF does not work fine in all situations, but I guess the above mentioned methods might help you here.

Or a tricky script to get the iframe of the current editor

jide's picture

Too bad Wysiwyg does not provide an API function to get the content of the editor... I don't remember if it is planed for 3.x release but definitely a must have !

In a module i made, i had to get the body value of the editor's iframe. Here's how I did - assuming you know the instanceId :

var instance = Drupal.wysiwyg.instances[instanceId];
var config = Drupal.settings.wysiwyg.configs[instance.editor][instance.format];
var iframe = $('iframe', $('#'+instance.field).parent());

It may not work in every case, but it may be useful.

close?

liquidcms's picture

hey jide,

your code might be close (Tiny 3.0) but iframe simply returns object with [0] = iframe#edit-body_ifr, not actual body html

but, maybe thats what you expected?

Closer !

jide's picture

Peter,

Yes that was the expected result.
If you want to get the body node, you can do this :

var iframeWindow = iframe[0].contentWindow;
var iframeDocument = iframeWindow.document;
var body = $('body', iframeDocument);
var content = body.html();

this works

liquidcms's picture

this works though:

$('iframe#edit-body_ifr').contents().find('body').html();

where #edit-body_ifr is from instance above

need to see if this also works for FCK now; suspect it does

jide's picture

Here : http://drupal.org/node/613204

So in this case you would simply have to do :

var instance = Drupal.wysiwyg.instances[instanceId];
var content = instance.getContent();

That would definitely be an easier and safer way to do it ;)

very cool; i'll check it

liquidcms's picture

very cool; i'll check it out.

Don't suppose you added a .putContent as well? :)

For autosave, when user comes back to a node edit that they have lost session for; they are presented with option to review what they had before browser was closed. The form (real, hidden fields, not js editor fields) is reloaded for the user to look at and they get a popup asking if they want to use these field values or use the older last submitted values.

Need to head out for a bit; will test your getContents patch when i get back.. thanks a ton for this.

insert API function

jide's picture

No I did not... but it already exists ;)

Drupal.wysiwyg.instances[instanceId].insert(content);

I advise you to do a console.log() on the instance to see all methods available, or check the files at modules/wysiwyg/editors/js.

missing methods

liquidcms's picture

sadly the insert method does just that.. inserts. but it doesn't do a replace - so it will only ADD content to the existing content (which in my case means i get duplicated content in iframe fields). Looking through code there seems to be no remove or replace content methods - either of these would help.

issue posted

liquidcms's picture

and i added a new issue for this here: http://drupal.org/node/614146

any idea?

liquidcms's picture

this is test code i wrote to try this out.. eventually will need to loop through all instances; but for now just trying this approach on the body field.

  var instance = Drupal.wysiwyg.instances['edit-body'];
  var content = instance.getContent();
  $('#edit-body').html(content);
  var serialized = $('#node-form').formHash();

in firebug i can see that the new content (i.e content entered into iframe field) does get pullled correctly into content. And, in firebug i can that the edit-body div does get assigned this new content; but, for some reason the formHash() function returns nothing in that field.

formHash is from jq field plugin and returns a serialized array of the entire form.

Hey Peter, That's no surprise

jide's picture

Hey Peter,

That's no surprise to me that formHash() does not return the iframes values. I never used the function but if i had implemented this it would definitely not return the content of iframes.

You could juste replace the 'edit-field=' bit (or something like that) value with the content you retrieved.

Or maybe...

jide's picture

Another approach could be to use the detach() method on the instance and then the attach() method again so that the regular field content is populated again with the right value, but i am not sure this is the right way to do this.

not iframe

liquidcms's picture

yea, thats not what i was doing.. you're right formHash won't pull iframe content.. which is why the $('#edit-body').html(content); line takes the iframe content and updates the real field so that formHash should see it. but even though i see the real field with updated content from iframe - formHash returns nothing at all.. very odd

originally, to make this work - we had a Tiny getContents kinda hack in the field plugin - but trying to avoid that if possible.

although, might just hack anyway since already need to hack field plugin since it can't deal with fields with [] in the names.

i'll try detach/attach.. maybe some reason that works different than just setting html(content)

Okay, sorry, i misread you

jide's picture

Okay, sorry, i misread your previous comment.
Very odd indeed... Maybe you could try $('#edit-body').val(content); ?

sweet...

liquidcms's picture

yup, .val(content) works. Should be almost there now... just need to do the loop and deal with the flipping back and forth between values stored in node and the autosaved values - and this works now for plain text fields; just need to tweak to work with iframe content. i think with concepts you have shown me above - rest should be trivial.

thanks so much for your help.

Wysiwyg

Group organizers

Group categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds:

Hot content this week