CKEditor script does not work on heavy HTML page - ruby-on-rails

I am trying to use the CKEditor gem with Rails 4.0.3. I have setup everything according to the docs, but it does not work.
I have a main project with a page which contains many html elements. In this page CKEditor does not work, and does not give any errors or warnings, neither on server side nor on client side (Javascript).
But when I created a test project, and applied the same settings, it worked!
After a lot of struggling, I finally came to this conclusion:
CKEditor inserts a bit of Javascript after the textarea which is supposed to converted. Here is the code:
//<![CDATA[
if (typeof CKEDITOR != 'undefined') { CKEDITOR.replace('article_body'); }
//]]>
I think the problem is that, on the page with many html elements, the code above is run before the DOM is completey loaded, so it has no effect. But on the other page the DOM loads quickly and the code is run in time.
One thing that validates my assumption is that if I run the Javascript code above in the Chrome Developer tools' console, when the page has been completely loaded, it does work.
I don't know if I am right or not, but supposing I am right, how can I force the code above to run when the DOM is fully loaded?

I found the problem. It is because I moved the
<%= stylesheet_link_tag "application" %>
line to the end of the file, before the closing body tag. This line:
//<![CDATA[
if (typeof CKEDITOR != 'undefined') { CKEDITOR.replace('article_body'); }
//]]>
was executed before any other Javascript files were loaded, so it did nothing.
And the solution:
One way is to move the stylesheet_link_tag line to top of the file (which I don't like).
Another way is to add a CSS class named ckeditor to the textarea which you want to be converted. For example:
= form_for #article do |f|
= f.text_area :body, class: "ckeditor"
This will tell CKEditor to convert that textarea to a WYSIWYG editor.

Related

Capybara prevents attaching onsubmit event to form

In my rails app I attach onsubmit event to my form using jquery like this:
$("form.my_form").submit(function(){
alert("test")
return true;
});
This is working fine when I manually open the page and submit the form (clicking on the submit button) - I see the alert "test"
BUT I have a Capybara test (over Selenium) that loads the page, fills in some values in the form, and then clicks on submit.
And the function is NOT triggered.
Note 1: when running the test the form is indeed submitted, new values recorded in the DB etc. so there is no problem with clicking on the submit button itself
Note 2: if instead of jquery, in the rails view in the form_for tag I put
html: {onsubmit: "onsubmitfunc();"}
with the alert in the onsubmitfunc() - everything works as expected in the capybara test
Note 3: in order for the jquery way to work the js file is defer loaded e.g.:
<%= javascript_include_tag 'application', defer: true %>
I am very new to JQuery, so am I doing something criminal there?
Or Capybara has some problem? with defer loading of the JS file? Or with JQuery? Any ideas?
Since you're using Selenium - the most common reason would be that you have an error in one of your JS assets. When in the dev environment all your JS assets are served in separate files which means an error in one file doesn't stop others from being processed. In the test environment (and production) the assets are concatenated into one file which means an error in any file can cause assets concatenated after it to not be processed.
Check the browsers console log for any JS errors and fix them.

Should the javascript_include_tag always load last?

Railscast#369 explains how moving the javascript_include tag to the bottom of application.html.erb can shorten loading time, as it allows the page to load at the same time as the javascript.
From the simple example given, it seems like the javascript tag should ALWAYS be at the bottom of the page. However, the fact that the Rails default has it at the top implies (to me at least), that this may not always be true.
When would someone NOT move the javascript tag to the bottom of application.html.erb?
If you call any javascript prior to it loading then you may run into issues. As an example in a view (blah.html.erb) file you might have:
<script>
jquery('#element_id').append("<p>Error Message</p>");
</script>
Which would look for jQuery being loaded by the include tag. Not a good practice but sometimes occurs.
Also, you may use a js view file (blah.js.erb) which would look for jQuery before it is loaded as well.

Rails 4 + Turbolinks: JS in the head or at the bottom of the body?

I'm used to sticking my JS at the bottom of my body element (as per HTML5Boilerplate), but since TurboLinks, which will be on by default in Rails 4, reloads the body (and title) on every request, would it make sense to put my JS in the head from now on? Are there any decent guides or best practices on this yet?
If you're using Turbolinks 5, you can now put turbolinks at the bottom of your body (and follow web dev best practices for rendering a page). This also helps with SEO ever so slightly. Simply add your scripts to the bottom of your body and add
data-turbolinks-eval="false"
to your script tag. This will prevent turbolinks from evaluating after the initial page load. Here's how it is done with the javascript_include_tag:
<%= javascript_include_tag 'application', 'data-turbolinks-eval' => 'false'%>
Then just use
$(document).on('turbolinks:load', function() {
// code to be executed when use changes pages
});
Also precompiled application.js (as per the assets pipeline) is on and in head by default. The reasoning is that even if the js is loaded before the rest of the page, as the js is always the same it will be loaded from cache from the second request onwards, so there is no actual reason to serve it at the bottom of the body anymore.

No pics in my PDF created with PdfKit on heroku

I've an app which works fine in development and on my current production server.
I want to move it to FREE heroku (basic config: 1 dyno, 1 worker).
Unfortunately, the pdf generation (using PdfKit) is ok BUT without the pictures defined in my CSS.
I've followed a lot of tips including:
http://blog.mattgornick.com/using-pdfkit-on-heroku
http://jguimont.com/post/2627758108/pdfkit-and-its-middleware-on-heroku
http://code-fu.pl/blog/2011/05/17/pdfkit-heroku
Thoughts?
Found a workaround but I am still eager to know a better option:
I duplicated my view: one dedicated for html, another for pdf.
I removed all css using pics and put it in a separate file, included only in the view dedicated for html
finally, I inserted the css in the view dedicated to the pdf:
.foo { background-image:url(<%= Rails.root %>/public/images/bar.png) }
Very Ugly but works so please tell me if you've better
It's probably an issue with the way the url's are specified in the css. As I recall, they should be file system absolute paths. What does your css look like?
Here is how I answered my needs with:
Just one single view file
Just one css file
The trick was to pass the proper base_url to the css file dynamically, given I expected a pdf or html.
I decided to use LESS. Style compiles css in a different manner, given the base-url I provide in the DOM. This base-url is generated by a helper.
Here were my steps:
changed my style.css to style.less
Added to my view:
<%= stylesheet_link_tag "style.less", :rel => "stylesheet/less" %>
<script id="base_url" type="text/javascript" data="<%= assets_path %>"></script>
<%= javascript_include_tag "less.min.js" %>
In my helper:
def assets_path
if request.fullpath.include? ".pdf"
"#{Rails.root.join('public',"images","pictos")}"
else
"#{request.protocol}#{request.host_with_port}/images/pictos"
end
end
and in my style.less:
#base_url: `document.getElementById('base_url').getAttribute('data')`;
.foo { background-image:~"url(#{base_url}/bar.png)" }

How do I create dynamic CSS in Rails?

what is the best/most efficient way of creating dynamic CSS with Rails. I am developing an admin area on a site, where I would like a user to be able to customize the style of their profiles(Colour mostly), which will also be saved.
Would you just embed ruby script in the css file?
Would you need to change the file extension from css?
Thanks.
In Rails 3.1, you can have your stylesheets pre-processed by erb.
Now let's say you have some dynamic styling called dynamic.css.scss.erb (the .erb at the end is important!) in app/assets/stylesheets. It will be processed by erb (and then by Sass), and as such can contain stuff like
.some_container {
<% favorite_tags do |tag, color| %>
.tag.<%= tag %=> {
background-color: #<%= color %>;
}
<% end %>
}
You can include it like any stylesheet.
How dynamic should it be?
Note that it will be only processed once, though, so if the values changes, the stylesheet won't.
I don't think there is a super efficient way to do have it completely dynamic yet, but it is still possible to generate the CSS for all requests. With this caveat in mind, here's a helper for that in Rails 3.1:
def style_tag(stylesheet)
asset = YourApplication::Application.assets[stylesheet]
clone = asset.class.new(asset.environment, asset.logical_path, asset.pathname, {})
content_tag("STYLE", clone.body.html_safe, type:"text/css")
end
Here's how to use it:
First, copy the above helper in app/helpers/application_helper.rb.
You can then include it in your page as follows:
<% content_for :head do %>
<%= style_tag "dynamic.css" %>
<% end %>
The rest of your page.
Make sure that your layout uses the content :head. For example, your layout/application.html.erb could look like:
...
<HEAD>
....
<%= yield :head %>
</HEAD>
...
I found this out thanks to this post.
You can use ERB with CSS, you just need to render css in the controller. However, for such a heavily requested resource, I do not recommend generating this every time. I would store the users stylesheet in memcached or redis, and recall from it when the page loads, rather than rerendering the file each time. When they update their style, you can expire the cache, just make sure it gets rebuilt when the page renders.
There has been a lot of development over the years, and I recently figured out how to do what this question is asking. And since it has been about 9-10 years since someone has answered this, I thought that I would put in my 2 cents.
As others have said, it is not good practice, and thus can not be done, to put ruby code directly into the CSS file as the CSS is precompiled and is not able to be dynamically changed within the file.... BUT, it can be dynamically changed outside the file!
I will need to give a quick synopsis of CSS variables in case future readers do not know how to use them.
CSS has the use of variables within its coding language to make it easier to change a lot of elements at one time. You put these variables at the top of the CSS file in a root section. Like this:
:root {
--primary: #0061f2;
--secondary: #6900c7;
}
Now, anytime you want to style an element one of those colors, you can simply put var(--variableName) like this:
.btn{
color: var(--secondary);
background-color: var(--primary);
}
.h1 {
color: var(--primary);
}
You can see how it would then be much easier to change the variable in the root section and thus change all other instances within the CSS.
Now for the dynamic Ruby part.
In the <head> section of your application file (or in the case of this question the file that holds the template for the admin's dashboard), you will need to redeclare the CSS variables with your dynamic variables and mark them as important. For example, let's say that you allow your user to choose primary and secondary colors for their dashboard and they are stored in the user's profile called like: user.primary_color and user.secondary_color. You will need to add this to your <head> section:
<style>
:root{
--primary: <%= user.primary_color %> !important;
--secondary: <%= user.secondary_color %> !important;
}
</style>
This !important tag will override the variables found in the CSS file thus dynamically allowing the user to change the CSS and view of their dashboard and have it remain persistent (as the values are saved in their profile).
I hope that this helps future developers.
Happy Coding!
Currently there is a lot of options to generate dynamic css in rails.
You can use less css - is an extension to CSS with extra features.
Gem Less css for rails provides integration for Rails projects using the Less stylesheet language in the asset pipeline.
If you are using twitter bootstrap you may check this out less rails bootstrap.
Also you can use one more CSS extension language Sass for generating CSS. Here is a Saas rails gem.
Check out Dynamic CSS in Rails and Render Rails assets to string blog posts and article about Asset Pipeline
Related SO questions:
Best way to handle dynamic css in a rails app
Dynamic CSS in Rails asset pipeline, compile on fly
Rails: change CSS property dynamically?
I just built this for another site. I have a controller action and a view that pulls color values out of the database, then renders a customized CSS based on the current user's account. To optimize, I am using the built in Rails page caching, which stores a copy on disk and serves it as a static asset. Nice and fast.
Here's an example from the ERB code
#header { background: <%= #colors["Header Stripe Background"] %>; border: 1px solid <%= #colors["Header Stripe Border"] %>; }
#header h1 {color: <%= #colors["Headline Color"] %>; }
#header p a { background: <%= #colors["Control Link Background"] %>; color: <%= #colors["Control Links"] %>;}
#header p a:hover {background: <%= #colors["Control Link Hover"] %>; text-decoration:underline;}
This solution defines some constants in config/site_settings.rb, which can then be used throughout the Rails application, as well as for automatically generating the CSS files whenever the Rails app starts and the CSS input files have been modified..
http://unixgods.org/~tilo/Ruby/Using_Variables_in_CSS_Files_with_Ruby_on_Rails.html

Resources