uncaught exception: Template undefined not found, ReferenceError: Backbone is not defined - ruby-on-rails

I am trying to follow along with this series:
http://www.backbonerails.com/series/engineering_single_page_apps
I am on episode 5, at around the 48 min mark. When I refresh the page in my browser, I get this in the firebug console:
uncaught exception: Template undefined not found
I tried running my code at http://coffescript.org, and I get this error:
ReferenceError: Backbone is not defined
I'm not sure, but I'm guessing the above error is just occurring because the coffescript.org console doesn't know what Backbone is.
Here is the relevant code:
show_controller.js.coffee
#Demo.module "FooterApp.Show", (Show, App, Backbone, Marionette, $, _) ->
Show.Controller =
showFooter: ->
console.log "footer"
footerView = #getFooterView()
App.footerRegion.show footerView
getFooterView: ->
new Show.Footer
With the above code, I notice in the console that "footer" is not appearing as it should. So maybe something is wrong with the controller? Or something within the "showFooter" method.
list_controller.js.coffee
#Demo.module "HeaderApp.List", (List, App, Backbone, Marionette, $, _) ->
List.Controller =
listHeader: ->
console.log "header"
headerView = #getHeaderView()
App.headerRegion.show headerView
getHeaderView: ->
new List.Header
With the above code, I DO NOTICE that "header" is appearing in the console, so it seems everything is alright with the HeaderApp.
show_view.js.coffee
#Demo.module "FooterApp.Show", (Show, App, Backbone, Marionette, $, _) ->
class Show.Footer extends Marionette.ItemView
template: "footer/show/templates/show_footer"
list_view.js.coffee
#Demo.module "HeaderApp.List", (List, App, Backbone, Marionette, $, _) ->
class List.Header extends Marionette.ItemView
template: "header/list/templates/list_header"
header_app.js.coffee
#Demo.module "HeaderApp", (HeaderApp, App, Backbone, Marionette, $, _) ->
#startWithParent = false
API =
listHeader: ->
HeaderApp.List.Controller.listHeader()
HeaderApp.on "start", ->
API.listHeader()
footer_app.js.coffee
#Demo.module "FooterApp", (FooterApp, App, Backbone, Marionette, $, _) ->
#startWithParent = false
API =
showFooter: ->
FooterApp.Show.Controller.showFooter()
FooterApp.on "start", ->
API.showFooter()
renderer.js.coffee
#Demo.module "FooterApp", (FooterApp, App, Backbone, Marionette, $, _) ->
#startWithParent = false
API =
showFooter: ->
FooterApp.Show.Controller.showFooter()
FooterApp.on "start", ->
API.showFooter()
app.js.coffee
console.log #
#Demo = do (Backbone, Marionette) ->
App = new Marionette.Application
App.addRegions
headerRegion: "#header-region"
mainRegion: "#main-region"
footerRegion: "#footer-region"
App.addInitializer ->
App.module("HeaderApp").start()
App.module("FooterApp").start()
App.on "initialize:after", ->
if Backbone.history
Backbone.history.start()
App
application.js
//= require jquery
//= require lib/underscore
//= require lib/backbone
//= require lib/marionette
//= require_tree ./backbone/config
//= require backbone/app
//= require_tree ./backbone/apps
application.css
#import "twitter/bootstrap";
#import "apps/base";
#import "apps/header";
#import "apps/footer";
Here is the directory structure:
app
assets
javascripts
backbone
apps
footer
show
templates
show_footer.jst.eco
show_controller.js.coffee
show_view.js.coffee
footer_app.js.coffee
header
list
templates
list_header.jst.eco
list_controller.js.coffee
list_view.js.coffee
header.app.js.coffee
config
marionette
renderer.js.coffee
app.js.coffee
application.js
stylesheets
application.css
I'm wondering if all my path stuff is declared correctly based on my directory structure.
Thanks for any help, I'll be awaiting a response eagerly.

