Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bower install keyboard and then grunt build cause "keyboard is not a funtion" error #418

Open
yangyili opened this issue Dec 10, 2015 · 15 comments

Comments

@yangyili
Copy link

when I bower install keyboard, it creates jquery.keyboard.min.js; I use requirejs in my project; then I execute "grunt build " minify project; the "jquery.keyboard.min.js" file was concat the require main.js file, and the main.js was minified too. I guess the error was caused by jquery.keyboard.min.js was repeat minifyed
how I get the jquery.keyboard.js by bower install keyboard?
thank you very much!
the error: "typeError: $(...).keyboard is not a function"; when I call keyboard function on jquery object

@yangyili
Copy link
Author

I tried minify the jquery.keyboard.js, the error still exist! I don't know what else reason cause the error

@Mottie
Copy link
Owner

Mottie commented Dec 10, 2015

Hi @yangyili!

I can update the bower.json file to include the non-minified version. I don't use bower, nor do I work with requirejs, so I can not provide a definitive answer for you.

But, I wonder if the problem might be with how the files are being included. Are you only including the jquery.keyboard.min.js file? I'm not 100% sure how to make the extensions "require" the keyboard and jQuery.

@yangyili
Copy link
Author

Thank you for your answer very much!
I have fixed the problem! it's not because the minified files; tthe problem was cuased by requirejs.
I found the following code(in your jquery.keyboard.js) [1]:

;function(factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof module === 'object' && typeof module.exports === 'object') {
        module.exports = factory(require('jquery'));
    } else {
        factory(jQuery);
    }
}(jquery-keyboard-function)

was minified in your jquery.keyboard.min.js as follow [2]:

!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof   module&&"object"==typeof module.exports?module.exports=a(require("jquery")):a(jQuery)}(jquery-keyboard-function)

but was minified in my project file as follow [3]:

function(e){typeof define=="function"&&define.amd?define("jquery-keyboard",["jquery"],e):typeof  module=="object"&&typeof module.exports=="object"?module.exports=e(require("jquery")):e(jQuery)}(jquery-keyboard-function)

Then I found in when run "define("jquery-keyboard",["jquery"],e) "code, it calls the "define" function of require.js, and finally it doesn't call "jquery-keyboard-function"; so "$.fn.keyboard" was not defiend

So for the moment I have to fix the problem by deleting the[1]code;and run "jquery-keyboard-function" with "jQuery" param immediatelly!

@Mottie
Copy link
Owner

Mottie commented Dec 11, 2015

I'm glad you solved the problem!

Do you know of a way to change the UMD wrapper so this problem doesn't happen in the future? I would appreciate a PR 😁.

@PekkaPLeppanen
Copy link

Had the same problem. This fixed it:

;(function (root, factory) {
    if(typeof define === 'function' && define.amd) {
        define(['jquery'], function(jquery){
            return (root.myModule = factory(jquery));
        });
    } else if(typeof module === 'object' && module.exports) {
        module.exports = (root.myModule = factory(require('jquery')));
    } else {
        root.myModule = factory(root.jQuery);
    }
}(this, function($) {
    /*
     * NOTHING CHANGED IN THE MODULE CODE ITSELF
     */
}));

Got the code from this article

I have tested this only with CommonJS (Browserify) environment. I can do PR for further testing or just grab the code from here.

@Mottie
Copy link
Owner

Mottie commented Jun 7, 2016

Hi @PekkaPLeppanen!

I'm glad to hear it! But I would prefer not to name myModule inside the wrapper because the keyboard is actually attached to jQuery as $.keyboard, and not naming it inside the wrapper would allow you to define a variable as any name. Maybe that is my ignorance showing since I haven't really used module loaders, so please correct me if I'm wrong.

Anyway, I would apprecaite it if you would please try this UMD example and let me know if it works for you. If it does, a PR would be greatly appreciated. 😁

@yangyili
Copy link
Author

yangyili commented Dec 6, 2016

I found what caused the problem is requirejs shim configuration:
The shim config only sets up code relationships. To load modules that are part of or use shim config, a normal require/define call is needed. Setting shim by itself does not trigger code to load
(reference: http://requirejs.org/docs/api.html)
so I use require function to load jquery.keyboard.js to resolve the code not loaded

@tobiasvandriessel
Copy link

tobiasvandriessel commented Jan 17, 2017

Hi, sorry to respond to this message so late, but if you modify in any extension at the beginning the third line (2nd line here)

	if ( typeof define === 'function' && define.amd ) {
		define( [ 'jquery'], factory );

to

	if ( typeof define === 'function' && define.amd ) {
		define( [ 'jquery', 'jqueryKeyboard' ], factory );

, the RequireJS user won't have the issue that the extensions fail to load with the error that "$.keyboard" is undefined. The user does need to have jqueryKeyboard (or another name) defined in their requirejs.config's paths, but that's a small change :p

For me this fixed a long standing issue :D

Oh and of course the same would go for the CommonJS case, so (I am not sure about this, but)

) {
		module.exports = factory( require( 'jquery' ) );

to

) {
		module.exports = factory( require( 'jquery' ), require('jqueryKeyboard') );

I don't know whether you agree about the second change, but the first one would make me happy :)

@Mottie
Copy link
Owner

Mottie commented Jan 17, 2017

I would have done this long ago, but I wasn't sure how to include an unnamed plugin as required in a UMD wrapper... so, how did you come up with "jqueryKeyboard"? Is it just the file name removing the periods, "min" and "js"?

I would greatly appreciate a pull request, so I don't muck-up any changes.

@tobiasvandriessel
Copy link

I understand completely, the name is indeed user-chosen, so this was just my naming, it can be anything you like. The user simply has to assign the correct file to the name you choose to 'require' there.

I can do a pull request and then you can choose what name you want to use? :p

@Mottie
Copy link
Owner

Mottie commented Jan 17, 2017

Is is possible to make it generic? I don't want to force my choice on to someone else... and there might be other plugins or libraries named "keyboard" since it is such a generic name.

@tobiasvandriessel
Copy link

I don't know whether you can make it generic, but I don't think so, you could go for Mottie-Virtual-Keyboard?

@Mottie
Copy link
Owner

Mottie commented Jan 17, 2017

I seem to recall seeing someone use a path, but I never tried it. Is this possible?

if ( typeof define === 'function' && define.amd )
	define( [ 'jquery', 'dist/js/jquery.keyboard.min.js' ], factory );

@Mottie
Copy link
Owner

Mottie commented Jan 17, 2017

But then how would one include extensions?

@tobiasvandriessel
Copy link

tobiasvandriessel commented Jan 17, 2017

I tried the relative path, but I get a "$keyboard.builtLayouts[layout] is undefined" error, maybe I did something else wrong :/

The extensions are something that the user will have to include himself (as he himself has to choose which one to use anyway), by defining them in the requirejs.config's paths, like so:

requirejs.config({
    baseUrl: "js/lib",
    paths: {
        app: "../app",
        jquery: "https://code.jquery.com/jquery-3.1.0.min",
        jqueryKeyboard: "https://cdnjs.cloudflare.com/ajax/libs/virtual-keyboard/1.26.13/js/jquery.keyboard.min",
        //jqueryKeyboardExtender: "https://cdnjs.cloudflare.com/ajax/libs/virtual-keyboard/1.26.13/js/jquery.keyboard.extension-extender.min",
        jqueryKeyboardExtender: "jquery.keyboard.extension-extender",

and then use them in a module by using

define(["jquery", "jqueryKeyboard", "jqueryKeyboardExtender"], 
function($) { 
... 
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants