JQVMAP with requirejs - javascript

How do I use jquery vector maps with require.js as a module?
Is JVP amd compatible? It'll be great if someone could link to an example or suggest some workaround.
I can't use shim option as I'm using old require.js and can't update it.

You can wrap the library with a define yourself, effectively achieving what the shim option does. A quick test setup:
jqvmap-wrapped.js
// to simplify the example used jQuery named as "jquery.js"
define(['jquery'], function(jQuery){
// original jqvmap.js goes here
// (...)
// please note: not returning anything
});
index.html
<html>
<head>
<script data-main="index" src="require.js"></script>
</head>
<body>
<div id="vmap" style="width: 600px; height: 400px;"></div>
</body>
</html>
index.js
define(['jquery', 'jqvmap-wrapped'], function ($, _jqvmapEmpty) {
console.log('jQuery=', $);
console.log('jqvmap-wrapped=', _jqvmapEmpty);
console.log('jqvmap attached to jQuery? ', $.prototype.vectorMap);
$('#vmap').vectorMap({
// params
});
})
A word of explanation: the plugin adds itself to jQuery, it has no "standalone" version. The wrapper module doesn't return anything, it just has a side-effect of adding jqvmap to the jQuery object; that's why the _jqvmapEmpty variable itself is undefined. It's available through jQuery, though, so you can use it in the same manner you'd do it in a non-modular code.

Related

Gist-embed with Angular app

