Trying to avoid multiple calls to jQuery in a Domino XPage - javascript

I am attempting to use the 'DataTables' table plug-in for jQuery on a simple Domino XPage.
I have loaded the two required libraries from CDN's...
JQuery: ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js
DataTables: cdn.datatables.net/1.10.13/css/jquery.dataTables.min.css
I have also tried loading them from local resources (doesn't help).
I then prepare a basic table on my XPage, and include the necessary Javascript to initialise the table...
$(document).ready(function() {
    $('#tableID').DataTable();
} );
When I test the XPage, I continually observe
test.xsp:15 Uncaught TypeError: $(...).DataTable is not a function
I've searched through several forums, and the general consensus is that...
a) I have loaded the libraries in the wrong order (nope!)
b) I have loaded jQuery more than once (how?)
I have many other solutions using Bootstrap and jQuery, and have never run into this issue before. So, I though I might strip the XPage back to bare bones. I got rid of all Dojo elements on the page by adding the following line to the 'xp.properties' file...
xsp.client.script.libraries=none
That actually seemed to work! I no longer observed the error. However, my page no longer looked like it should (for obvious reasons!). I've had to restore the 'xp.properties' file back to its original state, but cannot find out how to avoid the error.
Has anyone successfully used the 'DataTables' jQuery plug-in on an XPage? Any feedback or suggestions would be most appreciated!

Yes I have been doing a load of work on DataTables in XPages so it definitely works! I know your pain though....
The order of your jquery scripts in relation to each other may be okay, however there is a clash with dojo and it's AMD loader, so you have 3 options.
Option 1. Load your jquery scripts before any of the xpages scripts
Option 2. remove the 'amd loader' just before your jquery scripts and then restore it just after
Option 3. modify the javascript of the datatables so it ignores the amd problem
Option 1 : Loading your jQuery scripts first
If you are using resource aggregation, you can use this tip from Sven Hasselbach's blog, in which you use the generic 'headTag' resource tag and it will load first.
http://hasselba.ch/blog/?p=1181
If you want a solution that will work regardless of resource aggregation setting, I have an example on my blog in which you can create a viewRootRenderer which will then allow you to specify that you want a script loaded BEFORE everything else
http://camerongregor.com/2016/09/19/controlling-the-order-of-script-resources-e-g-jquery-with-a-custom-viewrootrenderer/
Option 2. Removing the AMD loader before loading scripts
There is an xsnippet which explains how to remove and then restore the amd loader so that a jquery plugin will load
https://openntf.org/xsnippets.nsf/snippet.xsp?id=hack-to-use-jquery-amd-widgets-and-dojo-together
Sven had already made a similar solution to mine above (viewRootRenderer) in which you can specify which scripts will need the amd loader disabled and it will do this for you, it is available here
http://hasselba.ch/blog/?p=2070
Option 3 : modify javascript of the jquery plugin (datatables)
Mark Roden demonstrated this on his blog. I don't really like doing it but hey it works!
https://xomino.com/category/jquery-in-xpages/
Let me know if any of this works! I hope I'm right, with javascript I never know...

Related

How to reduce JavaScript Files in Magento?

I am new to Magento but work in webdev for several years now.
My goal is to optimise an existing Magento installation in terms of speed.
Looking at all the JS and CSS files used within this installation the first thing I aim for is to combine those file or better reduce the number of modules used. I am aware of the "combine files" function within the config menu, but that does lead to conflicts between jQuery and prototype which is why I am trying to first get an understanding of what types of frameworks/modules etc are used.
This is a list of all JS-files required by the homepage of this installation:
jquery-1.12.3.min.js
prototype.js
ccard.js
validation.js
builder.js
effects.js
dragdrop.js
controls.js
slider.js
js.js
form.js
script.js
menu.js
translate.js
cookies.js
func.js
jquery.easing.1.3.min.js
efects.js
jquery-1.11.0.min.js
jquery-migrate-1.2.1.min.js
jquery.noconflict.js
swiper.min.js
jquery.easing.js
jquery.scrollTo.min.js
jquery.global.js
remodal.min.js
jquery.themepunch.tools.min.js
jquery.themepunch.revolution.min.js
easyzoom.js
ios-orientationchange-fix.js
jquery.swipebox.min.js
jquery.themepunch.plugins.min.js
jquery.themepunch.revolution.js
jquery.slider.js
jquery.selectbox.js
jquery.bxslider.min.js
jquery.tweet.js
cookieconsent.min.js
gtm.js?id=GTM-5W7V6F
analytics.js
ec.js
What would be the best approach to clean up this list in order to keep functionality while reducing request and load?
For starters i see that you load 2 versions of jQuery
jquery-1.12.3.min.js and jquery.easing.1.3.min.js
What i did was combine the javascript files with the config settings like you said and use the jQuery.noConflict() https://api.jquery.com/jquery.noconflict/. Don't use the $ (dollar) sign to use jQuery but write it fully because prototype also uses it and it creates problems sometimes. There will be some problems which you should try to fix. Sometimes it's just adding a ; to the end of the file or function.
I then tried to figure out what code was needed and what wasn't so i could remove some of it.
Magento Inbuilt provide this things
Login admin panel
goto System->configuration->Advanced->Developer->JavaScript Settings and set Merge JavaScript Files to yes
You can do same for css and you will see very few request in your web page

How do you use a page's existing jQuery + Twitter Bootstrap/plugins with StealJS?

I have a project that uses Twitter Bootstrap 3, however, I am supplementing the existing javascript situation with a CanJS app. For CanJS dependency management I chose their package StealJS. However, it appears that no matter what I do, StealJS insists on loading jQuery again, overwriting $.fn, of course.
In this question a core contributor answers that the solution is to "steal" a blank.js file. However, this breaks steal/build for production as can/util/jquery/jquery.js is passed 'jquery' as undefined (the results of blank.js).
I have tried variations on StealJS's stealconfig.js settings including map, paths, and completed but nothing seems to work.
Here is an example of doing this in RequireJS. Is the solution simply not to use StealJS and to use RequireJS instead?
You can try a solution that is similar to the RequieJS solution you linked to. That is, create a dummy file that looks like this:
steal(function(){
return window.jQuery;
});
And in stealconfig.js map jquery to wherever you put this file.

Check jQuery version and load a newer version

I have various web pages that have varying versions of jQuery included on them ranging from 1.4.2 upwards (yes, I know, it's a mess). I want to use the jQuery validation plugin on these pages but it requires jQuery 1.6.4+.
I know I can check the version of jQuery loaded and then load in a newer version if necessary but I'm unsure on how to reference them individually so the pre-existing JavaScript/jQuery code that's on the site can still use $ (as I know this works quite happily and I don't want to break it) and then the new plugin can use something else?
Any help or suggestions on a better way to do this would be greatly appreciated. Thanks.
Bad idea to do what you are doing.
If you really insist on having different jquery versions, you can always write some sort of a script manager. Basically you specify in your page's "config" what jquery versions are required on this page and the manager will load the appropriate one.
Something like:
// each page content before everything else
Manager.reguire("plugin 1", "1.4.7");
Manager.require("plugin 2", "1.4.4");
// Main layout <head section>
Manager.LoadRequiredVersions();
And the manager would just request the files for you, but don't forget that you might have to do some clever no-conflict stuff with jQuery if you want more than one on a single page. https://stackoverflow.com/a/1566644/486780
If it's one version per page then a manager would be the easiest option.
original version of jquery loads (Version1)
$ and jQuery belong to version1
second version of jquery loads (Verion2)
now $ and jQuery belong to Version2, and _$ and _jQuery that belongs to Version1
assign the Version2 version to a var ($v2 = jQuery.noConflict(true);)
now $ and jQuery belong to Version1, _$ and _jQuery are probably null, and $v2 is Version2

How to use javascript in Silverstripe CMS?

I'm using SilverStripe 3.0 CMS, and I need to include a Google Map into the CMS.
I'm following this steps, and besides it's a little bit old, the official documentation uses the same methods in the current version of SilverStripe (At least it seems to be the current version documentation).
The issue is in this part of the code:
Behaviour.register({
"#Form_EditForm" : {
initialize : function() {
this.observeMethod("PageLoaded", this.adminPageHandler);
this.adminPageHandler();
},
adminPageHandler : function() {
initialize();
}
}
});
First of all, Behaviour was not defined. I needed to include manually the behaviour.js file that comes within the framework. But now, I get a Type Error:
this.observeMethod is not a function
Can someone give me a hint of what can I do in order to call a javascript function when a page editor is opened in the SilverStripe CMS?
the 'Behaviour.register' call you mention is definitly deprecated and no longer available in the core code, so the docs need an update here.
unfortunately, i couldn't find a documented way to replace this behaviour, but for now the following should work for you, based on the approach in the forum post you mentioned first hand:
find the 'initGoogleMaps.js' script added here:
function getCMSFields() {
Requirements::javascript('mysite/javascript/initGoogleMaps.js');
...
inside this script, remove the Behaviour.register... block, and move the initialize function outside document.ready (or simply remove the document.ready part), so initialize is globally available (you might consider renaming it).
then, add the following inside getCMSFields:
$fields->addFieldToTab('Root.Content', new LiteralField('js', '<script>initialize();</script>'));
this will ensure the initialize function is called every time a page's 'edit view' is rendered inside the cms.
hth
As mentioned by ben,
LeftAndMain::require_javascript('mysite/javascript/initGoogleMaps.js')
is more reliable than 'include-it when needed'. Why?
Because Silverstripe uses Ajax, it is better to load any javascript or css on the first load, so that they are ready when you go to different model admin areas within the CMS in ajax-powered environment. Not loading at the start causes inconsistency and your js, css files will not be loaded when you don't hard-load that admin area.
From documentation: http://doc.silverstripe.org/framework/en/reference/requirements and http://api.silverstripe.org/3.0/class-LeftAndMain.html
The whole "include it when you need it" thing shows some weaknesses in
areas such as the CMS, where Ajax is used to load in large pieces of
the application, which potentially require more CSS and JavaScript to
be included. At this stage, the only workaround is to ensure that
everything you might need is included on the first page-load.
One idea is to mention the CSS and JavaScript which should be included
in the header of the Ajax response, so that the client can load up
those scripts and stylesheets upon completion of the Ajax request.
This could be coded quite cleanly, but for best results we'd want to
extend prototype.js with our own changes to their Ajax system, so that
every script had consistent support for this.
By the way, the ideal place for this line is _config.php in your custom module or in mysite, depending on your needs.
LeftAndMain::require_javascript('mysite/javascript/initGoogleMaps.js')
would work much better

Injecting JQuery Cross-Domain

Is it safe to inject JQuery's script using JsonP?
The installation of my web application is - adding a script to a customer's website (like google analytics). I was thinking of using JQuery on the customer's website, as part of my own injected script.
I was wondering, if there is some kind of risk?
The application needs to support any kind of website.
Thank you
Yaron
Its hard to tell what you are doing with your library, but it seems you are building some type of widget for use on multiple sites.
From here down has been updated after an enlightening comment from #K Prime caused me research exactly how you could include two copies of jQuery if needed:
It is generally bad to use jQuery if you are building a widget that will live on a site outside your control, and will be added to the site with a "copy this embed code and paste onto your site" type of functionality. (Of course jQuery widgets and plugins abound, but these are normally chosen and installed/implemented by developers not a generic "copy-n-paste" widget type implementation)
Probably the biggest reason (after realizing you can run two copies of jQuery on the same page) is the file size increase. Whether it is warranted will depend on your particular needs and function. Simple small widget = straight JS. Complex website front-end extension, then it probably is worth the file-size increase.
To include it properly (so you don't run into conflicts on their site) follow a workflow that looks something like this:
Dynamically add jQuery to their page using the Google APIs as mentioned on the other answers here.
Run var mywidget_jQuery = $.noConflict( true ); which will restore the original meaning of $ and restore the original meaning of window.jQuery.
Dynamically add your script file, but be sure to wrap the entire thing in a self executing anonymous function like this:
JS
(function($){
... Your code here ...
})(mywidget_jQuery);
Now, you can safely use $ inside your special function and all the jQuery features you want without issue.
Extra credit You could wrap steps 1 and 2 in an if statement that tests if window.jQuery is defined and if it, test if jQuery.fn.version is high enough to run your code. If either test fails, then run steps 1 and 2. If it passes, however, then just run var mywidget_jQuery = window.jQuery so the script you include in step 3 will still run.
You can add jQuery to a website by simply adding a <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.js" /> element.
However, make sure to call jQuery.noConflict() in case they use a different $ keyword.
If you're just after a reference to the library, why wouldn't you just link to the API hosted on Google Code?

Categories