Transition page with jQuery - javascript

I use Jquery script Barba to make fluid and smooth transitions between my pages.
I have Jquery scripts in my website. The most of my js functions are in a file named main.js.
To make my plugins works with Barba.js I use the Views methods.
So I put all my jQuery functions in my main.js like this :
var Homepage = Barba.BaseView.extend({
namespace: 'homepage',
onEnter: function() {
// Here's they are my jQuery functions.
},
});
Homepage.init();
Barba.Pjax.start();
It works for these jQuery functions.
The problem is that I have some other jQuery functions in two other pages : index.phpand single.php. I have no more choice to put them in these pages because these Jquery functions contain php code.
So I put the other jQuery functions in my index.php and single.php like this :
<script type="text/javascript" src="main.js"></script>
// Here's they are my html code.
<script type="text/javascript">
var Homepage = Barba.BaseView.extend({
namespace: 'homepage',
onEnter: function() {
// Here's they are my jQuery functions.
},
});
Homepage.init();
</script>
It doesn't works for these jQuery functions which are in my index.php and single.php. I can't see them in my pages. Like they don't exist.
Why and how to fix it ?

Related

How can I make a call to an api that was loaded globally while I am inside requirejs?

I inherited a project that is using magento and foundation. I incorporated requirejs and backbone on top of this and I am trying to get a foundation orbit gallery working that is being loaded into the dom via hogan (render) in backbone.
The problem I am having is that foundation is already being loaded globally in one of the magento templates and when I render the slides in requirejs, the orbit gallery has already been built so it is not displaying the slide indicators.
Basically, I need to be able to call $(document).foundation(); from inside my backbone view in order to re-initialize the orbit container somehow whenever I change the slides.
Here is what is being loaded at the bottom of the dom from magento,
<script type="text/javascript" src="skin/frontend/package/theme/js/foundation/foundation.min.js"></script>
<script type="text/javascript" src="skin/frontend/package/theme/js/foundation/foundation.interchange.js"></script>
<script type="text/javascript" src="skin/frontend/package/theme/js/foundation/foundation.orbit.js"></script>
<script type="text/javascript" src="skin/frontend/package/theme/js/foundation/foundation.topbar.js"></script>
<script type="text/javascript" src="skin/frontend/package/theme/js/foundation/foundation.reveal.js"></script>
Here is the gist of my requirejs view and what I am trying to accomplish
define([
'generics/genericView',
'foundation',
'text!carousel.tpl'
], function(
GenericView,
foundation,
visualCarouselTpl
) {
return GenericView.extend({
'el': 'html',
'events': {
},
render: function() {
var rederedTpl = Hogan.compile(visualCarouselTpl).render({"myImages": imagePaths});
$(".my-carousel").prepend(rederedTpl);
$(document).foundation();
},
initialize: function (params) {
this.render();
return this;
},
});
});
And here is the template
<ul data-orbit>
{{#myImages}}
<li>
<a href="#">
<img src="{{src}}" alt="{{alt}}" />
</a>
</li>
{{/myImages}}
</ul>
In this particular example, I am requiring another copy of foundation in order for this module to see what "foundation" is when I call $(document).foundation();. This seems to create the carousel, but the indicators are not there I believe because the slides are being included after the carousel is rendered.
To sum up, I need to be able to do one of the following (preferably the first one)
Incorporate the global foundation api's into require and use it to re-initialize the obit gallery.
Require all of the same foundation files through require and re-initialize the orbit gallery that way. I however do not want to be loading the foundation libraries twice if possible, so I would need to figure out how to remove those from the dom first on this one. Though I guess I could load them twice if its just easier.
So far I have tried to call $(document).foundation(); both with and without it being incorporated into require. There is a javascript error when not including it into require (because it does not see foundation), and there is a javascript error of
When foundation is in require.
Here's a recreation of your problem using jquery.cookie, it's a small plugin that modifies the jQuery object also.
In this example, there is a Global jQuery added via <script>, this is version 2.2.4, and within the RequireJS configuration, there is another, which is 3.2.1. This way we can compare.
Run the code and see what happens.
var globaljQuery = jQuery;
require.config({
paths: {
"jquery-cookie": "//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min",
"jquery": "//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min"
}
});
require(['jquery-cookie'], function() {
console.log("Old Global jQuery Version: " + globaljQuery().jquery);
console.log("Old Global Cookie add-on exists: " + Boolean(globaljQuery.cookie));
console.log("New Global jQuery Version: " + jQuery().jquery);
console.log("New Global Cookie add-on exists: " + Boolean(jQuery.cookie));
});
<!-- Global jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.3/require.min.js"></script>
The plugin in this case, understands it is in an AMD environment and uses RequireJS to access jQuery. Now 2 jQuery objects have been created, and unfortunately only 1 modified to include the plugin.
In your case, you cannot remove the globals right now, but your solution should be to use the globals within the RequireJS context.
This can be done in 2 ways:
A) Create a module with this code:
define(function() { return jQuery; });
and then use your path config to point jquery there.
B) Slightly cleaner is to use the callback configuration option:
require.config({
callback: function() {
define('jquery', function() { return jQuery; });
},
...
See it in action:
var globaljQuery = jQuery;
require.config({
callback: function() {
define('jquery', function() { return jQuery; });
},
paths: {
"jquery-cookie": "//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min",
"jquery": "//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min"
}
});
require(['jquery-cookie', 'jquery'], function(cookiePlugin, requiredjQuery) {
console.log("Old and New Global jQuery equal?: " + (globaljQuery === jQuery));
console.log("Global and Required jQuery equal?: " + (jQuery === requiredjQuery));
});
<!-- Global jQuery -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.3/require.min.js"></script>

Loading elements with javascript then applying them javascript

I am trying to load "header.html" using jquery .load("file") function, apply css to the loaded elements (works) and then apply JS to the loaded elements, functions like floating menu on scroll, etc, this it not working however. This is the order I import the files in the head:
<!-- Elements going to be loaded are using this font-awesome css
so they must be loaded before anything -->
<link rel="stylesheet" href="awesome/css/font-awesome.min.css" />
<!-- Then importing the jquery -->
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<!-- This is the point where i load the header.html -->
<script src="js/indexLoad.js"></script>
<!-- Then apply css to the loaded elements (works) -->
<link rel="stylesheet" href="css/index.css" />
<!-- Then apply JS to the loaded elements (doesnt work) -->
<script src="js/index.js"></script>
Inside the header.html I import some elements like nav for example.
Then changing style to nav to display it in red.
When I use var newHeight = $("nav").position().top in the index.js I just get cannot read property value of null... Why did css apply styles to the loaded element and JS coudnt get em?
I properly use $(document).ready( function(){} in both .js files:
indexLoad.js
$(document).ready( function(){
$("header").load("http://localhost/js/header.html");
});
index.js
$(document).ready( function(){
var newHeight = $("nav").position().top;
});
ALWAYS first load all the CSS files, and then the JS scripts. Always.
And all the JS that accesses DOM elements needs to be loaded after the DOM is ready. Either by using one of the handlers (like $(document).ready) or simply putting the script at the very end of the HTML body. (not sure if you were doing that to all the scripts, you probably are)
Since you're using an AJAX call to load the header, you need to wait for it to load in order for the nav element to be available to JS. So use the load() callback function to execute everything that manipulates the header markup.
Key stuff: And since you're loading index.js and indexLoad.js separately, you actually need some kind of coordination between them. I suggest setting up an event listener in the index.js file, and firing that event in the indexLoad.js once the header is ready (in the load() callback). Something like this:
indexLoad.js
$(document).ready( function(){
$("header").load("http://localhost/js/header.html", function() {
$('body').trigger('headerReady');
});
});
index.js
$('body').on('headerReady', function(){
var newHeight = $("nav").position().top;
// everything else that requires header elements goes here
// or under a similar listener
});
Here is a simple snipper that mimics this using a timeout to simulate the async call delay:
setTimeout(function(){
$('body').append('<nav>Nav here</nav>');
$('body').trigger('headerReady'); // simulating a 3s delay
}, 3000);
$('body').on('headerReady', function() {
alert('header is ready');
$('nav').css('color', 'green');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
JS is asynchronous, and therefore even if the newHeight measurement is made further down the page, it does not mean that it will be executed/run after the loading has completed. Instead, use callbacks:
$(document).ready( function(){
$("header").load("http://localhost/js/header.html", function() {
var newHeight = $("nav").position().top;
});
});
... or deferred objects: Using jQuery load with promises

Modernizr.load()/yepnope : Error when loading JQuery before JS plugins

I'm using Modernizr to load all of my JS and CSS scripts in a specific order with callbacks functions to manage the dependences. But I meet a problem with the loading of Bootstrap witch need JQuery. I have 3 levels of loading :
1) JQuery lib
2) scripts using JQuery but not needing that the document is loaded
3) scripts using JQuery AND needing document loaded
I get the following error in Firbug :
TypeError: l is not a function bootstrap.min.js (ligne 4)
It seems that JQuery does not have time to load before Bootstrap.
Does anybody have an idea please? (to resolve this problem or to purpose another solution to make the same thing) Thanks for your help.
The code in head :
<script type="text/javascript" src="js/modernizr-2.6.1.min.js"></script>
<script type="text/javascript">
Modernizr.load([{
load: 'http://code.jquery.com/jquery-1.10.2.min.js',
complete: function(){
Modernizr.load([
//scripts using JQuery but not needing that the document is loaded
'bootstrap/js/bootstrap.min.js',
'js/plugins/respond/respond.min.js',
'js/plugins/jquery-ui/jquery-ui-1.8.23.custom.min.js',
'js/plugins/easing/jquery.easing.1.3.js',
'js/plugins/parallax/js/jquery.stellar.min.js'
]);
$(function(){
//scripts using JQuery AND needing document loaded
Modernizr.load([
{
test : Modernizr.touch,
yep : 'js/plugins/toucheeffect/toucheffects.js'
},{
test : $('.camera_wrap').length,
yep : {
'js':'js/plugins/camera/camera.min.js',
'css':'js/plugins/camera/css/camera.css'
},
complete : {
'js': function(){
$('.camera_wrap').camera();
console.log("plugin loaded!");
}
}
}
]);
});
}
}]);
</script>
[EDIT] alert(jQuery) at the beginning of the first callback function is OK so I don't understand why Bootrstarp don't run correctly...

How to wait until DOM has loaded before adding script tags to <head>?

I'm implementing this Developr theme from themeforest into a Meteor app.
I'm currently accomplishing this by placing the javascripts in question to /public and appending them using jQuery:
Meteor.startup(function() {
$('head').append('<script src="/template_stuff.js"></script>');
// .. all 7 scripts or so
});
If the required scripts are placed in /client/js/, it appears that they either run too early or before the DOM is done loading. If they are placed directly in the header of the main html file, they seem to bug out the same way.
Am I missing something here - is there a more elegant way to make the scripts load after DOM has loaded?
There are several methods for waiting until the DOM has loaded to inject your scripts:
Meteor.startup (as you illustrated)
jQuery's document ready: $(function () { ... })
script tag at the bottom of your layout template
Regarding elegance, I use a handlebars helper as it allows me to consolidate all 'after body' code in one place. Then use jQuery's document ready as needed.
For example,
// in client/handlebars.js
Handlebars.registerHelper('afterBody', function(name, options) {
function isMobileSafari() {
return navigator.userAgent.match(/(iPod|iPhone|iPad)/) &&
navigator.userAgent.match(/AppleWebKit/)
}
if (isMobileSafari()) {
$(function () {
FastClick.attach(document.body)
})
}
//// load scripts however you want...
// $(function () {
// $.getScript as Daniel suggests
// $('body').append as you have
// pure js: document.createElement('script')
// })
})
// in client/main.html (using mini-pages router)
<template name="layout_no_header">
{{{yield}}}
{{afterBody}}
</template>
<template name="layout">
{{> header}}
{{{yield}}}
{{afterBody}}
</template>
Use jQuery getScript()
(function ($) {
$.getScript("/template_stuff.js");
})(jQuery);
I think you might have a different problem. It sounds like the 3rd party code is being wrapped in a closure and is not working correctly. Try and place them inside the client/compatibility folder. This will prevent it from being wrapped in a closure, which can solve 3rd party problems. Be sure the load order inside of here is correct, it loads files in alphabetical order inside of a folder. (load order)
If that doesn't work, find out where the code is being executed and comment out the call. Then load your html inside of a template, even if it's just a 'page' template with all the html. Create a js file for the template and call the methods in the templates rendered callback.
// Execute this function when myPage template is rendered
Template.myPage.rendered = function() {
stuff.init();
stuff2.run();
};
Note, the to call stuff2, etc.. you'll likely need to have it's script in the compatibility folder so you can reach the namespaces from the template_stuff.js.

jQuery not working in external JavaScript

I am new to jQuery and am stuck at some strange issue. I am using jQuery's change and click methods. They are working fine when used in my HTML file in the <script> tag.
Like:
<script>
$("select,input").change(function ()
{
// My code and some alerts
});
</script>
When I copied the same in external JavaScript code without <script> and imported that in my HTML it was not at all working.
Are there any changes which are needed to use jQuery in external JavaScript code?
PS: Some other non-jQuery functions present in same external JavaScript code are successfully called from HTML.
First off, you don't want a <script> tag in an external JavaScript file, if that's how I'm reading your post.
The trick with jQuery is that your code is set to execute immediately.
You want to wrap your script so that it loads when the document is ready, in something like:
$(document).ready(function(){
$("select,input").change(function ()
{
// My code and some alerts
})
});
And you want to make sure that your file is loaded after jQuery (otherwise the $ global will not be set).
Additions:
Here is what your HTML should look like:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="jscript/myExternalJs.js"></script>
Here is what your JavaScript code should look like (note there is no script tag inside the JavaScript file):
$(document).ready(function(){
$("select,input").change(function ()
{
// My code and some alerts
})
// Other event handlers.
});
As far as your other script... it sort of depends on what you're doing. The most important thing is to not try to hook event listeners up to objects that don't yet exist, which is why we use document.ready.
Did you make sure jquery is defined before your own jquery code?
You should also make sure the DOM is ready when dealing with jquery:
$(document).ready(function() {
$("select,input").change(function() {
// my code and some alerts
});
// more code here if needed, etc.
});

Categories