kendoButton is not a function, although Kendo is loaded - javascript

I use RequireJS to load Kendo according to this and it works. jQuery is loaded first, then Kendo. But I got an error "kendoButton is not a function". Here is my app.js
require.config({
paths: {
"jquery": "lib/kendo-ui/jquery.min",
"jquery-ui": "lib/jquery-ui.min",
"kendo-ui": "lib/kendo-ui" // this is a directory containing all Kendo files
},
shim: {
"kendo-ui/kendo.button.min": {
deps: ["jquery"]
},
"kendo-ui/kendo.core.min": {
deps: ["jquery"]
}
}
});
require(["jquery", "kendo-ui/kendo.core.min", "kendo-ui/kendo.button.min"],
function ($)
{
$("#primaryTextButton").kendoButton();
});
Kendo troubleshooting says that jQuery should be included just once (yes, I have) and all the required Kendo files are included (yes, I included kendo.core.min.js).
I use RequireJS 2.2.0, Kendo 2016.1.226, and jQuery version, which is included in the Kendo package. Can someone point out what's wrong?

Set the baseURL to "js/kendo".
I'm not sure if this has been stated clearly in the documentation. I thought the URL in this example is well, an example, but it turns out to be important.

Related

Load textext.js plugin with require.js

I'm trying to load textext.js jquery plugin, with one of it's plugins, textext tags. On my project, I'm using require.js in order to load all scripts with it's dependencies.
As used for other scripts, I'm using a shim config on my main.js file:
main.js
require.config({
shin: {
jquery: {
exports: '$'
},
'textext': {
deps: ['jquery'],
exports: '$.fn.textext'
},
'textext_tags': {
deps: ['jquery', 'textext'],
}
},
paths: {
jquery: 'lib/jquery-min',
textext: 'lib/textext/textext.core',
textext_tags: 'lib/textext/textext.plugin.tags',
}
});
On the page that I use it, I call it as above:
file-app.js
define([
'jquery',
'textext',
'textext_tags',
], function($, Textext, TextextTags) {
// do stuff
});
The code is loading and working correctly on firefox, but on Chromium, sometimes (about 2/3 of the times), at the first time that I load the page, I've receive the following error, that broke the functioning of the page:
TypeError: Cannot set property 'TextExtTags' of undefined
#3 localhost/js/lib/textext/textext.plugin.tags.js:23:27
Inside the file textext.plugins.tags.js, we have at line 23 (the failure line):
$.fn.textext.TextExtTags = TextExtTags;
So, inspecting it with Firebug, I realize that Jquery is not loaded, so $ and $.fn is undefined.
My question is: why this schema of require.js is working with other jQuery plugins on the same project (like jquery cookie and others), but not with this, a jquery plugin with it's subplugins?
As Vishwanath said, only changing from "shin" to "shim" worked, like above:
require.config({
shim: {
jquery: {
exports: '$'
},
...
Thanks!

RequireJS way of creating a copy of object

Our project is really huge, singe-page enterprise app, based on RequireJS and Backbone.js, and for some complex UI we use jqWidgets.
In particular, these jqWidgets are what is causing us problems.
There are many app features implemented using older jqWidgets 3.3, and for all new ones we would like to use 3.6, but porting old features to 3.6 is very tricky and will cost us time that we don't have at the moment.
What we would like to do to save this time, is having both 3.3 and 3.6 working alongside without creating any problems, and do the porting part later when we can.
What I have tried so far:
requirejs.config({
paths: {
"jquery": "vendor/jquery",
"jqx": "vendor/jqwidgets/3.3",
"jqx3.6": "vendor/jqwidgets/3.6",
... other libs...
},
shim: {
... other shims ...
// jqWidgets3.3
"jqx/jqxcore": {
deps: ["jquery"]
},
"jqx/<<some_plugin>>": {
deps: ["jqx/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
// jqWidgets3.6
"jqx3.6/jqxcore": {
deps: ["jquery"]
},
"jqx3.6/<<some_plugin>>": {
deps: ["jqx3.6/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
}
});
Usage in old feature:
require(["jquery", "jqx/<<some_plugin>>"], function($) {
$('<<some_selector>>').<<some_plugin>>(...options...);
});
Usage in new feature:
require(["jquery", "jqx3.6/<<some_plugin>>"], function($) {
$('<<some_selector>>').<<some_plugin>>(...options...);
});
Since both plugins are applied to same jQuery object referencing them with different names/paths works but creates lots of bugs. Example: if first feature you used in app was loaded using jqWidgets 3.3, then next used feature using 3.6 would probably broke, and vice-versa. It only works if you refresh the page after every feature use -- which is kind of pointless since it is single-page app.
So my question is: is it possible to make both jqWidgets 3.3 and 3.6 work alongside by each one of then depend on their own jQuery object so this conflict does not happen?
// Appendix 1:
I think potential solution lies in comment of this question: RequireJS - jQuery plugins with multiple jQuery versions
I'll take a closer look and post here a solution if I find one.
You can use 'map' feature of requirejs,
Map allows you to map the same dependency to different files based on the module which uses dependency.
so you config your build file like this:
requirejs.config({
paths: {
"jquery": "vendor/jquery",
"jqueryForjqx3.6": "toNoConflictJQueryModule",
"jqx": "vendor/jqwidgets/3.3",
"jqx3.6": "vendor/jqwidgets/3.6",
... other libs...
},
map:{
'*':{
.....
},
'jqx':{
'jquery' : 'jquery'
},
'jqx3.6':{
// map jquery to no conlict jquery
'jquery' : 'jqueryForjqx3.6'
},
'jqueryForjqx3.6':{
'jquery' : 'jquery'
}
},
shim: {
... other shims ...
// jqWidgets3.3
"jqx/jqxcore": {
deps: ["jquery"]
},
"jqx/<<some_plugin>>": {
deps: ["jqx/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
// jqWidgets3.6
"jqx3.6/jqxcore": {
deps: ["jquery"]
},
"jqx3.6/<<some_plugin>>": {
deps: ["jqx3.6/jqxcore"],
exports: "$.fn.<<some_plugin>>"
},
}
});
This configuration maps jquery dependency to different files based on module which uses it.
The content of no conflict version can be like this:
define(['jquery'], function($){
return $.noConflict();
});
You can use http://requirejs.org/docs/jquery.html#noconflictmap about how to use jquery no-conflict and requirejs
if jqWidgets doesn't support it out of the box, I'd try this:
load jQuery
load jqxWidget 3.3
load jQuery again, but in its noConflict mode, and assign it to $2 for instance (I'm not sure RequireJS can do that, but you could copy the jQuery.js file and rename it to something different to load it a second time)
set the 1st jQuery to $1 (window.$1 = $)
set the 2nd jQuery to $ (window.$ = $2)
load jqxWidget 3.6
Now each jqxWidget should have its own, separate jQuery.
Obviously it's not ideal to have jQuery loaded twice, but that shouldn't be a problem apart from using a bit more memory on your app.

Scripts Dependencies Using RequireJS Shim

I'm upgrading from jQuery 1.8 to 1.9 and since jQuery.browser() is removed, I will use jQuery Browser Plugin.
My requirejs config file (loaded using data-main="") looks somewhat like this:
(EDITED - added more code snippets)
main-comp.js
require.config({
paths: {
jquery: 'libs/jquery/jquery1.9.1.min',
utils: 'modules/utils',
myController: "controllers/myController",
browserPlugin: 'libs/jquery/jquery.browser.min'
},
shim: {
browserPlugin: {
deps: ['jquery']
}
}
});
require(['myController', 'jquery'], function (controller, $) {
$(controller.start);
}
);
moduls/utils.js
define(['browserPlugin'], function () {
return {
browser: $.browser
};
});
myController.js
define(['utils'], function (utils) {
function start() {
console.log(utils.browser.msie)
}
return {
start: start
};
});
Everything seemed to work properly, but then I saw that sometimes in IE only I get a 'jQuery' is undefined (it's a capital Q there) or '$' is undefined errors from the jquery.browser.min.js file.
I thought the deps means that jquery will load before the jquery.browser file but apparently this isn't always the case. I tried following this answer and add exports: "$.fn.browser" but with no success.
When running an optimized version (minify+uglify using r.js) I haven't encountered it.
What am I doing wrong?
You need to ensure you reference $ as a parameter in the require callback. Like so:
require(['myController', 'jquery'], function (controller, $) {
$(controller.start);
}
);
This ensures that jQuery is available to use. It is a bit of an odd one as it will expose itself globally anyway so it will sometimes work regardless, but the correct way is to explicitly require it and use it inside the callback as a parameter.
It looks like you are missing jquery dependency in moduls/utils.js, please try:
define(['jquery', 'browserPlugin'], function ($) {
return {
browser: $.browser
};
});
and also, just to be on the safe side, add jquery to your shim :
jquery: {
exports: "$"
},
By the way, why don't you use $.browser in your code and just load the jquery plugin using the shim configuration?
I had the same problem, the script in data-main is loading asynchronously, that means that it may load after the scripts it defines.
The solution is to load another script with the require.config right after the require.js script.
data-main Entry Point Documentation.

Implementing AMD in JavaScript using RequireJS

I am totally new to RequireJS so I'm still trying to find my way around it. I had a project that was working perfectly fine, then I decided to use RequireJS so I messed it up :)
With that out of the way, I have a few questions about RequireJS and how it figures out everything. I have the file hierarchy inside the scripts folder:
I have the following line inside my _Layout.cshtml file:
<script data-main="#Url.Content("~/Scripts/bootstrap.js")" src="#Url.Content("~/Scripts/require-2.0.6.js")" type="text/javascript"></script>
And here's my bootstrap.js file:
require.config({
shim: {
'jQuery': {
exports: 'jQuery'
},
'Knockout': {
exports: 'ko'
},
'Sammy': {
exports: 'Sammy'
},
'MD': {
exports: 'MD'
}
},
paths: {
'jQuery': 'jquery-1.8.1.min.js',
'Knockout': 'knockout-2.1.0.js',
'Sammy': 'sammy/sammy.js',
'MD': 'metro/md.core.js',
'pubsub': 'utils/jquery.pubsub.js',
'waitHandle': 'utils/bsynchro.jquery.utils.js',
'viewModelBase': 'app/metro.core.js',
'bindingHandlers': 'app/bindingHandlers.js',
'groupingViewModel': 'app/grouping-page.js',
'pagingViewModel': 'app/paging-page.js'
}
});
require(['viewModelBase', 'bindingHandlers', 'Knockout', 'jQuery', 'waitHandle', 'MD'], function (ViewModelBase, BindingHandlers, ko, $, waitHandle, MD) {
BindingHandlers.init();
$(window).resize(function () {
waitHandle.waitForFinalEvent(function () {
MD.UI.recalculateAll();
}, 500, "WINDOW_RESIZING");
});
var viewModelBase = Object.create(ViewModelBase);
ko.applyBindings(viewModelBase);
viewModelBase.initialize();
});
require(['viewModelBase', 'bindingHandlers', 'Knockout'], function (ViewModelBase, BindingHandlers, ko) {
BindingHandlers.init();
var viewModelBase = new ViewModelBase();
ko.applyBindings(viewModelBase);
viewModelBase.initialize();
});
Then I implemented my modules by using the define function. An example is the pubsub module:
define(['jQuery'], function ($) {
var
publish = function(eventName) {
//implementation
},
subscribe = function(eventName, fn) {
//implementation
}
return {
publish: publish,
subscribe: subscribe
}
});
I've basically done the same thing to all of my javascript files. Note that the actual file containing the pubsub module is jquery.pubsub.js inside the /Scripts/utils folder. This is also the case with other modules as well.
UPDATE:
Ok I updated my bootstrap file now that I think I understand what a shim is and why I should be using it. But it's still not working for me, although I've also declared all the paths that I think would've caused me trouble in getting them right. The thing is that it's not even going into my require callback inside the bootstrap file, so I guess I still have a problem in the way I'm configuring or defining my modules?
Well, for one, if you are going to use a non-amd library, say jQuery, with require and have the jQuery function passed to the callback, you need to specify a shim with exports in your require config, like so:
require.config({
shim: {
jQuery: {
exports: '$'
}
},
paths: {
jQuery: 'jquery-1.8.1.min.js',
}
});
Other than that I'm not sure I understand what your issue is exactly.
If you are using ASP.NET MVC take a look at RequireJS for .NET
The RequireJS for .NET project smoothly integrates the RequireJS framework with ASP.NET MVC on the server side using xml configuration files, action filter attributes, a base controller for inheritance and helper classes.
I did not completely understand what the problem is. But if it relates to JS libraries to be loaded with require.js then this boot file works for me:
require.config({
paths: {
"jquery": "/scripts/jquery-1.8.2",
"sammy": "/scripts/sammy-0.7.1"
},
shim: {
"sammy": {
deps: ["jquery"],
exports: "Sammy"
}
}
});
require(["jquery", "sammy"], function ($) {
$(document).ready(function () {
alert("DOM ready");
});
});
Please, note, there is no '.js' in paths.
BTW, if you use MVC 4, you don't need #Url.Content in 'href' and 'src' any more.

How to debug a 3rd party library when moving to requirejs

I moved a project to requirejs and everything works fine except for a detail with a 3rd party library (which is not an AMD module). I would like to know any suggestions on the techniques to follow to resolve these type of issues when using requirejs.
The 3rd party library is kendo-ui and the issue is when trying to change the locale by calling kendo.culture("es-MX"). The function is being called without an error but it does not work as supposed.
The way to use this is kendo is by:
loading kendo :
loading the locale :
calling the function: kendo.culture("es-MX");
I checked and the only global variable that gets exported is named kendo by the kendo script. I cannot see any global variable added by kendo.culture.es-MX.min.js
The setup I did in my main script for requirejs is:
require.config({
paths: {
jquery: 'lib/jquery-1.7.2.min',
signals: 'lib/signals',
hasher: 'lib/hasher',
crossroads: 'lib/crossroads',
kendo: 'lib/kendo.web.min',
kendoCulture: 'lib/cultures/kendo.culture.es-MX.min',
knockout: 'lib/knockout-2.1.0',
knockout_kendo: 'lib/knockout-kendo.min',
underscore: 'lib/underscore-min',
json2: 'lib/json2',
faclptController: 'faclpt/faclptController',
FacturaViewModel: 'faclpt/FacturaViewModel',
ConfigViewModel: 'faclpt/ConfigViewModel',
domReady: 'lib/domReady'
},
shim: {
'kendoCulture': {
deps: ['kendo']
},
'kendo' : {
exports: 'kendo'
}
}
});
require([
'require',
'jquery',
'knockout',
'knockout_kendo',
'underscore',
'json2',
'faclptController',
'FacturaViewModel',
'ConfigViewModel',
'domReady'
], function (
require,
$,
ko,
knockout_kendo,
_,
json2,
faclptController,
FacturaViewModel,
ConfigViewModel,
domReady) {
// Start of Main Function
domReady(function () {
kendo.culture("es-MX");
// knockout Bindings
ko.applyBindings(FacturaViewModel, document.getElementById('Proceso'));
ko.applyBindings(ConfigViewModel, document.getElementById('Configuracion'));
});
});
So what else should I look for?
I would appreciate any techniques or tips on how to debug requirejs

Categories