Reputation: 882
The jQuery UI has handy functions that are available globally, e.g. Sine, Circ, Elastic, Back, Bounce etc. However when including jQuery UI using webpack, the global functions become unavailable. Following code fails:
function setup_sidebar_menu()
{
var $ = jQuery,
$items_with_submenu = public_vars.$sidebarMenu.find('li:has(ul)'),
submenu_options = {
submenu_open_delay: 0.25,
submenu_open_easing: Sine.easeInOut,
submenu_opened_class: 'opened'
},
root_level_class = 'root-level',
is_multiopen = public_vars.$mainMenu.hasClass('multiple-expanded');
because Sine is undefined. Is there any way to make those jQuery UI functions available globally when using webpack? For instance, $ is available globally, jQuery also is available globally. $.ui is available as well.
configuration is following:
environment.js
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
$: 'jquery',
JQuery: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
'window.Tether': "tether",
Popper: ['popper.js', 'default'], // for Bootstrap 4
}))
module.exports = environment
application.js
var jQuery = require("jquery")
// import jQuery from "jquery";
global.$ = global.jQuery = jQuery;
window.$ = window.jQuery = jQuery;
import 'webpack-jquery-ui'
as I said, the jQueryUI library is loaded correctly and available via $.ui, the problem concerns global functions.
UPDATE:
it appears that the correct solution is to create new js script file from scratch within the packs
directory and re-write valid ES6 / ES7. The problem which appears with this approach is that it's impossible to import jquery-ui global functions Sine, Circ, Elastic, Back, Bounce:
all fails, Sine and any other similar global function is always undefined:
import {Sine} from 'jquery-ui/ui/effect'
// or
import {Sine} from 'jquery-ui'
// or
import {Sine} from 'webpack-jquery-ui'
console.log(Sine)
what is wrong here?
Upvotes: 0
Views: 869
Reputation: 882
the correct approach is to define a new module within the packs
directory and copy-paste or re-write in ES6 all needed global jQuery-UI functions. Export functions from that module and than import it into the module which is using it.
For example, I have created ES6 module with previously global jQuery-UI functions:
app/javascript/packs/jquery-ui-es6-migrations.js
const Sine = (p) => {
return 1 - Math.cos( p * Math.PI / 2 );
}
const Circ = (p) => {
return 1 - Math.sqrt( 1 - p * p );
}
const Elastic = (p) => {
return p === 0 || p === 1 ? p :
-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
}
const Back = (p) => {
return p * p * ( 3 * p - 2 );
}
const Bounce = (p) => {
var pow2,
bounce = 4;
while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
}
export {Sine, Circ, Elastic, Back, Bounce}
in another ES6 module simply importing these functions:
import {Sine, Circ, Elastic, Back, Bounce} from './jquery-ui-es6-migrations'
that's it. everything works like a charm!
Upvotes: 0
Reputation: 14630
You probably don't want to hear this, but my sense is that you're kind of working against the general spirit of modular javascript, which isn't meant to (as a feature) encourage global code like this.
You could probably get this to work, but it seems a lot like an "old school" approach to writing JS where libs are available globally.
In the past when I REALLY needed something to be global, I would make an object on window, like window.APP = {}
at the top of the JS chain and stuff things in there that I really wanted to be global, like an Event Emitter, and ENV info from the server. I don't know if I would recommend this approach, it felt kinda code smelly to me, but I still did it in a couple of apps.
But my general sense is that the pain you're feeling here is about going against the grain. Doesn't mean you SHOULDN'T, but might as well give you pause to consider how else to do this.
Maybe you should put this in its own file in /packs
and import Sine
?
That said, I've seen that this may work, though I haven't used it myself:
import $ from 'jquery';
import 'jquery-ui-bundle';
import 'jquery-ui-bundle/jquery-ui.min.css';
This might add the Sine
on $
?
Upvotes: 1