I have a script from a third party, that I need implemented on my Nuxt site in the Header.
What would be the best way to insert a script such as this?
<script id="sleeknoteScript" type="text/javascript">
(function (){
var sleeknoteScriptTag=document.createElement("script");
sleeknoteScriptTag.type="text/javascript";
sleeknoteScriptTag.charset="utf-8";
sleeknoteScriptTag.src=("//sleeknotecustomerscripts.sleeknote.com/00000.js");
var s=document.getElementById("sleeknoteScript");
s.parentNode.insertBefore(sleeknoteScriptTag, s);
})(); </script>
<!-- End of Sleeknote signup and lead generation tool - www.sleeknote.com -->
Usually I would put scripts in Nuxt.config like this.
script: [
{ src: 'https://unpkg.com/#lottiefiles/lottie-player#0.2.0/dist/lottie-player.js' },
]
But this one I don't know.
You can do it in the same way, just place the script into a javascript file and use the path to that file as a script's src property value in the nuxt.config.js:
script: [
{ src: '/scripts/myScript.js' },
]
The myScript.js would be placed in static/scripts/myScript.js in this case
Related
I want to include 3rd party libraries, such as jQuery, from CDN. I also want to create a fallback so if the CDN fails, I include my own local copy. I have followed the suggestion here:
This is how I include jQuery in my page:
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="/Scripts/jquery-3.3.1.min.js"><\/script>');</script>
At the same time Google is saying that document.write() is unreliable and should not be used:
Using document.write() can delay the display of page content by tens
of seconds and is particularly problematic for users on slow
connections. Chrome therefore blocks the execution of document.write()
in many cases, meaning you can't rely on it.
Is there any alternative method to create fallback for the CDNs?
If you don't mind loading it asynchronously you can do it like this:
function fallback() {
var element = document.createElement('script');
element.type = 'text/javascript';
element.src = 'https://code.jquery.com/jquery-3.3.1.min.js'; // or your path to your local script
document.body.appendChild(element);
}
window.jQuery || fallback();
setTimeout(function() {
console.log(window.jQuery);
}, 1000); // Add timeout since script is loaded asynchronously
I recommend using 3p packages like fallback.js or require.js given they are more scalable in case you have multiple fallbacks and they give you faster loading performance.
Example of fallback.js
HTML CODE
<html>
<head>
<!-- **The `data-main` attribute tells the library to load `main.js`** -->
<script async data-main="main" src="fallback.min.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
MAIN JS FILE
cfg({
"libs": {
"jQuery": {
"urls": [
"//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min",
"//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min"
]
},
}
});
req(function(jQuery) {
jQuery("body");
});
Example of require.js
requirejs.config({
enforceDefine: true,
paths: {
jquery: [
'https://code.jquery.com/jquery-3.4.1.min.js',
//If the CDN location fails, load from this location
'js/jquery-3.4.1.min.js'
]
}
});
require(['jquery'], function ($) {});
In yii2 I have put all my js code in 1 file using yii2-assets-auto-compress plugin, including jQuery lib. Loading this file is async to speed up page load. But, if there are forms on the page, yii adds yiiActiveForm() at the end of </body>. So, the error is jQuery is not defined.
How to manage this problem? Firstly, I can make call yiiActiveForm() manually from script.js, but how to turn it off automatically load at the end of the body? Generally, that's not convenient, because there might be other scripts that append js code. Maybe someone knows how append js code with this yii2-assets-auto-compress plugin?
<script src="/assets/js-compress/script.js?" async="async"></script>
<script type="text/javascript">
jQuery(document).ready(function () {
jQuery('#w0').yiiActiveForm([],[]);
});
</script>
</body>
async downloads the file during HTML parsing and will pause the HTML parser to execute it when it has finished downloading.
You should either load Jquery outside your compressed scripts inside the head.
Or load the script inside the <head> of the document means inside the layout file either using script tags
<script type="text/javascript" src="/path/to/compressed.js" async="async"></script>
or using
<?php $this->registerJsFile('/path/to/compressed.js',['aync'=>'aync'])?>
if you are using AssetManager to load the script file
Then load it like this
public $js = [
['js/compressed.js','async'=>'async','position' => yii\web\View::POS_HEAD],
];
Also, you should configure the asset manager to not load the core script jquery so that it does not load jquery twice.
'assetManager' => [
'bundles' => [
'yii\web\JqueryAsset' => [
'sourcePath' => null,
'js'=>[]
],
],
],
HERE is a good read.
I want some of my scripts in my index.html page to run only on condition.
For example on specific version of IOS i want that the scripts after general.js not to run.
<script src="general.js"></script>
// stop here on condition
<script src="vendor/jquery/dist/jquery.js"></script>
<script src="vendor/angularjs/angular.js"></script>
<script src="vendor/angular-sanitize/angular-sanitize.js"></script>
<script src="vendor/angular-ui-select/dist/select.js"></script>
How can i do this?
RequireJS?
Why don't you use something like RequireJS. Have your main bootstrap script (your general.js) load all other scripts that depend on your condition.
You can't do that. Instead, insert the first general.js script as you would normally, and in your head, put a script that adds the files:
<script>
var scripts = ['vendor/jquery/dist/jquery.js', 'vendor/angularjs/angular.js',
'vendor/angular-sanitize/angular-sanitize.js', 'vendor/angular-ui-select/dist/select.js'];
if(condition) {
for(i=0;i<scripts.length;i++) {
$('head').append("<script src='"+scripts[i]+"'></script>");
}
}
</script>
Or in vanilla JS:
<script>
var scripts = ['vendor/jquery/dist/jquery.js', 'vendor/angularjs/angular.js',
'vendor/angular-sanitize/angular-sanitize.js', 'vendor/angular-ui-select/dist/select.js'];
if(condition) {
for(i=0;i<scripts.length;i++) {
script=document.createElement('script');
script.src=scripts[i];
document.getElementsByTagName('head')[0].appendChild(script);
}
}
</script>
This creates an array of the new script directories and names, and loops through them, adding them to the head of the document dynamically.
I know this has already been discussed, but after searching for a while I can't figure out why my small setup does not load jquery correctly with requireJS.
I'm running a small sample html page from 'file://' and try to load 2 modules with a call to require:
jquery
a custom module I wrote
If my custom module loads correctly (i can use it with its alias in the require call, jquery is always undefined)
I tried to setup paths in require.config, as well as shim (exporting '$' or 'jQuery') but it does not work.
The only way i can get jquery to correctly load, is removing all paths definition and naming the jquery file on my filesystem 'jquery.js'
Here is my config:
main.js:
require.config({
baseUrl: 'scripts',
paths: {
jquery: 'jquery-2.1.3.min' //does not work
//jquery: 'http://code.jquery.com/jquery-2.1.3.min.js' //does not work either
}
});
console.log( "main.js is loaded" ); //this is correctly ouputed to the console
test.html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<!--
... page content ...
-->
<!-- main.js is loaded from data-main -->
<script data-main="scripts/main" src="scripts/require.js"></script>
<script type='text/javascript'>
require(
['jquery','custom'],
function($, Custom){
console.info('$:');
console.info($); //outputs undefined
console.info('Custom:');
console.info(Custom); //outputs my custom object
});
</script>
</body>
</html>
Once again, it works if I remove all paths definition for jquery, and simply name my jquery js file 'jquery.js' but this is sloppy.
Can somebody points me on the right way to go ?
The problem is that you load your RequireJS configuration, which is in main, through data-main. The data-main attribute merely tells RequireJS to load the module listed there but the loading is still asynchronous, so main may load after RequireJS tries to load jQuery. When this happens, RequireJS fails to find jQuery and $ is undefined. (Incidentally, I'd suggest setting enforceDefine to true in your RequireJS configuration so that you get an error message telling you when a module has not loaded. That's a better clue than having an undefined symbol.)
One solution would be to move your configuration outside of main. So you remove it from main and add it to a script element in front of the one loading RequireJS:
<script>
// RequireJS will use the value of `require` as its configuration.
require = {
baseUrl: 'scripts',
paths: {
jquery: 'jquery-2.1.3.min'
},
enforceDefine: true
};
</script>
<script src="scripts/require.js"></script>
Or you can nest require calls to force main to load before any other module:
require(['main'], function () {
require(['jquery','custom'], ...
});
I'm attempting to get a gruntfile working to concatenate / uglify javascript files in a Laravel application. All of my tasks work in isolation, but for whatever reason the paths to my input javascript files are not being set correctly.
Here's an example of one of my blade templates:
#section('scripts')
<!-- build:js /js/min/page.min.js -->
<script type="text/javascript" src="/js/scrollIt.min.js"></script>
<script type="text/javascript" src="/js/jquery.omniwindow.js"></script>
<script type="text/javascript" src="/js/isotope.min.js"></script>
<!-- endbuild -->
#stop
Here's my useminPrepare / usemin task definitions:
useminPrepare: {
html: 'app/views/**/*.blade.php',
options: {
dest: 'app/views/dist'
}
},
usemin: {
options: {
assetDirs: [ 'public/js' ]
},
html: [ 'app/views/dist/**/*.blade.php' ]
},
I have no defined uglify task, I'm just relying on the one that usemin will generate.
All templates are making it into the 'app/views/dist' directory correctly, with the correct replacement (in the example above, there's a single javascript file at public/js/min/page.min.js being included in the template). During processing, I noticed output:
$ grunt build
Running "useminPrepare:html" (useminPrepare) task
Going through {list of templates} to update the config
Looking for build script HTML comment blocks
Configuration is now:
concat:
{ generated:
{ files:
[ { dest: '.tmp/concat/js/min/page.min.js',
src:
[ 'app/views/course/js/scrollIt.min.js',
'app/views/course/js/jquery.omniwindow.js',
'app/views/course/js/isotope.min.js' ] },
] } }
uglify:
{ generated:
{ files:
[ { dest: 'app/views/dist/js/min/page.min.js',
src: [ '.tmp/concat/js/min/page.min.js' ] },
] } }
cssmin:
{}
As you can see above, it is looking for my javascript files in app/views/course/js directory, which is incorrect. Why is this? I thought specifying assetDirs: ['public/js'] in my usemin task would tell grunt where to find those files. I have tried changing the script references to look like this:
<script type="text/javascript" src="../../../public/js/scrollIt.min.js"></script>
And this causes a successful build, but breaks my local development so its definitely not a solution. Do I need to somehow override the uglify:generated task, and if so, how do I do it for multiple different templates with generated filenames?
If it's necessary, you can see the entirety of my Gruntfile.js here. You can see from there I had to also add a new copy task for copying Javascript files from app/views/dist/js/min back over to public/js/min. I'd also like to get rid of that, but if I can just get around this issue I'd be happy.
The answer here actually turned out to be relatively simple, and was able to be gathered directly from the usemin documentation (as soon as I started to look hard enough):
Blocks are expressed as:
<!-- build:<type>(alternate search path) <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->
In my case for working with Laravel, I needed to specify an alternate search path of public/ and it wound up working just fine:
#section('scripts')
<!-- build:js(public/) /js/min/script.min.js -->
<script type="text/javascript" src="/js/script1.js"></script>
<script type="text/javascript" src="/js/script2.js"></script>
<script type="text/javascript" src="/js/script3.js"></script>
<script type="text/javascript" src="/js/script4.js"></script>
<!-- endbuid -->
#stop