jejacks0n / mercury

Mercury Editor: The Rails WYSIWYG editor that allows embedding full page editing capabilities directly inline.
http://jejacks0n.github.com/mercury
Other
2.63k stars 531 forks source link

post form on page results in error #18

Closed lvanderree closed 13 years ago

lvanderree commented 13 years ago

when you have a form on a page that is enriched with Mercury, and you post the form, Mercury returns a "Mercury.PageEditor failed to load: " + error + "\n\nPlease try refreshing." alert.

when navigating things go OK, but posting data result in this problem. I guess because the iFrame is not updated with the new content.

I haven't found any solution or work-around for this problem.

jejacks0n commented 13 years ago

I'll look into this.. I remember something subtle that I had to do in the past, which I should just work into the system properly. Thanks for the heads up.

lvanderree commented 13 years ago

Thanks Jeremy,

it would be great if you could help me with this. Given me a lead would already be very helpful, for now I have now idea where to start looking.

lvanderree commented 13 years ago

Hi Jeremy,

could you give me some insight in how things work, regarding this issue? Maybe I can help tackle this issue, since this is the most annoying bug at the moment.

What I understand is the following:

  1. normal page is loaded
  2. JavaScript is being executed
  3. Mercury builds an iFrame and moves the original page in the iFrame

From here I could use some help:

What will be the solution?

It is not completely clear to me how the Mercyrt-iFrame is intervening between the page and the browser (url-bar)

jejacks0n commented 13 years ago

I'm working on it tonight.. it needs to be added into the PageEditor#hijackLinks method. A similar behavior is needed on forms.

On Sep 8, 2011, at 3:19 PM, Leon van der Ree wrote:

Hi Jeremy,

could you give me some insight in how things work, regarding this issue? Maybe I can help tackle this issue, since this is the most annoying bug at the moment.

What I understand is the following:

  1. normal page is loaded
  2. JavaScript is being executed
  3. Mercury builds an iFrame and moves the original page in the iFrame

From here I could use some help:

  • How come clicking on links will result in the loading of the new requested page in the browser? (Is the click being caught in the iFrame and send to the browser, is this done automatically by the browser, is there some JavaScript intervention)
  • How come posting a form results in showing the requested page in the iFrame (url bar from browser is not updated, Mercury detects it has lost control.)

What will be the solution?

  • Make Merucry reload the page after a post, showing it the correct result page (although reloading is probably dangerous after a post (change of reposting data if no redirect has been performed)
  • Post to the browser (instead of the iFrame)
  • Make Mercury detect the post and update its state (and the browser url-bar)

It is not completely clear to me how the Mercyrt-iFrame is intervening between the page and the browser (url-bar)

Reply to this email directly or view it on GitHub: https://github.com/jejacks0n/mercury/issues/18#issuecomment-2044878

jejacks0n commented 13 years ago

It was basically a change to how PageEditor#hijackLinks (now #hijackLinksAndForms) worked. I just added forms to the list of elements that are "highjacked", which basically means that under some circumstances the target is set to _top.

So, if there's a form in the page with no target set (or the target is set to _self) we change that so the form will submit in the window where mercury is loaded, instead of the iframe. If the action of the form loads a page that loads mercury, mercury will simply reload and make things editable again.. if not (eg. the action of the form is somewhere offsite or something) mercury isn't loaded again, which would be appropriate.

It should also be noted that the standard onBeforeUnload behavior that's already in mercury that prompts about leaving the page is still presented to the user if changes have been made to editable regions.

jejacks0n commented 13 years ago

Ah, I should also mention that I moved a PageEditor option to the configuration. nonHijackableClasses, which allows you to provide an array of classes for elements that should not be hijacked in the way I outline above.

If you have a form that's handled entirely with ajax, there's no need to hijack it -- you can give it a classname, and provide that in the configuration and the target won't be set to _top.. this was primarily for lightbox style links, but the same may be applicable to forms (I find it hard to imagine, but I can't think of every scenario). =)

lvanderree commented 13 years ago

This is exactly what I was hoping for! Works like a charm!

I have 2 configuration options, one for my admin pages, where I post forms, and one for my onsite editing functionality, where I use AJAX. So the onBeforeUnload is convered!

Now my admin pages are usable again! And as you said already, the resulting page is covering the reloading of mercury again, which is as desired.

I also like it that my idea about how things work, regarding the intercepting (hijacking) of links with respect to the iFrame turned out to be OK. I didn't see you altered the target attribute, but I did suspect you where doing something like this. Since I didn't had time to look for it myself I hadn't found it yet, and because of my lack of experience with iFrames I couldn't say it for sure yet either.

