How to namespace coffeescript in a Rails project - ruby-on-rails-3

In my Rails project, in which I am using Coffeescript, I want to be able to do something like this in a view:
f.text_area :content, :size => "77x4", :oninput => 'Helpers.expandTextarea(300)'
This would call a coffeescript function that would expand the textarea when required. My problem is that I can't seem to properly namespace the coffeescript to get this to work. I tried to do it like this
# site.js.coffee
Helpers =
expandTextarea: ->
alert "function found!"
This doesn't work. Trying to call Helpers in the browser console will throw an undefined error. My question is this:
What code would I use in site.js.coffee to achieve the namespacing I want?

You could manually put Helpers into the global namespace:
window.Helpers =
expandTextarea: ->
alert "function found!"
Then you should be able to say Helpers.expandTextarea(300) anywhere you want. Assuming, of course, that site.js.coffee is included on every page.
CoffeeScript files are wrapped in functions by default:
(function() { /* compiled CoffeeScript goes here */ })();
to avoid polluting the global namespace. You can supply options to the CoffeeScript compiler to not wrap like this but you're better off explicitly putting global things into window.

Related

Multiple Aurelia Instances - Aurelia Webpack Plugin - aureliaApp option - "module not found"

I am composing my web app as a number of Aurelia "feature" apps - although I'm not using Aurelia features as such. Consequently in my html markup I have two entry points pointing to different apps:
<!-- Top Navigation Bar -->
<div aurelia-app="topnav"></div>
<!-- Main App-->
<div aurelia-app="main"></div>
I am using webpack and everything works perfectly using the single "main" app. Webpack generates a JS file "main.bundle.js" which I include in the src tag.
Things are not so straightforward when I added the "topnav" app. In webpack I tell the plugin to use a different aureliaApp name:
new AureliaPlugin({ aureliaApp: "topnav"}),
and, as you can see my HTML entrypoint also calls "topnav". Webpack generates a JS file "topnav.bundle.js" which I also include. I have a file called "topnav.ts" which contains the aurelia Cionfigure function which ends:
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName("nav")));
And a pair of files "nav.ts", "nav.html" which constitute my viewmodel and view.
When I run the app aurelia loads and the "nav" module code executes. But I then get an error - see below.
The module which it reports that it cannot find is the one entered into the HTML markup.
Should this work? Have I missed something?
I should add, everything seems to work. I can create and update properties in the viewmodel and these are bound to the view. It's just that this error is thrown.
You are doing nothing wrong, just unsupported scenario. Per official doc-wiki: https://github.com/aurelia/webpack-plugin/wiki/AureliaPlugin-options#aureliaapp
You can have only 1 auto entry module with aureliaApp configuration. To solve this, you just need to add PLATFORM.moduleName('topnav') to your main.ts (and put it on root level)
Another way to do is to bootstrap manually:
// in your index.ts
import { bootstrap } from 'aurelia-bootstrapper';
// bootstrap top nav application, with one instance of Aurelia
bootstrap(aurelia => {
// do your configuration
aurelia
.start()
.then(() => aurelia.setRoot(
PLATFORM.moduleName('topnav'),
document.querySelector('#topnav')
);
});
// bootstrap main application, with another instance of Aurelia
bootstrap(aurelia => {
// aurelia.use.standardConfiguration();
// ...
aurelia
.start()
.then(() => aurelia.setRoot(
PLATFORM.moduleName('app'),
document.querySelector('app')
)
});

is this the correct declarative, data-dojo-type syntax to require a package?

I have a package, defined in dojoConfig like this:
packages: [
{ name: 'Widget', location: '/widgets/Widget' }
]
The /widgets/Widget/main.js file defines my main module. With this config, in Javascript i can require the module Widget/main directly by its package name like this:
require(["Widget"], function(Widget){
var widget = new Widget();
// all is well
});
But doing the same using declarative syntax throws a Unable to resolve constructor for: 'Widget' error:
<div data-dojo-type="Widget"></div>
Am I doing something wrong, or is this expected behaviour?
It would be easier to see how widget is created, but the complaint is that you have no constructor.
a constructor is required for a widget. If you extend WidgetBase its done for you.
check the doc:
http://dojotoolkit.org/reference-guide/1.9/quickstart/writingWidgets.html
You need to add the
require(["Widget"], function(Widget){});
part in a script tag in the HTML document you are using
<div data-dojo-type="Widget"></div>
It should look like something:
<script> require(["Widget"], function(Widget){}); </script>
You have to require the module/widget before you can call it in an HTML page the same way you need to do it in a script tag.

rails 3.x pageless callback method

I am working on integrating jquery pageless plugin with a rails application. The pageless plugin works seamlessly when i write out the javascript. The issue lies in trying to have a javascript method issued upon complete. What i am trying to accomplish is having a helper method to generate it, but it renders the javascript with quotes around my callback method which then generates an error in the javascript
Uncaught TypeError: Object reloadMasonry has no method 'call'
here is the helper method code
def pageless(total_pages, url=nil, container=nil) opts = {
:totalPages => total_pages,
:url => url,
:loaderMsg => 'Loading more results',
:loaderImage => image_path("load.gif"),
:complete => "reloadMasonry"
}
container && opts[:container] ||= container
javascript_tag("$('#masonry-container').pageless(#{opts.to_json});")
end
This is the produced javascript code
<script type="text/javascript">
//<![CDATA[
$('#masonry-container').pageless({"totalPages":3,
"url":"/articles",
"loaderMsg":"Loading more results",
"loaderImage":"/assets/load.gif",
"complete":"reloadMasonry"});
//]]>
</script>
the javascript results in having quotes around the reloadMasonry callback function
reloadMasonry = function(){
$('#masonry-container').masonry('reload');
}
if i copy the exact javascript produced, and simply remove the double quotes around the javascript callback method ( reloadMasonry ) in this case, everything works seamlessly.
does anyone have any suggestions.

rendering a partial Rails3.x + coffeescript

I have the following requirement. I have a 'school' drop down and as the last options I have add new school, so if the user selects that option I want to load the new_school form as a partial via ajax.
I'm on
gem 'rails', '3.2.9'
gem 'coffee-rails', '~> 3.2.1'
Jquery via gem 'jquery-rails'
Earlier with rails < 3 and prototype I used to do it with
Ajax.Updater (aka Rails link_to_remote :update => 'some_div')
and with rails > 3 + JQuery I'm familiar with *.js.erb, and having something like
$("#school_form").html("<%= escape_javascript(render(:partial => "form"))%>");
But I'm new to coffeescript and I have no idea on how to do this with coffeescript, can someone help me :), (because I believe you shouldn't have to do a server request for this)
So far I have done following to catch the select_tag change event
$ ->
$('#school_name_select').change ->
unless $(this).val()
$('school_name').html([I want to have the _new_school_form partial here])
Use a hidden div.
In general, you don't want to bother trying to mix JS and HTML. The escaping can be complicated, error-prone, and flat out dangerous due to the possibility of cross-site scripting attacks.
Simply render your form partial in a div that's not displayed by default. In ERB:
<div id="school_name_form" style="display: none;">
<%= render 'form' %>
</div>
In your CoffeeScript:
$ ->
$('#school_name_select').change ->
if $(this).val()
$('#school_name_form').slideUp()
else
$('#school_name_form').slideDown()
I recommend using a small, tasteful transition like slide or fade. It gives your app a more polished feel.
No AJAX is required. This pattern is so common that I have an application-wide style defined as follows.
.not-displayed {
display: none;
}
Then using HAML (if you're into that), the HTML template becomes simply:
#school_name_form.not-displayed
= render 'form'
You can try to render the form partial inside hidden div (not too correct from semantic point of view), or put the form html as data attribute of any relevant element, something like
f.select school_name, ... , data: {form: escape_javascript(render(:partial => "form"))}
And the Coffeescript
$ ->
$('#school_name_select').change ->
unless $(this).val()
$('school_name').html($('#school_name_select').data('form'))

Rails 3: how to render text file in-line?

All.
A Rails n00b here...
I'm writing an application that reports the status of a transaction.
Some of the content in the rendered HTML comes from instance variables
initialized in the controller, while other content comes from text files
(e.g., log files) that I want to render in the HTML using <pre> tags.
What is the "Rails Way" to do this?
Thank you for your time...
<pre>
<%= render :file => '/tmp/test.log' %>
</pre>
Here you go: http://edgeguides.rubyonrails.org/layouts_and_rendering.html
In some cases (when the file is not small and loading it is connected with a delay), I prefer to load the page content and then to use jQuery ajax request to load the file content.
For example, let's say I have a model with file path attribute. In the view layout I am doing something like this:
<pre data-source=" <%= (#file.path) %>"></pre>
Then in the corresponding js file I am loading the context like this:
$(document).ready ->
$.ajax(
url: $("pre").data("source")
context: document.body
).done (response) ->
$("pre").html response
return
return
Of course you can check the jQuery ajax documentation for more options. For example, you can render the pre tag with loading like this:
<pre data-source=" <%= (#file.path) %>"><div class="loading"></pre>
or use other jQuery animations as well.