Rails Webpacker SCRIPT5009: 'app' is undefined - IE11 issues - ruby-on-rails

For some reason most of my JS work in IE11 and lower fails. No issues with Chrome, Firefox, and Edge.
I have in the application.html.slim file:
meta http-equiv='X-UA-Compatible" content="IE=edge'
I found this: github webpacker thread
So I went through and tried the following in my config > webpack > production.js:
if (environment.plugins.getIndex('UglifyJs') !== -1) {
const plugin = environment.plugins.get('UglifyJs');
plugin.options.uglifyOptions.ecma = 5;
}
environment.config.optimization.minimizer[0].options.uglifyOptions.ecma = undefined
environment.plugins.get("UglifyJs").options.uglifyOptions.ecma = 5
None of those worked. In the console I'm getting:
SCRIPT5009: 'app' is undefined
From my home page I have it set up:
= content_for :head do
= stylesheet_pack_tag 'styles/home'
= javascript_pack_tag 'home'
= javascript_include_tag "//maps.googleapis.com/maps/api/js?key=#{ENV['MAP_KEY']}"
= content_for :body do
.container
.row
#map-banner.banner[type"hidden" data-location=all_locations.to_json]
=render template: '/layouts/application'
javascript:
document.addEventListener('DOMContentLoaded', app.home);
Then in my javascript > packs > home.js
import { mapStyle } from './styles/mapStyle';
app.home = () => {
function init() {
setupSlider();
homeSlider();
startGoogleMap();
let tabs = document.querySelectorAll('a.tab');
for (let tab of tabs) {
tab.addEventListener('click', tabClicked);
}
document
.querySelector('#region-select_')
.addEventListener('change', selectClicked);
}
return init();
};
Current versions:
webpack 3.12.0
rails 5.2.2
yarn 1.17.3
bootstrap 4.3.1
When I checked in the Network on my tiny-slider.js it's returning a status code of 304 however its returning 200 in Chrome. Any idea why it's not compiling?

Leaving this here in case someone finds it useful. Updated config > webpack > environment.js with:
environment.loaders.get('babel').exclude = [];

Related

PhotoSwipe, Rails, Coffee doesn't work at all

Can't understand why PhotoSwipe doesn't show anything when I'm trying to add it into Rails project
Used this gem: https://github.com/skakri/photoswipe-rails
Step by step reproduced manual: https://photoswipe.com/documentation/getting-started.html#init-add-pswp-to-dom
Wrote 'click' handler
But it shows nothing
Code I wrote:
<body>
<!-- some Rails and other stuff -->
<%= render 'shared/photoswipe' %>
</body>
shared/_photoswipe.html.erb contains full copy of div class="pswp" from 2)
Invisible div successfully added at the end of page
Added some coffee code for PhotoSwipe init on click handler
$ ->
$PhotoContainer = $('#MainPhoto')
$PhotoContainer.click ->
$pswpElement = document.querySelectorAll('.pswp')[0]
$items = []
$('.photo-item').each ->
$Img = $(#)
$items.push( { src: getUrlFromImg($Img).bigImgUrl, w: 1000, h: 1000 } )
$options = {
history: false,
focus: false,
index: 0
}
$gallery = new PhotoSwipe( $pswpElement, PhotoSwipeUI_Default, $items, $options)
$gallery.init()
When I click on #MainPhoto container event fired, $items array correctly fills by image urls and sizes and calls PhotoSwipe init() function, but nothing shows on screen
gem is improperly written
should add
#import "photoswipe/index";
#import "photoswipe/photoswipe";
#import "photoswipe/default-skin/default-skin";
into application.scss

Rails 6 + Webpacker 4 + PostCSS & #font-face + Local fonts

I'm trying to import fonts in my rails 6 app for hours now.
It's a fresh app using Rails 6, Webpacker 4 and PostCSS.
Everything is loaded (with no error) through webpack (css, js, images). Compilation is correct. Image are properly displayed (using css background:url).
OTF/EOT/WOFF fonts : Compiled properly and fonts inside my #font-face are loaded and salted by Webpack. The font are not rendered properly in view (I got the default browser font instead).
I think I tried everything I know. I Switched file-loader for url-loader and back, with no success. Changed the folders hierachy, tried different fonts files, absolute urls (resolve-url-loader). Nothing seems to work.
Anyone would be kind enough point me to the right direction or to share a working config of local fonts loading with webpacker on rails 6 and PostCSS ?
Thank you in advance for your help.
Here is my config :
javascript > fonts
raleway_thin-webfont.woff
javascript > packs > application.js
require.context('../fonts/', true, /\.(eot|ttf|woff|woff2|otf)$/i);
import "./application.pcss";
import "js";
require("#rails/ujs").start();
require("turbolinks").start();
require("#rails/activestorage").start();
require("channels");
javascript > packs > application.pcss
#font-face {
font-family: 'Raleway';
src: url('../fonts/raleway_thin-webfont.eot'), format('eot');
}
#font-face {
font-family: 'Amaranth';
src: url('../fonts/Amaranth-Regular.otf'), format('otf');
}
#test-div { font-family: 'Raleway'; }
/postcss.config.js
module.exports = {
plugins: [
require('postcss-import'),
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
})
]
};
/config > webpack > environment.js
const webpack = require("webpack");
const { environment } = require("#rails/webpacker");
const { VueLoaderPlugin } = require("vue-loader");
const vue = require("./loaders/vue");
// const url = require('./loaders/url');
environment.plugins.append(
"Provide",
new webpack.ProvidePlugin({
jQuery: "jquery",
$: "jquery",
Tether: "tether",
tether: "tether",
Popper: ["popper.js", "default"]
})
);
["css", "moduleCss"].forEach(loaderName => {
const loader = environment.loaders.get(loaderName);
loader.test = /\.(p?css)$/i;
environment.loaders.insert(loaderName, loader);
});
environment.plugins.prepend("VueLoaderPlugin", new VueLoaderPlugin());
environment.loaders.prepend("vue", vue);
// environment.loaders.prepend("url", url);
// avoid using both file and url loaders
// environment.loaders.get("file").test = /\.(tiff|ico|svg)$/i;
module.exports = environment;
/config > webpack > loaders > url (not in use)
module.exports = {
test: [/\.eot$/, /\.otf$/, /\.ttf$/, /\.woff$/, /\.woff2$/],
use: [
{
loader: "url-loader",
options: {
limit: 10000,
name: "[name]-[hash].[ext]"
}
}
]
};