Trying to get gist-embed (https://github.com/blairvanderhoof/gist-embed) working within my Angular app but with no luck.
It works no problem on my homepage (which is not part of the Angular app) but when I use something like:
<code data-gist-id="<gist-id>"></code>
within the app it won't show. There are no messages in the console to explain why though.
Could someone explain why and offer a solution?
(function($) {
$(function() {
// find all elements containing "data-gist-id" attribute.
$('[data-gist-id]').each(function() {
var $elem = $(this),
id,
that lib is coded in such a way one cant really use it in angular,you'll have to look for a fork that offers a proper jquery plugin architecture you can use into a directive.That lib doesnt respect basic jQuery plugin architecture.
And no Error will show up because it's likely the .each will execute before your angular app runs.
As of June (version 1.8), the gist-embed project is now a jQuery plugin.
var $code = $('<code data-gist-id="474f6d7839fccffc4b2a"/>');
$code.appendTo('body').gist();
Basically you have to trigger "gist()" on the dom elements.
Try this, it worked for me very well.
// register trigger gist on every template include
$rootScope.$on('$includeContentLoaded', function() {
// initialize gist on new elements
angular.element(document).ready(function() {
if (typeof(angular.element(document).gist) === 'function') {
angular.element('[data-gist-id]').gist();
}
});
});
I put together a small library hoping to solve the problem.
Check it out : https://github.com/pasupulaphani/angular-gist-embed
Chekout this angular module : https://github.com/kiran3807/another-angular-gist-embed
This allows you to include the gists in your angular project in the form of a directive, one of the attributes for which is the gist-id :
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="path/to/another-angular-gist-embed.js"></script>
<script>
angular.module('example',['another-angular-gist-embed']);
angular.module.controller('exampleCtrl',['$scope',function($scope){
$scope.gistId = 'a85770344febb8e30935';
}]);
</script>
</head>
</head>
<body ng-app="example">
<div ng-controller="exampleCtrl">
<!-- This loads a gist with a specific id-->
<gist-embed data-gist-id="gistId"></gist-embed>
</div>
</body>
</html>
Declaration : I am the author of this module

Force AngularJS to use specific version of jQuery while using multiple versions of jQuery at once

I inherited the project where several version of jQuery are loaded into the page in noConflict mode. Application is huge, tests are missing and it seems every former devloper did not have "cohones" big enough to remove previous library. So the result is that $ refers to jquery version 1.4.2.
Is there any way/trick to tell angular wich version of jQuery should be used? Something like
angular.jq = j182
I know I can do it like
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="xxx/scripts/angular.js"></script>
<script>j182 = jQuery.noConflict();</script>
but then I have kind of "hidden dependency" which I would like to avoid.
You're right that $.noConflict() allows you to play with 2 versions of jQuery at once (which should be avoided unless REALLY necessary).
To make your angular module use the version you want, you can use ng-jq="whateverYouCallIt" where whateverYouCallIt is variable in window. Example:
<script type="text/javascript" src="/js/jquery-1.9.0.min.js"></script>
<script type="text/javascript">window.j190 = jQuery.noConflict();</script>
<script type="text/javascript" src="/js/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
console.log('globally available jQuery: ' + jQuery.fn.jquery);
console.log('j190: ' + window.j190.fn.jquery);
</script>
...
<div ng-app='myApp' ng-jq="j190" ng-controller='MyController' id="myAngularApp">
Just be careful, because if you need to access $scope from somewhere else, you will have to obtain it via the same jQuery that has been specified in ng-jq:
var myAnguarAppScope = window.j190('#myAngularApp').scope();
BTW, the above console.log calls output:
globally available jQuery: 1.7.2
j190: 1.9.0

Conditional Loading of CSS files based on test condition in JQuery plugin

I'm looking for the best approach to conditionally load some files based on a specific set of conditions.
I have three CSS files and two javascript files which I'm currently loading like so:
<link href="core.min.css" rel="stylesheet" type="text/css">
<link href="add_regular.min.css" rel="stylesheet" type="text/css">
<link href="add_retina.min.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery-plugin.min.js"></script>
As is evident the fourth file is JQuery and the fifth is my JQuery plugin. Inside the JQuery plugin are a series of functions that are like tests e.g. isMobile, isRetina, isPhone, etc. However, let's focus on isRetina.
What I am trying to accomplish is as follows:
Load JQuery and my JQuery Plugin first
Use isRetina function inside my JQuery plugin to check whether the device has a retina display
Load core.min.css
Load add_regular.min.css if not Retina display, or load add_retina.min.css if Retina display
Currently I'm loading all three CSS files and I wouldn't want to do that because I've got a bunch of other CSS files and I want to load them as my JQuery plugin determines which one is best as per my above example. For example, I might have a phone.min.css that I would want to load after I do another test using my plugin's isPhone function.
I'm considering using YepNope and doing something like this:
<script type="text/javascript" src="yepnope.min.js"></script>
<script>
yepnope([{
load: ['jquery.min.js', 'jquery-plugin.min.js'],
test : $.myplugin.isRetina(),
yep : ['core.min.css', 'add_retina.min.css'],
nope : ['core.min.css', 'add_regular.min.css'],
complete : function(){
//my jquery plugin constructor here
$(selector).myplugin(options);
}
}]);
</script>
However, even if the above approach is the correct one, I am not sure how to implement document.ready, as my plugin's constructor needs to run only when the DOM is ready.
I would like some ideas on how I can pull this off using YepNope or any other solution.
Cheers.
I am not sure how to implement document.ready, as my plugin's constructor needs to run only when the DOM is ready.
There are two relevant events
window.addEventListener('load', function () {
// code runs when document+resources have finished loading
});
and
document.addEventListener('DOMContentLoaded', function () {
// code runs when document has finished parsing, but before resources loaded
});
If you wait for either of these events before importing jQuery, I'm not sure what effect it will have on jQuery's inbuilt $(document).ready / similar.
That said, you do have the option of checking document.readyState === 'complete' before attaching listeners, to see if you should invoke straight away.
I was just going over the JQuery Docs for .ready(), and apparently $(function(){}); is equivalent to $(document).ready(function() {}); (I'm not sure how I'm just discovering this #ScratchingMyHead).
I also saw this being used in a YepNope Tutorial on NetTuts+: http://net.tutsplus.com/tutorials/javascript-ajax/easy-script-loading-with-yepnope-js/.
So I guess my earlier code becoming what you see below should solve the problem:
<script type="text/javascript" src="yepnope.min.js"></script>
<script>
yepnope([{
load: ['jquery.min.js', 'jquery-plugin.min.js', 'core.min.css'],
test : $.myplugin.isRetina(),
yep : 'add_retina.min.css',
nope : 'add_regular.min.css',
complete : function(){
//my jquery plugin constructor added to JQuery DOM Ready Stack
$(function(){
$(selector).myplugin(options);
});
}
}]);
</script>
I will test this out and remove this if it doesn't work.
Not sure if I understand you correctly but this should work.
Include this by default:
<link href="core.min.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery-plugin.min.js"></script>
<script type="text/javascript">
yepnope([{
load: ['jquery.min.js', 'jquery-plugin.min.js'],
test : $.myplugin.isRetina(),
yep : ['core.min.css', 'add_retina.min.css'],
nope : ['core.min.css', 'add_regular.min.css'],
complete : function(){
//my jquery plugin constructor here
$(selector).myplugin(options);
//Remove the mask here.
}
}]);
// Feel free to call ready() here
$(document).ready(function(){
// whatever you want here
});
</script>
Then you can call ready() adding your specific logic according to the output of your tests. This way ready will only fire once the above has loaded and executed.

All js functions need in .js file if I use the RequireJs?

I want to use RequireJs in my project, but I found that I can't write the following code
<html>
<head>
</head>
<body>
<input type="button" />
<script>
// Use the jQuery
$(function() {
//some code
}
)
</script>
<input />
<input />
// I had added the jQuery in required shim and jQuery is working in RequireJs.
<script data-main="scripts/main" src="/scripts/require.js"></script>
</body>
</html>
There was an error $ is undefined, when the page was loaded.
I looked up a lot articles, but I can't solve it. How can I handle this? I don't want to move the sample js function to .js file.
As you wrote in your question:
All js functions need in .js file if I use the requirejs?
And with the definition of RequireJS:
RequireJS is a JavaScript file and module loader.
Using a modular script loader like RequireJS will improve the speed and quality of your code.
So doing such inserting inline <script> tags in your page is not a good idea.
However, in answer to your question, because RequireJS load the scripts asynchronously, so you don't know when jQuery will load, and you can not use inline scripts as old schools, you need to use define or require methods as George Reith wrote in the answer.
First things first $ means nothing in JavaScript but is used by the popular jQuery library. JavaScript !== jQuery.
Secondly assuming you have loaded jQuery via require.js you need to put your initial script tag after
<script data-main="scripts/main" src="/scripts/require.js"></script> as it is being called before require.js.
Thirdly require.js asynchronously loads files so you must wrap your code in the require() or define() tag with a list of dependancies so it only calls them once they have been loaded.
e.g.
<html>
<head>
<script data-main="scripts/main" src="/scripts/require.js"></script>
</head>
<body>
<input type="button" />
<script>
/*
RequireJS is asynchronous so you must wrap your code
in "require(["jQuery"], ...)" so it only calls it once
jQuery has been loaded. Each included script is available
to you as a parameter in the callback function.
*/
require(["jQuery"], function($) {
$(function() {
});
});
</script>
<input />
<input />
</body>
</html>
Your settings should look like this:
requirejs.config({
paths: {
'jQuery': 'path/to/jquery'
},
shim: {
'jQuery': {
exports: '$'
}
}
});
You also have to include jQuery. There is a whole manual page devoted to this on requirejs.org which should help you out.
Maybe what you want is also explained here. Taken from there:
require(["helper/util"], function(util) {
//This function is called when scripts/helper/util.js is loaded.
//If util.js calls define(), then this function is not fired until
//util's dependencies have loaded, and the util argument will hold
//the module value for "helper/util".
});
Require.js doesn't even implement $. Why are you even wrapping you function in $(..)?
Try moving your sample script tag after the requirejs script tag. Currently your sample function is executed before requirejs gets a chance to load jQuery.

using getScript to import plugin on page using multiple versions of jQuery

I am developing an app on a page that uses jQuery 1.2.6, but I would like to use jQuery 1.4.2 for my app. I really don't like to use multiple versions of jQuery like this but the copy on the page (1.2.6) is something I have no control over. I decided to isolate my code like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<script type="text/javascript" src="jquery-1.2.6.min.js>
<script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="myStuff.js"></script>
</div>
</body></html>
The file myStuff.js has my own code that is supposed to use jQuery 1.4.2, and it looks like this:
(function($) { //wrap everything in function to add ability to use $ var with noConflict
var jQuery = $;
//my code
})(jQuery.noConflict(true));
This is an extremely simplified version, but I hope you get the idea of what I did. For a while, everything worked fine. However, I decided to use a jQuery plugin in a separate file. I tested it and it acted funny. After some experimentation, I found out that the plugin was using the old version of jQuery, when I wanted it to use the new version. Does anyone know how to import and run a js file from the context within the function wrapping the code in myStuff.js?
In case this matters to anyone, here is how I know the plugin is using the old version, and what I did to try to solve the problem: I made a file called test.js, consisting of this line:
alert($.fn.jquery);
I tried referencing the file in a script tag the way external Javascript is usually included, below myStuff.js, and it came up as 1.2.6, like I expected. I then got rid of that script tag and put this line in myStuff.js:
$.getScript("test.js");
and it still came back as 1.2.6. That wasn't a big surprise -- according to jQuery's documentation, scripts included that way are executed in the global context. I then tried doing this instead:
var testFn = $.proxy($.getScript, this);
testFn("test.js");
and it still came back as 1.2.6. After some tinkering, I found out that the "this" keyword referred to the window, which I assume means the global context. I am looking for something to put in place of "this" to refer to the context of the enclosing function, or some other way to make the code in the file run from the enclosing function. I noticed that if I copy and paste the code, it works fine, but it is a big plugin that is used in many places, and I would prefer not to clutter up my file with their code. I am out of ideas. Does anyone else know how to do this?
When you load jQuery, all it does is to create a root jQuery object and set window.jQuery and window.$ to point to it. So you can simply load the old jQuery, copy window.jQuery to window.jQuery126, load the new jQuery, copy window.jQuery to window.jQuery142, and then change window.jQuery and window.$ whenever you want a plugin to use the other version.
This is an ugly and unstable hack but it should work as long as
all code written for the non-default version is encapsulated with (function($){...})($) (proper jQuery plugins should do this, and you can easily ensure it for your own code)
scripts used with different jQuery versions don't mess with each other's stuff (such as one binding an event handler and the other trying to unbind it)
Another, simpler but less maintainable solution is to simply edit the plugin to look like (function($){...})(jQuery142) instead of (function($){...})(jQuery)
Versions
There is a script that specifically attempts to fix this problem: Versions . It's rather old, though.
It's just a neat helper for doing the switching of versions.
While I have not tested this script myself, you can do something like this based on the GitHub repository for the project:
<!-- Old jQuery and it's plugins -->
<script type="text/javascript" src="../jquery/jquery-1.2.6.js"></script>
<script type="text/javascript" src="test-plugin-for-old.js"></script>
<!-- Include the Versions helper -->
<script type="text/javascript" src="versions.js"></script>
<!-- Include a new jQuery -->
<script type="text/javascript" src="../jquery/jquery.js"></script>
<script type="text/javascript">
Versions.add('jquery', 'latest', jQuery.noConflict(true));
Versions.add('jquery', 'default', jQuery);
</script>
<!-- Load a plugin into the new jQuery -->
<script type="text/javascript">jQuery = Versions.use('jquery', 'latest');</script>
<!-- Do whatever you need with the new jQuery -->
<script type="text/javascript" src="test-plugin-for-new.js"></script>
<!-- Finish up and use the old jQuery back -->
<script type="text/javascript">jQuery = Versions.use('jquery', 'default');</script>
On-Demand JavaScript Loading (Lazy Loading)
With that out of the way, there are some ways to do on-demand JavaScript loading, but I don't think they will work well with loading of jQuery since jQuery modifies and requires the presence of the window object.
Also, you might want to read about script loading. There's more details about it in this StackOverflow question and the article pointed out.
RequireJS
In the list, RequireJS is not mentioned. It's rather new and you can do things like:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script>
<script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
<script type="text/javascript" src="require.js"></script>
<script type="text/javascript">
require({context: "1.4.2"},
["http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"],
function() {
console.log($.fn.jquery); // returns 1.4.2
// myStuff.js
});
require({context: "1.2.6"},
["http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"],
function() {
console.log($.fn.jquery); // returns 1.2.6
});
</script>
</div>
</body></html>
I always go for the newest stuff, haha, so I'm recommending this. However, due to the nature of loading the jquery (it modifies window as mentioned above), all references to $ and jQuery outside and beyond the last require in the HTML code block above, will refer to the jQuery 1.2.6.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" />
<script type="text/javascript">
$new = $.noConflict();
document.write("$new = " + $new.fn.jquery + "<br/>");
document.write("$ = " + $.fn.jquery + "<br/>");
</script>
I just tried this and it seems to work, $ reports to be the old version and you just have to make sure to use $new when invoking jquery for the stuff you want to do with 1.4.2
jQuery is actually a variable in the window context. So whenever you load a jQuery library it will create that variable in the window context if you load it outside any function.
I believe you could do something like this to achieve what you want. Although somewhat restrictive, theoretically it should work:
<script type="text/javascript">
// Get new jQuery code
$.get( "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", function (data, textStatus, XMLHttpRequest){
if(data){
// data should contain the file content. eval() it
eval(data);
// Use jQuery 1.4.2 from here, only inside this callback function.
}
}, "html" );
</script>
This is ugly, but should do the trick.
For now, I am going along with Tgr's solution. Here are the details of how I implemented it:
page.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<script type="text/javascript" src="jquery-1.2.6.min.js>
<script type="text/javascript" src="pageStuff.js"></script>
</head>
<body>
Welcome to our page.
<div id="app">
Here is our app.
<script type="text/javascript">
var oldJQuery = $;
</script>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="myStuff.js"></script>
</div>
</body></html>
myStuff.js:
var jq142 = jQuery.noConflict(true);
(function($) {
var jQuery = $;
$(function() {
//init app stuff
includeScript("jCarousel.js", function() {
//init carousel stuff
});
});
})(jq142);
function includeScript(URL, callback) {
window.$ = window.jQuery = jq142;
window.$.ajax({
url: URL,
dataType: "script",
error: function() {
window.$ = window.jQuery = oldJQuery;
},
success: function() {
if (typeof callback != "undefined")
callback();
window.$ = window.jQuery = oldJQuery;
},
async: false
});
}
I still don't like the idea of putting another variable (jq142) into the global namespace, but I couldn't think of any reasonable way around it. If I come up with something better, I will post it here.

Categories