Check the following:
The template paths are correct
You've properly overridden the he renderer in renderer.js.coffee and it's getting loaded properly in the HTML (i.e. you can see the code when you view the page's source)
If that looks correct, try comparing your code to the source code provided with the screencast.

Related

Uncaught TypeError: this.template is not a function Backbonejs

I am working in Rails with BackboneJS in handlebar templates.
I am getting a weird error here..
this is my header view
class App.Views.Header extends Backbone.View
className: "navbar-inner"
template: HandlebarsTemplates['app/templates/header']
render: ->
#$el.html(#template())
#
main application file is this
#= require_self
#= require_tree ./templates
#= require_tree ./views
#= require_tree ./routers
window.App =
Routers: {}
Views: {}
Collections: {}
Models: {}
initialize: ->
new App.Routers.MainRouter()
Backbone.history.start()
and my main router file is this
class App.Routers.MainRouter extends Backbone.Router
routes:
"": "index"
initialize: ->
#headerView = new App.Views.Header()
index: ->
$("#header").html(#headerView.render().el)
when I hit localhost:3000.. I got this error upfront.
Uncaught TypeError: this.template is not a function..
Am totally stuck in that any help will be appreciated Thanks
template: HandlebarsTemplates['header']
Template path should be only the template itself.
May that is version due to version or assets precompiled
It sounds like the Handlebars template in HandlebarsTemplates['app/templates/header'] either does not exist, has not been compiled, or there may have been an error while compiling it. That's the error you'd get if that value was null or undefined.
You might want to try setting a breakpoint in your browser's javascript debugger in the call to render, then use the debugger to check the value of this.template and see what's going on.

ActiveAdmin Select2 not working

I am using ActiveAdmin 1.0 (current master updated today). And have migrated from Chosen to Select2. I followed the directions at https://github.com/mfairburn/activeadmin-select2 but am noticing issues. If I navigate pages on the site, the css doesn't seem to be working. However if I am on a page and select the refresh button, the Select2 css shows up.
active_admin.js.coffee
#= require active_admin/base
#= require chosen-jquery
#= require_tree ./active_admin
#= require_tree .
#= require active_admin/select2
active_admin.css.scss
// SASS variable overrides must be declared before loading up Active Admin's styles.
//
// To view the variables that Active Admin provides, take a look at
// `app/assets/stylesheets/active_admin/mixins/_variables.css.scss` in the
// Active Admin source.
//
// For example, to change the sidebar width:
// $sidebar-width: 242px;
// Active Admin's got SASS!
#import "active_admin/mixins";
#import "active_admin/base";
//#import "chosen";
//#import "active_admin/chosen";
//body.active_admin {
#import "active_admin/select2/base";
//}
// Overriding any non-variable SASS must be done after the fact.
// For example, to change the default status-tag color:
//
// .status_tag { background: #6090DB; }
Any ideas why I have to refresh every page for the css to load? I have cleared cache and precompiled assets.
Sounds like this isn't a CSS issue, but an issue with your JS initialization and turbolinks. The problem lies on this line of code: https://github.com/mfairburn/activeadmin-select2/blob/master/app/assets/javascripts/active_admin/select2/select2.js.coffee#L15 which isn't compatible with Turbolinks, as the document.ready event isn't called when making page transitions - you can read about Turbolink's event lifecycle here: https://github.com/rails/turbolinks#events
My suggestion would be to probably override the file I linked to above by creating a assets/javascripts/active_admin/select2/select.coffee in your own app tree containing this code:
'use strict';
initSelect2 = (inputs, extra = {}) ->
inputs.each ->
item = $(this)
# reading from data allows <input data-select2='{"tags": ['some']}'> to be passed to select2
options = $.extend(allowClear: true, extra, item.data('select2'))
# because select2 reads from input.data to check if it is select2 already
item.data('select2', null)
item.select2(options)
$(document).on 'has_many_add:after', '.has_many_container', (e, fieldset) ->
initSelect2(fieldset.find('.select2-input'))
$(document).on 'ready page:load', ->
initSelect2($(".select2-input"), placeholder: "")
return
(notice the use of Turbolink's page:load event)

WebSharper JQuery Mobile Page Hidden

I'm trying to put together a JQuery Mobile site using the F# WebSharper Framework. In WebSharper parlance I have created a Pagelet using JQueryMObile controls which is being served by a Sitelet. Everything compiles and runs, the problem is in the html that is generated.
The page I have declared (simplePage) clearly exists in the markup and is marked with the JQueryMobile css class ui-active to make it visible. However, it is surrounded by a div that is also a page but is not marked with the active css class, making it invisible. Therefore my page inside this div is hidden. I am not creating this containing page div. It seems to be a side-affect of loading the JQueryMobile script in the html head. How can I get rid of it?
I have taken the example from http://websharper.com/samples/JQueryMobile. I am using WebSharper version 2.5.125.62 and WebSharper.JQueryMobile version 2.5.4.198. I have one relevant code file shown below followed by the generated html.
Main:
open IntelliFactory.Html
open IntelliFactory.WebSharper
open IntelliFactory.WebSharper.Html
open IntelliFactory.WebSharper.JQuery
open IntelliFactory.WebSharper.Sitelets
type Action = | Home
[<JavaScript>]
module MyJQueryContent =
let Main() =
JQuery.Mobile.Mobile.Use()
let page = Div [
Id "simplePage"
HTML5.Attr.Data "role" "page"
HTML5.Attr.Data "url" "#simplePage"
] -< [
Div[Text "content"]
]
Div [page]
|>! OnAfterRender (fun _ -> JQuery.Of(page.Body)
|> JQuery.Mobile.JQuery.Page
|> ignore
JQuery.Mobile.Mobile.Instance.ChangePage(JQuery.Of(page.Body)))
[<Sealed>]
type MyJQueryMobileEntryPoint() =
inherit Web.Control()
[<JavaScript>]
override this.Body = MyJQueryContent.Main() :> _
module Pages =
let HomePage =
PageContent <| fun context ->
{ Page.Default with
Title = Some "Index"
Body = [IntelliFactory.Html.Tags.Div[new MyJQueryMobileEntryPoint()]] }
[<Sealed>]
type Website() =
interface IWebsite<Action> with
member this.Sitelet = Sitelet.Content "/" Home Pages.HomePage
member this.Actions = [Home]
type Global() =
inherit System.Web.HttpApplication()
member g.Application_Start(sender: obj, args: System.EventArgs) =
()
[<assembly: Website(typeof<Website>)>]
do ()
Output:
As a side note, you are creating one of the containing DIVs when you write Div [page] instead of page before adding OnAfterRender, but indeed this is not your problem.
As Omar describes, with jQuery Mobile you need to carefully control when and how the initialization of the page structure takes place, especially when working with dynamic pages. I recall seeing your exact problem before but I can't find that conversation in my email box, however, here is an earlier article that has some useful bits for tapping into JQM page initialization:
http://fpish.net/blog/JankoA/id/3362/201367-jquery-mobile-page-reuse-with-websharper
When jQuery Mobile framework is loaded, it checks if there is a page div in DOM. If not, it wraps body's content in page div. To control this behavior, you need to prevent jQM's autoInitializePage in order to initialize manually $.mobile.initializePage() whenever you want.
You need to listen to mobileinit event to override autoInitializePage. The code should be placed after jQuery (core) and before jQuery Mobile libraries in head.
/* jQuery.js */
$(document).on("mobileinit", function () {
$.mobile.autoInitializePage = false;
});
/* jQuery-Mobile.js */
Now you can initialize jQuery Mobile whenever you want by calling $.mobile.initializePage().
I am a developer of WebSharper. Omar is right, this is a JQM thing, another workaround for it is having a dummy page node in the sitelet. Like this:
module Pages =
open IntelliFactory.Html
let HomePage =
PageContent <| fun context ->
{ Page.Default with
Title = Some "Index"
Body =
[
Div [HTML5.Data "role" "page"; Id "dummy"]
Div [new MyJQueryMobileEntryPoint()]
] }

How to resize images client side using jquery file upload

I am using blueimp jquery-file-upload in a Rails 3.2 app, via the jquery-fileupload-rails gem.
I am trying to resize images on the client side prior to uploading, but am having trouble following the documentation. My code is below. Currently uploading works perfectly, but the images are not resized.
What is the correct syntax to resize images via jquery-file-upload.
(Two approaches shown in the coffeescript based on this and this documentation. Neither works for me.)
#Coffeescript
jQuery ->
if $("#new_asset").length
$("#new_asset").fileupload
dataType: "script"
add: (e, data) ->
types = /(\.|\/)(jpe?g|png)$/i
file = data.files[0]
if types.test(file.type) || types.test(file.name)
data.context = $(tmpl("template-upload", file))
$('#progress-container').append(data.context)
jqXHR = data.submit()
$("button.cancel").click (e) ->
jqXHR.abort()
else
alert("#{file.name} is not a jpeg or png image file")
progress: (e, data) ->
if data.context
progress = parseInt(data.loaded / data.total * 100, 10)
data.context.find('.bar').css('width', progress + '%')
stop: (e, data) ->
$('.upload').hide()
process: [
action: "load"
fileTypes: /^image\/(gif|jp?g)$/
maxFileSize: 20000000 # 20MB
,
action: "resize"
imageMaxWidth: 1500
imageMaxHeight: 1500
,
action: "save"
]
dropZone: $(".dropzone")
sequentialUploads: true
disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator and navigator.userAgent)
imageMaxWidth: 1500
imageMaxHeight: 1500
downloadTemplateId: null
#application.js
//= require jquery-fileupload
EDIT
According to Matanza's answer, the add callback in my code prevents any processing functions from being called automatically. So I assume I need to do something like
...
add: (e, data) ->
$.each data.result, (index, file) ->
// processing code goes here
But I'm having a lot of trouble working out the correct syntax or making sense of the guides that are available.
How do I apply the resize processing to each file in the add callback?
I solved it by calling the process within the add callback like so:
add: (e, data) ->
current_data = $(this)
data.process(->
return current_data.fileupload('process', data);
).done(->
data.submit();
)
also remember to load your JS files in the right order in application.js....(this wasted several hours of my life):
//= require jquery-fileupload/vendor/jquery.ui.widget
//= require jquery-fileupload/vendor/load-image
//= require jquery-fileupload/vendor/canvas-to-blob
//= require jquery-fileupload/jquery.iframe-transport
//= require jquery-fileupload/jquery.fileupload
//= require jquery-fileupload/jquery.fileupload-ui
//= require jquery-fileupload/jquery.fileupload-process
//= require jquery-fileupload/jquery.fileupload-validate
//= require jquery-fileupload/jquery.fileupload-image
If that is still relevant-
I found out that once you use the add callback, it is your responsibility to add whatever processing stages that you require. So for that matter if you remove the add callback it will resize the image with your settings.
what you should do is register the resize processing settings to each file in the add function
hope that helps
I had trouble getting Image resize to work. In the end I started again. I had added image resize to an existing working file upload code. For me, it was the custom add that was hindering the resize. Once I removed the custom add, it was hunky-dorey. Just wanted to put it out there for the benefit of other strugglers.

javascript in rails not recognized

This is a fairly simple question but I can't seem to figure out why it's not working
I have this code:
$(".positive").numeric({ negative: false }, function() { alert("No negative values"); this.value = ""; this.focus(); })
which works when I put it in my view between <script> and </script>
However, when I copy and paste that formula to app->assets->javascripts-> page.js.coffee it doesn't work. I have even tried copy and pasting that code to JS2Coffee converter and pasting the coffee version of the code. Still no luck.
What am I doing wrong that my view does not recognize the javascript in my assets?
Here is the code in coffescript:
$(".positive").numeric
negative: false
, ->
alert "No negative values"
#value = ""
#focus()
my application.js has
//= require jquery
//= require jquery_ujs
//= require jquery.numeric
//= require_tree .
Your CoffeeScript generates the following JavaScript:
$(".positive").numeric({
negative: false
}, function() {}, alert("No negative values"), this.value = "", this.focus());
As you can see, it's not the same.
Please note some things:
You do not have to use CoffeeScript. You can use plain JavaScript if you want to.
If you want to use CoffeeScript, please read up on its syntax. Most importantly: in CoffeeScript, whitespace is significant.
Your codesnippet could look like this, in correct CoffeeScript:
$(".positive").numeric
negative: false
->
alert "No negative values"
#value = ""
#focus()
The reason that your code isn't executed when you put it through the asset pipeline, is that it will end up in the head of the document, instead of the body, and hence it will be executed before the browser has finished loading the DOM.
In other words - there isn't any element to fetch yet.
To solve this, wrap you code with JQuery:
$ ->
# Your code goes here
JQuery will make sure that your code is executed only once the DOM is ready for manipulation.

Resources