How to solve Rails environment difference? Works in staging but not in dev

I have dashboards that are in a backbone.js app in a larger Rails app. In staging and production (on heroku) the dashboards work fine.
However, in my local Pow dev environment I get the following error in the browser console when I try and view a specific dashboard:
Uncaught TypeError: Object #<Object> has no method 'merge'
After tracking that down a bit, here is what I came up with. The merge method being referred to in the error message is coming from the rendered /assets/templates/dashboard/details.js file. Here is the code with what the browser is calling the error at the start of line 5: helpers = this.merge...:
(function() {
this.HandlebarsTemplates || (this.HandlebarsTemplates = {});
this.HandlebarsTemplates["dashboard/details"] = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression;
buffer += "<p>\n <b>Name:</b>\n <span class='editable' data-attribute-name='name'>";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "</span>\n</p>\n<p>\n <b>Description:</b>\n <span class='editable' data-attribute-name='description'>";
if (stack1 = helpers.description) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.description; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "</span>\n</p>\n<p>\n <button class='add_module'>Add module</button>\n</p>\n";
return buffer;
});
return this.HandlebarsTemplates["dashboard/details"];
}).call(this);
I think this is a Rails precompile or asset pipeline setup issue since it works fine in staging and production but fails in local development.
It sucks having to push any changes to heroku to test them. Any suggestions for solving this are appreciated.
It looks like this is resulting from my handlebars version being out of date. Thanks to the Thoughtbot guys for helping to track this down.
https://github.com/wycats/handlebars.js/issues/547

Facebook commenting w/Rails 4 and Turbolinks

