I was trying to use jquery ui in a sharepoint project and since the jquery is already loaded I don't see the reason of requiring it again when I need the accordion from jquery ui.
I already followed all the steps and added the folders to work with require js. as in:
https://learn.jquery.com/jquery-ui/environments/amd/
but I still get the same error:
Script error for "jquery", needed by: jqueryui/widgets/accordion, jqueryui/version, jqueryui/keycode, jqueryui/unique-id, jqueryui/widget
here is my code:
function main() {
require({
paths: {
jqueryui: '/teams/sp-test-site/dist/jQuery/ui/1.12.1',
},
shim: {
deps: [ 'jquery', ],
},
}, [ 'jqueryui/widgets/accordion', ],
function (accordion) {
$('#accordion').accordion();
});
}
ExecuteOrDelayUntilScriptLoaded(function () {
SP.SOD.executeFunc('require.js', null, main);
}, 'core.js');
So I assume I am missing some init function to use the already loaded jquery from the globals, I am just not sure how, if it is the case. Does any body know what could be wrong here?
defining jquery and returning the global one solved.
define('jquery', [], function () {
return window.jQuery;
});
Related
I am adding jquery using requireJS like
requirejs.config({
enforceDefine: true,
paths: {
jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min'
}
});
Later in seperate JS file I am loading on page using require as
require(['jquery'], function ($) {
//Do something with $ here
}, function (err) {});
I gave jquery URL incorrectly and want to show some custom err message to end user..I added above code but when URL is incorrect the control is not coming inside err function..Do I want to add any other code..I am using for DOJO version.
It seems you're using the Dojo AMD loader, they have a different approach of handling errors.
While in RequireJS you would use:
require([ 'jquery' ], function($) {
// Do something with $ here
}, function(err) {
// Error handling
});
In Dojo you would use a different syntax, for example:
require.on('error', function(err) {
// Error handling
});
require([ 'jquery' ], function($) {
// Do something with $ here
});
An example: http://plnkr.co/edit/t3j7mTgLKSiTCIrvl2eD?p=preview
However, since you're using Dojo, the requirejs.config() does probably not work either if you're working the Dojo AMD loader.
I've written a full web app and I bootstrap it with require in this line at the end of my HTML document:
<script src="js/vendor/require-2.1.6.min.js" data-main="js/main.js"></script>
Inside main.js, I declare my app using the following two functions:
requirejs.config({
paths: {
'jquery': 'vendor/jquery-1.9.1.min',
'lodash': 'vendor/lodash-1.3.1.min',
'knockout': 'vendor/knockout-2.2.1.min',
'bootstrap': 'vendor/bootstrap-2.3.2.min'
},
shim: { 'bootstrap': { deps: ['jquery'] } }
});
requirejs(dependencies, function main(dependencies) { ... });
Now, I want to port my app as a jQuery plugin. As such, the end result I desire is to wrap my app in a jQuery fn,
(function($) { $.fn.myPlugin = function() { ... }; }(jQuery));
modularize the code to compile into a single js file (plugin-1.0.0.min.js), include the code in another project, with or without AMD, and load my app into a div using
$('#pluginDiv').myPlugin({ options: {} });
First, do I need to change the requirejs/requirejs.config functions to declares in order to package my app as a modular component? Or do I simply leave my app like this? What about the config?
Next, how do I expose my plugin to the jQuery which the plugin user will be using, e.g. the one declared in the global scope? Will this work if they're using an AMD?
UPDATE
For question 1, I moved my requirejs.config to a build file, build.js, which requires some additional properties:
({
baseUrl: ".",
paths: {
'jquery': 'vendor/jquery-1.9.1.min',
'lodash': 'vendor/lodash-1.3.1.min',
'knockout': 'vendor/knockout-2.2.1.min',
'bootstrap': 'vendor/bootstrap-2.3.2.min'
},
shim: { 'bootstrap': { deps: ['jquery'] } },
optimize: "none", // for debug
name: "main",
out: "plugin.js"
})
I was able to use r.js to compile this and it works great.
I am still stuck on question two, however. The code in my compiled myPlugin.js is as follows:
requirejs(dependencies, function main(dependencies) {
(function($) {
$.fn.myPlugin = function(options) {
...
return this;
};
})(jQuery);
});
where dependencies does not include jQuery. Then, I bootstrap the app by calling:
<script src="js/vendor/require-2.1.6.min.js" data-main="js/app.js"></script>
And the code in app.js is
requirejs.config({
paths: { 'jquery': 'vendor/jquery-1.9.1.min' },
shim: { 'myPlugin': ['jquery'] }
});
requirejs(['jquery','myPlugin'], function main($) {
$('#plugin').myPlugin(options);
});
However, my code always attempts to bind the plugin (from app.js), fails when the plugin is not a method on jQuery, and THEN loads the compiled plugin code and creates the method on jQuery. What's the problem here??
UPDATE 2
So, I've created a modular JavaScript file plugin.js using requirejs and its optimizer. The main code in the compiled plugin script,
requirejs(dependencies, function main(dependencies) {
(function($) {
$.fn.plugin = function(options) { return this; }
})(window.jQuery);
);
doesn't get called until after the main code in the parent app:
requirejs(['jquery','plugin'], function main($) {
$('#plugin').plugin({});
});
I assume this is because they are both making calls to requirejs. So the problem here is how to write my plugin such that it is usable within an AMD loader.
Sorry, I'm still figuring out the right questions to ask.
There is a pretty standard convention for modularizing plugins for use with and without requirejs. It looks something like this:
(function(){
var makeplugin = function(dependancies){
//do your plugin
};
if(define && define.amd) {
defined(dependancies,function(dependancies){
makeplugin(dependancies);
});
} else {
makeplugin(dependancies)
}
}());
Because your plugin uses require internally, but your parent app doesn't have to, you can load requirejs using $.getScript()
(function(){
var makeplugin = function($){
//do your plugin
};
if(define && define.amd) {
// require is defined already, just use the plugin and have it load what it needs
define(["jquery"],makeplugin);
} else if(jQuery){
// load require
jQuery.getScript("/vendor/require",function(){
require.config({
// your config
});
makeplugin(jQuery);
});
} else {
throw "requirejs or jquery are required for this plugin";
}
}());
It isn't pretty but it should work.
I'm trying to load jqplot as a requireJS module.
My main.js has a path and shim like this:
require.config({
, paths: {
plot: '../js/plugins/jqplot/jqplot.module'
}
, shim: {
'plot': { deps: ['jquery']}
}
});
Since this module is not needed on most pages, I'm waiting for the pageXYZ to be loaded and then inside a <script></script>, I'm calling:
require(['plot'],
function (plot) {
// do stuff
}
);
And my jqplot.module looks like this:
define(['../js/plugins/jqplot/jquery.jqplot'],
function () {
require([
'../js/plugins/jqplot/plugins/jqplot.barRenderer'
, '../js/plugins/jqplot/plugins/jqplot.logAxisRenderer'
, '../js/plugins/jqplot/plugins/jqplot.categoryAxisRenderer'
, '../js/plugins/jqplot/plugins/jqplot.canvasAxisTickRenderer'
, '../js/plugins/jqplot/plugins/jqplot.canvasTextRenderer'
, '../js/plugins/jqplot/plugins/jqplot.pointLabels'
, '../js/plugins/jqplot/plugins/jqplot.enhancedLegendRenderer'
],
function (){
return $.jqplot;
}
);
}
);
which returns the correct object with all sub-plugins defined and usable.
However, my Do stuff code runs BEFORE jqplot is assigned to $, so I'm still getting undefined errors when my code runs (I assume, because the files are all loaded, so requirejs starts running)
Question:
What can I do halt code execution until the jqplot has been assigned to $?
1) I think this line from your question:
define(['../js/plugins/jqplot/jquery.jqplot'],
should read:
define(['../js/plugins/jqplot/jquery.module'],
2) You do not need a shim, because you have a module definition that loads jqplot. So change your requirejs.config to
require.config({
, paths: {
plot: '../js/plugins/jqplot/jqplot.module'
}
});
3) your jqplot.module is not returning anything right now. Change it to:
define([
'../js/plugins/jqplot/jquery.jqplot'
],
function () {
var plot;
require([
'../js/plugins/jqplot/plugins/jqplot.barRenderer',
'../js/plugins/jqplot/plugins/jqplot.logAxisRenderer',
'../js/plugins/jqplot/plugins/jqplot.categoryAxisRenderer',
'../js/plugins/jqplot/plugins/jqplot.canvasAxisTickRenderer',
'../js/plugins/jqplot/plugins/jqplot.canvasTextRenderer',
'../js/plugins/jqplot/plugins/jqplot.pointLabels',
'../js/plugins/jqplot/plugins/jqplot.enhancedLegendRenderer'
],
function () {
plot = $.jqplot;
});
return plot;
});
This is all untested, but I think these should help
Answering this question and all the repeats, basic above answer is close but no cigar, as require is async, as such require could/will fire before define closure closes and returns, async safe solution below :
Nasty problem, as it's a chain of three dependencies
jquery is required for jqplot which is required for jqplot plugins, I have a simpler solution based on the same lines as the one above
first do your requirejs "main.js" config like so
requirejs.config({
paths: {
"jquery": "path/to/jquery-1.10.2.min",
// WORKAROUND : jQuery plugins + shims
"jqplot.core": "path/to/jquery-jqplot-1.0.8.min",
"jqplot": "jquery-jqplot-module-with-plugins-1.0.8"
},
shim: {
"jqplot.core": {deps: ["jquery"]},
"jqplot": {deps: ["jqplot.core"]}
}
});
create a wrapper file module file called "jquery-jqplot-module-with-plugins-1.0.8.js", containing :
// wraps jquery jqplot plugin in define statement
define([
"jquery",
"path/to/jqplot.highlighter.min",
"path/to/jqplot.cursor.min",
"path/to/jqplot.dateAxisRenderer.min",
"path/to/jqplot.canvasTextRenderer.min",
"path/to/jqplot.canvasAxisLabelRenderer.min",
"path/to/jqplot.enhancedLegendRenderer.min",
"path/to/jqplot.pieRenderer.min",
"path/to/jqplot.donutRenderer.min",
], function($) {
var jqplot;
jqplot = $.jqplot;
return jqplot;
});
Then when ever you need jqplot with those plugins, simply call for "jqplot" which will load "jquery" then "jqplot.core" then all the jqplot modules, then finally return the jqplot object :)
require(["jquery", "jqplot"], function ($, $jqplot) {
console.log("Success..Inside Require JS");
console.log("Plot...", $.jqplot, $jqplot);
});
or
define(["jquery", "jqplot"], function ($, $jqplot) {
console.log("Success..Inside Define JS");
console.log("Plot...", $.jqplot, $jqplot);
});
tada! :)
ps jquery plugins are evil, no suggestion how to fix that situation, just a statement of fact
cheers
Ant
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.
I have about 3 different errors that can occur while loading the same page. I get different errors when I refresh the same page: jquery ui loads before jquery, or underscore does not load in time to be a dependency. Is there a way to make sure the configuration modules wait until their depenedencies load before loading themselves? I am using the following:
main.js
require.config({
paths: {
jQuery: 'libs/jquery/jquery-wrapper',
Underscore: 'libs/underscore/underscore-wrapper',
Backbone: 'libs/backbone/backbone-wrapper',
}
});
require([
'src/app',
'order!libs/jquery/jquery-min',
'order!libs/jquery/jquery-ui-min',
'order!libs/jquery/jquery.ui.selectmenu',
'order!libs/underscore/underscore-min',
'order!libs/backbone/backbone-min',
], function (App) {
App.initialize();
});
I grab injected dependencies from the page.
app.js
define([
'jQuery',
'src/global'
], function ($) {
var initialize = function () {
var d = $('#dependencies').html();
require($.trim($('#dependencies').html().toString()).split(','), function () {
});
}
return {
initialize: initialize
};
});
I was using Require v2, which got rid of order. I switched back to version 1 and the problem was resolved.
I switched to Require 2.0 and employed a shim that is working for the most part.