You made my day! Unfortunately I cannot show you the site I am currently working on, but you probably already saw my django feincms-mercury plugin, which is being accepted in the feincms community already. As soon as I have a little bit more time I will improve the integration of our repositories!

lvanderree commented 13 years ago

There is now showing up a new (unforeseen) situation.

After a post, the resulting page contains a new instance of the mercury editor which does a reload (new request to the server) of the content. This makes my messages and form-errors disappear, since these are only shown at the first request after a post and not at the second request...

So my current goal will be to inject the mercury editor into the DOM, without doing a new request for the iframe.

the orignal body/page should be moved to the iFrame...

lvanderree commented 13 years ago

Isn't it maybe an idea to load mercury in a dynamically injected iFrame, instead of reloading the content in the injected iFrame.

This way you don't have to reload the page, and don't have to manipulate all links/forms to set their target to _top

jejacks0n commented 13 years ago

Cool.. you're welcome to give it a shot. I know there's a fork that balupton made where he tried to do this, so you should definitely check that out.

I wrote mercury for a specific use case, and don't plan on making it support some of these things because it makes it much more complex, and has several drawbacks. I could go into all of the issues that begin to crop up, but I'll just outline the top two reasons why I didn't do this, and why I don't plan to. There's a previous conversation about this as well, so you may want to reference that one.

There's always pollution of some kind -- css, or javascript libraries. Mercury has none of those issues currently, but if it were in the same DOM it would. Currently mercury can be placed on a page using Prototype, jQuery, Ext, etc.. This has a lot of value, and you likely don't think about it because you don't have any issues with it (because of the way it was written). But you would have to face all of that type of support. I namespaced everything in mercury (both css and js), but it doesn't make it much simpler to do.

There's many selection issues that arise when you try to put this all on one page .. any input (as well as links etc) will take focus away from the contentEditable regions, so you have to reselect whatever was previously selected -- for instance when you open a modal and enter information, the selection has to be stored and re-selected. I wasn't happy with this in previous incarnations of mercury, so I dropped it. It keeps everything a lot simpler and cleaner.

With that being explained, you're welcome to give it a shot if you'd like, I'll do what I can to help support it if you decide it's worth it.

But to answer your original question.. I'd have to say I think you're using it somewhat inappropriately if I'm rightly picturing what you're describing. Mercury was really written as a tool for editing content on whatever page you're actually viewing, so if you're trying to wedge it into an admin interface I can't say that's what it's intended for. For it to be true WYSIWYG functionality, you have to have all the css and structure loaded to display things properly, and to provide an accurate picture of what things will look like when saved. Yes, you may want to let admins enter html in inputs in an admin form, but that's not really what mercury excels at. I would encourage you to investigate some of my suggested alternatives (in the readme) for that sort of functionality. What I've done in the past that's worked great, is to provide support for markdown in my admin forms, which you can do very simply, or you could use something like http://markitup.jaysalvat.com/home/ -- which I've leaned towards recently.

I also intend to build a textarea replacement version of mercury, which does more of what you're looking for. But I can't commit to a timeline on that, but I expect it would be more of what you're looking for.

lvanderree commented 13 years ago

Hi Jeremy.

I understand that i tried to get more out of Mercury, than that it was currently designed for. However I also think that it is not impossible what I (and balupton) try to do. There obviously are some changed required to accomplish this, but as long as you are open for these changes, like you say, I think this will work out great!

Regarding the iframe, I think there 3 options:

  1. do like you do, put the content into an iframe 1a. reload the page in this iframe, but this time without merucry of course
    • This wil trigger a second get to the server 1b. move the body from the _top to the iframe.
    • All JavaScript functionality has to be moved to this iFrame as well. No idea how to do this transparently yet
  2. load Merucry in an (fixed positioned) iframe (or two iframes (top/bottom))
    • Need to find a way to insert these iframes, pushing the (absolute and fixed positioned) content away
  3. don't use iframes at all. This will probably result in something like Aloha. using a (floating) div on top of the content

I think I would prefer 1b of 3. I don't know if 1b is possible (without adding to much complexity), and with 3 I probably will see some completely new problems, I haven't thought of yet.

I need some more time to work this out though, and for now i think that your approach of integrating to text-editors (one for admin, one for on-site), with the same server-sided validation/cleaning should be good enough for now. For now I think I will re-introduce TinyMCE in the admin, but I am looking forward to see your mercury-textarea implementation one day.

Again many thanks for your response and thinking along.