I'm having trouble adding Facebook social plugins (specifically commenting) to my Rails 4 app with Turbolinks enabled. I followed the example on turbolinks issue #62, but couldn't get it to work.
I also tried turbolink's solution here, but couldn't get it to work.
Fixing the apparent typo on the turbolinks page per this answer did not work either.
The SDK isn't loading and there are no errors in the console.
Code:
### view:
<div id="fb-root"></div>
<div class="fb-comments" data-href="<%= request.original_url %>"></div>
### coffeescript:
fb_root = null
fb_events_bound = false
$ ->
loadFacebookSDK()
bindFacebookEvents() unless fb_events_bound
bindFacebookEvents = ->
$(document)
.on('page:fetch', saveFacebookRoot)
.on('page:change', restoreFacebookRoot)
.on('page:load', ->
FB.XFBML.parse()
)
fb_events_bound = true
saveFacebookRoot = ->
fb_root = $('#fb-root').detach()
restoreFacebookRoot = ->
if $('#fb-root').length > 0
$('#fb-root').replaceWith fb_root
else
$('body').append fb_root
loadFacebookSDK = ->
window.fbAsyncInit = initializeFacebookSDK
$.getScript("//connect.facebook.net/en_US/all.js#xfbml=1")
initializeFacebookSDK = ->
FB.init
appId : 'xxxxxxxxxxxx'
channelUrl: '//www.mydomain.com/channel.html'
status : true
cookie : true
xfbml : true
### /public/channel.html
<script src="//connect.facebook.net/en_US/all.js"></script>
--
Thanks. Really appreciate the help.
Try this and let me know if it works...
create a social.js.coffee in assets/javascripts folder.
in it write:
$(document).on 'page:change', ->
FB.init({ status: true, cookie: true, xfbml: true });
Do the following:
Install observejs:
gem 'observejs'
Then add tag to the widget:
<div as="FB" class="fb-comments" data-href="<%= request.original_url %>"></div>
Then create a new script in javascripts folder (fb.coffee in my example):
ObserveJS.bind 'FB', class
root: document.createElement('div')
#::root.id = 'fb-root'
loaded: =>
if !document.body.contains(#root)
document.body.appendChild(#root)
if FB?
FB.XFBML.parse()
else
#initialize()
initialize: =>
js = document.createElement('script')
script = document.getElementsByTagName('script')[0]
js = document.createElement('script')
js.id = 'facebook-jssdk'
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=YOUR_APP_ID&version=VERSION_OF_API"
script.parentNode.insertBefore(js, script)
Include the js files in your application.js
//= require observejs
//= require fb

jquery mobile footer does not render properly with dynamic content

Folks
I am using backbonejs (0.9) with latest jquery mobile (1.3). I am using WebSql for storing local data. When the home page loads, I do a query from the local database and use jquery Deferred to render the content after the query is successful. Unfortunately, the jquery mobile footer does not get "enhanced".
My Haml template for the view is simple and looks as follows:
%div{'data-role' => 'header'}
%div{'data-role' => 'navbar', 'data-iconpos' => 'top'}
%ul
%li
%a.ui-btn-active.ui-state-persist{'href' =>''}ATAB
%li
%a{'href' =>'#btab'}BTAB
%div{'data-role' => 'content'}
%div{'data-role' => 'footer', 'data-position' => 'fixed'}
%a{'data-icon' => 'plus', 'href' => '#a_link'}A link
My Backbonejs view looks as follows (I use coffeescript). Router already has templates cached in router.templates and txnsLoadedPromise gets "resolved" once the db records from websql are loaded:
window.HomeView = class HomeView extends Backbone.View
initialize: (options) ->
#template = Handlebars.compile(router.templates['/home/home'])
render: () ->
txnsLoadedPromise.then(
#renderDynamic
)
return this
renderDynamic: () =>
if (transactions.length > 0)
#generate content dynamically here and put in result
result = {}
$(#el).html(#template(result))
$('[data-role="header"]').trigger('create')
$('[data-role="footer"]').trigger('create')
This is how my view looks:
I have tried to use "refresh" instead of create in the trigger call for footer but it does not work. Strangely enough, the header refresh works properly. Also, if I remove the dynamic nature of the page (meaning render the view directly instead of when the promise is resolved, then it works fine (which is expected.)
Just for completeness, Following is my router code (portions of it that are relevant)
window.MyRouter = class MyRouter extends Backbone.Router
routes:
"": "home"
initialize: (options) ->
#code for preloading view templates
templates: {}
home: () ->
PageUtil.changePage new HomeView({templateKey: '/home/home'})
And the changePage method in PageUtil class:
window.PageUtil = class PageUtil
#changePage: (view, overrideOptions={}, role='page') ->
defaultOptions={transition: 'slide', reverse: false}
options = $.extend(defaultOptions, overrideOptions)
view.render();
$('body').append($(view.el));
if window.curentView
console.log 'removing view: ', currentView
window.currentView.remove()
window.currentView = view
$.mobile.changePage(view.$el, options);
Any ideas?
There's a problem in your code.
First trigger('create') will work only on content part, use trigger('pagecreate') to enhance header + content + footer.
Read more about it in my other ARTICLE. Or find it HERE.
There you will find a working example of dynamically added footer content.
If you are adding dynamic navbar element then even trigger('pagecreate') wont help you.
But there's a working solution:
$('#index').live('pagebeforeshow',function(e,data){
navbarHandler.addNewNavBarElement('navbar-test','el4','Page Four');
});
var navbarHandler = {
addNewNavBarElement:function(navBarID, newElementID, newElementText) {
var navbar = $("#" + navBarID);
var li = $("<li></li>");
var a = $("<a></a>");
a.attr("id", newElementID).text(newElementText);
li.append(a);
navbar = navbarHandler.clearNavBarStyle(navbar);
navbar.navbar("destroy");
li.appendTo($("#" + navBarID + " ul"));
navbar.navbar();
},
clearNavBarStyle:function(navbar){
navbar.find("*").andSelf().each(function(){
$(this).removeClass(function(i, cn){
var matches = cn.match (/ui-[\w\-]+/g) || [];
return (matches.join (' '));
});
if ($(this).attr("class") == "") {
$(this).removeAttr("class");
}
});
return navbar;
}
}

Resources