Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get Mercury Editor to redirect to a new resource?

After watching RailsCast #296 about Mercury Editor, I am trying to get the editor to redirect to a newly created resource.

I can already redirect on the client-side using JS and window.location.href=. But for a new resource, I cannot "guess" its URL on the client-side. I need it to be in the server response.

However, the problem is that I don't see the possibility of using the server response in the editor. No matter what the controller renders, the server response is discarded by Mercury instead of used as an argument to my function for mercury:saved.

Is there a way to get around this?

like image 683
awendt Avatar asked Jul 17 '12 15:07

awendt


2 Answers

I was able to do this on update by sending a valid JSON string back. I would assume create works the same way. check firebug to make sure you're not getting an error in the jQuery.ajax call that Mercury uses.

posts_controller.rb

def mercury_update
  post = Post.find(params[:id])
  post.title = params[:content][:post_title][:value]
  post.body = params[:content][:post_body][:value]
  post.save!
  render text: '{"url":"'+ post_path(post.slug) +'"}'
end

mercury.js:

  jQuery(window).on('mercury:ready', function() {
    Mercury.on('saved', function() {
       window.location.href = arguments[1].url      
    });
  });

note: I'm using friendly_id to slug my posts

like image 199
corneliusk Avatar answered Sep 26 '22 09:09

corneliusk


Redirecting on the server side doesn't work because the save button is just an jQuery.ajax call:

// page_editor.js
PageEditor.prototype.save = function(callback) {
      var data, method, options, url, _ref, _ref1,
        _this = this;
      url = (_ref = (_ref1 = this.saveUrl) != null ? _ref1 : Mercury.saveUrl) != null ? _ref : this.iframeSrc();
      data = this.serialize();
      data = {
        content: data
      };
      if (this.options.saveMethod === 'POST') {
        method = 'POST';
      } else {
        method = 'PUT';
        data['_method'] = method;
      }
      Mercury.log('saving', data);
      options = {
        headers: Mercury.ajaxHeaders(),
        type: method,
        dataType: this.options.saveDataType,
        data: data,
        success: function(response) {
          Mercury.changes = false;
          Mercury.trigger('saved', response);
          if (typeof callback === 'function') {
            return callback();
          }
        },
        error: function(response) {
          Mercury.trigger('save_failed', response);
          return Mercury.notify('Mercury was unable to save to the url: %s', url);
        }
      };
      if (this.options.saveStyle !== 'form') {
        options['data'] = jQuery.toJSON(data);
        options['contentType'] = 'application/json';
      }
      return jQuery.ajax(url, options);
    };

So your redirect is sent to the success callback, but the page doesn't actually re-render, as with any successful AJAX request. The author discusses overriding this very function here. It also looks like there might be some room to maneuver here by passing a callback function to save.

Btw, another way to do what @corneliusk suggests is:

render { json: {url: post_path(post.slug)} }

Either way, the response body is passed as an argument to the function in the mercury:saved callback.

like image 33
jordanpg Avatar answered Sep 22 '22 09:09

jordanpg