lunes, 28 de abril de 2014

A road to HTML Mails in Rails

 If you need your Rails 4 application to send html emails, then perhaps this post can help you.
 Here there is a very good page about the topic.
 As you can see in the page, the email clients will strip the css classes out. So you should use inline styles.
 I followed the next steps:
 - I put the html email layout (with inline styles) in app/views/layouts
  <body style="your-style">
    <table>
      <tr>
        <td style="your-style">
          <p><%= yield(:email_content) %></p>
        </td>
      </tr>
     </table>
  </body>
 - For each mailer view file .text.erb write a corresponding file .html.erb in the same folder and with the same name, with the following code
<% content_for :email_content do %>
  <p>Text</p>
  <p>message</p>
<% end %>
 - In the application, you probably will have several mailer classes in the folder mailer. Mailers work very similarly to controllers. In my case these classes inherit from the class ApplicationMailer, so I wrote in this class:
layout 'layouts/email'
 - If you are using devise you need to configure it to use the layout. Write inside the class Application in config/application.rb:
config.to_prepare do
 Devise::Mailer.layout "layouts/email"
end
 - If you are testing your application with rspec and have code like the following:
expect(inbox_for(email_account)).to include_email(subject: 'Text Subject', body_text: /Text message/)
 After the change, the test won't work because now the email isn't plain text any more. Now is a multipart email. So you could write:
last_email = inbox_for(email_account).last
expect(last_email.subject.to_s).to match('Text Subject')
expect(last_email.text_part.body.raw_source.to_s).to match(/Text message/)
expect(last_email.html_part.body.raw_source.to_s).to match(/Text</p>\n\n  <p>message/)
 Instead of use inline styles you could use gems as premailer or roadie. I didn't use them because I only have an html.
 I hope that this information helped you. I am sure that you have better ideas to implement this, so share it with us!

viernes, 24 de enero de 2014

Mysterious scroll

Today I'd like to speak about a problem that we had with CSSModal and Autofocus.

What do we use in our application?
 - Rails
 - For modal windows CSS Modal. For example, we have at the top of the index page a link for login. When we click this link, a modal with a form for the login is opened.

 The problem showed up when we used the autofocus attribute in our forms. The result was that when we opened the index page, it was scrolled to the middle of the page, without clicking the login link.

 I didn't know that the autofocus could cause this behaviour, so I created a JS to test what it was happening:

console.log(document.activeElement);
console.log($(window));
console.log('$(window).scrollTop() ' + $(window).scrollTop());
console.log('$(window).height() '+ $(window).height());
console.log('$(document).height() ' + $(document).height());
console.log('window.pageYOffset ' + window.pageYOffset);
console.log('document.body.scrollTop ' + document.body.scrollTop);

I saw that the activeElement was always the first field of the login form. How could it be? I didn't click the login link.

Thilo, told me that perhaps the autofocus of the login form was changing the pageYOffset. He removed the link and tested that the page worked properly.

So, I removed the autofocus in the modal forms and the pages worked.

But I needed the focus in the first field of each form!!!

How did we resolve? With JS.

In the input or text fields of our forms with the needed autofocus, we used a html class called "should_have_focus"

Then, in a js file:

$(document).on('cssmodal:show', function () { 
     $('.is-active') 
          .find('input.should_have_focus, textarea.should_have_focus')
          .focus();
});

When the modal is active, the focus is transferred to the input or textarea field with the html class "should_have_focus"

And that's all!!