Width giving a different result while/after loading the page - javascript

I am trying to set the margin-left of a specific div (let's call it: div1) to be:
-1 * $('.div2 canvas').width()/2
So I am using the following line of code to do that:
$('#div1').css('margin-left', -1 * $('.div2 canvas').width()/2);
Once the page is loaded the result it gives me is -150. However, if I run the same exact line of code in the Chrome console, it gives the right result: -360 since the total width of div2 is 720.
I tried adding:
$(window).load(function () { });
or
$('#div1').load(function () { });
or
$('.div2 canvas').load(function () { });
but that did not help.
My assumption is that the width of div2 is changing based on some sort of information that is being injected and that once the page is ready the total width of the div 720px (in this example) but I am not entirely sure how to run this line of code once the whole page has been loaded and everything has been injected.

$(window).load(function () { });
should have helped. You also might try
$(document).ready(function () { });
but if that doesn't help, you'll need to show us your page (or a demo containing the problem) and the code which injects things after that.

You'll want to wrap this code in a document ready callback.
$(document).ready(function () {
// Your code
}
This ensures that the html is loaded, however it does not care about loaded images, which is where .load comes in. If your div contains image tags, you'll need two callbacks.
$(document).ready(function () { // Ensures that your document is loaded
$('.div2 canvas').load(function () { // Ensures that the images within our tag are loaded
// Your code
}
}
If we do not enclose this second callback definition in document ready, the tag we're referring to $('.div2 canvas') will not exist, and thus no load callback will be bound.

Related

Do I have to use document ready for jQuery?

I have a script that I want to use, however, I don't know if I require to put document ready.
$(window).scroll(function(){
$(".hero-h1").css("opacity", 1 - $(window).scrollTop() / 250);
});
If position and run your script so that the elements it depends on already exist at the time it runs, no.
This is essentially the same question as whether someone needs to use
window.addEventListener('DOMContentLoaded', () => {
// all of the code
});
If, at the time your script runs, you try to select an element that isn't always present regardless - like a particular <div> on the page - for example
$('.mybutton').on('click', () => {
// ...
Then at the time that the above line runs, you need to make sure that .mybutton exists on the page.
This can be accomplished in a few ways. One of these ways is by wrapping the whole script in .ready (or, as is usually preferred nowadays, just a plain function):
$(() => {
$('.mybutton').on('click', () => {
// ...
Another way it can be accomplished is by putting your script after all the elements that it depends on in the HTML markup - for example
// lots of HTML code
<button class="mybutton">click</button>
<script src="myscript.js"><script>
</body>
If you put your script at the end of the body, all elements from the static page markup will exist in the DOM by then.
A third way is to give your script the defer attribute.
<script defer src="myscript.js"><script>
This will ensure that all static elements are loaded before the script runs.
For this particular case of yours, if all you do is add a scroll handler to the window, then there aren't any elements to wait for in order to attach the handler, so you may not need to use any of the approaches above.

Load a jquery event only after the preloader ends

My website is : https://365arts.me/
So it loads about 16mbs of pics(Yes I know, I'm stupid. I'll try to change it very soon, also if someone could tell me a way to reduce size of do something else(like dynamic loading only when needed, if something like that exists) I'd be very grateful).
I added a preloader for it using:
[html]:
<div class="spinner-wrapper">
<div class="spinner">
<div class="dot1"></div>
<div class="dot2"></div>
</div>
</div>
and corresponging [jquery]:
<script>
$(document).ready(function() {
//Preloader
$(window).on("load", function() {
preloaderFadeOutTime = 500;
function hidePreloader() {
var preloader = $('.spinner-wrapper');
preloader.fadeOut(preloaderFadeOutTime);
}
hidePreloader();
});
});</script>
this works well but the problem is I have a javascript code that comes and says Hi! but it runs only for 2.8 seconds. So if loading takes up more than that, It doesnt show up. Can someone please tell me how to make sure that it loads only exactly after loading is completed.
Thanks a ton.
Code for my website:
https://github.com/richidubey/365-Days-Of-Art/blob/master/index.html
this may work
document.addEventListener('DOMContentLoaded', function() {
// your code here
}, false);
if you are happy with pure javascript
My first suggestion is to just get rid of the "Hi!" message since you already have a splash page in the form of the loader. But if you really want that second splash page, you can use the JQuery when() method:
$(window).on("load", function() {
$.when($('.spinner-wrapper').fadeOut(500)).then(displaySplashPage);
});
This assumes that displaySplashPage() is your function for showing the "Hi!" message.
You don't need $(document).ready() and window.on("load") here. Document ready waits for the HTML to be built, then applies event listeners/functions/etc to the structure. Window onload waits for everything to get loaded, then fires. In your case, you're trying to wait for all your pictures to load, so you only need onload.
You might need to have a container around all your main content set to opacity: 0 that switches to opacity: 1 as part of displaySplashPage(). That would prevent things from leaking through as you do the .fadeOut() on the loader.
JavaScript version - run js code when everything is loaded + rendered
window.onload = function() {
alert("page is loaded and rendered");
};
jQuery version (if you need it instead pure JS)
$(window).on('load', function() {
alert("page is loaded and rendered");
});
You can try this:
<script>
// Preloader
$(window).on("load", function() {
fadeOutTime = 500;
sayHelloDuration = 5000;
function hideSayHello() {
var sayHello = $('.say-hello');
sayHello.fadeOut(fadeOutTime);
}
function hidePreloader() {
var preloader = $('.spinner-wrapper');
preloader.fadeOut(fadeOutTime);
setTimeout(function() {
hideSayHello();
}, sayHelloDuration);
}
hidePreloader();
});
</script>
Also, remove the code from lines 83 ~ 87:
<script>
$(document).ready(function() {
$('.say-hello').delay(2800).fadeOut('slow');
});
</script>
About your website performance, you can improve a lot of things right now:
Use smaller thumbnail images on your front page, don't load FULL SIZE images at once. "work-showcase" section is really heavy without real necessity.
Try to incorporate src-set and smaller images for small screens, larger/heavier images for bigger screens. All modern browsers support it, and it will improve performance/loading speed.
Try to lazyload your big images, e.g. only when users scroll down to them, not before. It may take some work to integrate it with your image viewer, but it will additionally speed things up on initial load. My favorite library for this is this one: https://github.com/aFarkas/lazysizes but, you may find something else...
Unrelated to your original question, I have noticed that you have a bug in your HTML - see this screenshot. What kind of code editor do you use? Instead of empty space it apparently inserts invisible dots symbols which are not good. Actually, it's not the invisible dot (that's my editor's space indentation symbol), it's caused by 2 long dash (instead of short dash or minus) in your code after opening html comment tag:

Equal Height is not working .js file

I have a function that I wrote basically as below:
function getListHeight() {
$(".tur-list .col-lg-5 figure img").each(function() {
var getTurHeight = $(this).parents(".tur-list").find(".col-lg-7").outerHeight();
var getLeftHeight = $(this).parents("tur-list").find(".col-lg-5 figure img").outerHeight();
if (getTurHeight > getLeftHeight) {
$(this).outerHeight(getTurHeight);
}
});
}
to make equal my columns and it works as I wanted so there is nothing to here. my problem is this code is not working on my .js file but if I copy and paste it console my code is working so if you try you will see
Please click to my real demo
and copy getListHeight(); and paste it on console you will see my columns will be equal my question is why my code is not working properly in .js file ? what I have to do to work my code ?
and my getListHeight() function is work with $(window).resize when I resize the window or with click event but my function is not working in document.ready.
its not working because the images are not loaded yet, the image tag is there but the size is not set yet because the image is still being loaded.
i'd change the code to the following:
function matchSize() {
var getTurHeight = $(this).parents(".tur-list").find(".col-lg-7").outerHeight();
var getLeftHeight = $(this).parents("tur-list").find(".col-lg-5 figure img").outerHeight();
if (getTurHeight > getLeftHeight) {
$(this).outerHeight(getTurHeight);
}
}
function onResize() {
$(".tur-list .col-lg-5 figure img").each(matchSize);
}
function getListHeight() {
$(".tur-list .col-lg-5 figure img").load(matchSize);
}
$(document).ready(function(){
getListHeight();
$(document).on('resize', onResize)
onResize()
});
this will work on resize, on newly loaded images, and on previously loaded images before javascript kicks in (cached images probably).
here is a link to the codepen fork: https://codepen.io/Bamieh/pen/gRLPqm
P.S. i do recommend that you do not rely on the col-* classes as a selector, since the code will easily break as soon as you change your styles, using data-* attributes for selection is the way to go in my opinion.

Calling JQuery function from different context

This might be a very basic question but I'm trying to understand this behavior
This is my javascript code. I want to know why second call to foo does not work. Here is the JSFiddle link
$.fn.foo = function(somestring){
var $this = this;
$this.html(somestring);
}
$(function(){
$('#container').foo("within function"); //this works
});
$('#container').foo("outside"); //this does not
The DOM is not fully loaded .. Thats the reason it won't work..
So when you encase your code inside the DOM Ready handler it waits for the document to be loaded and then runs the code inside.
This makes sure the element is available before any code is run on it..
When the HTML document is parsed , it parses top down.
So if the script is included in the head section , then the scripts are loaded first and then the HTML structure.. When you try to the run the code , it obviously won't work cause the element was still not parsed..
So encasing that in the handler will make sure the element is available before calling the methods on them..
This is because $('#container').foo("outside"); is evaluated before the body is processed. $('#container') will return with a length of 0. This is demonstrated below.
$.fn.foo = function(somestring){
var $this = this;
$this.html(somestring);
}
$(function(){
$('#container').foo("within function");
});
var element = $('#container');
console.log(element.length); //prints 0
element.foo("outside");
If the script is at the beginning of the page the rest of the HTML document has not been parsed yet, so the document looks empty to the script, so there is no #container yet.
$(function() { ... });
is (roughly) equivalent to
Wait till the whole HTML file is loaded and ready
Then execute function
so #container will be there and it will work. Another way to make it work would be to put the script below the rest of the page or at least below #container.

Wrapping all AJAX calls jQuery

I populate many parts of my website using
$("#theDivToPopulate").load("/some/api/call.php", callBackToBindClickEventsToNewDiv);
Where /some/api/call.php returns a built list, div, or some other HTML structure to place directly into my target div. The internet has been running slow lately and I've noticed that the time between a button click (which kicks off these API calls) and the div populating is several seconds. Is there an easy way to globally wrap all the load calls so that a div containing "Loading..." is displayed before the call is even made and hidden once the API call is complete.
I can not simply put the code to hide the div into the callBackToBindClickEventsToNewDiv as some load events have different call backs. I would have to copy the code into each function which is ugly and defeats the purpose. I want the flow of any .load to go as follows:
1) dispplayLoadingDiv()
2) Execute API call
3) Hide loading div
4) do callback function.
The loading div must be hidden first as the callback contains some animations to bring the newly loaded div in nicely.
EDIT:
Expanding on jacktheripper's answer:
var ajaxFlag;
$(document).ajaxStart(function(){
ajaxFlag = true;
setTimeout(function (e) {
if(ajaxFlag) {
hideAllDivs();
enableDivs(['loading']);
}
}, 500);
}).ajaxStop(function(){
ajaxFlag = false;
var load = $("#loading");
load.css('visibility','hidden');
load.css('display','none');
load.data('isOn',false);
});
This way loading is only displayed if the page takes more than 500 MS to load. I found the loading flying in and out real fast made things kind of choppy for fast page loads.
Use the following jQuery:
$(document).ajaxStart(function(){
$('#loader').show();
}).ajaxStop(function(){
$('#loader').hide();
});
Where you have an element called #loader that contains what you want to show when an AJAX request is being performed. It could be a span with text, an image (eg a gif), or anything similar. The element should be initially set to display: none
You do not even need to call the function anywhere else.
Try this
$("#someButtonId").click(function(e){
e.preventDefault();
$("#theDivToPopulate").html("Loading...");
$.get("/some/api/call.php",function(data){
$("#theDivToPopulate").fadeOut(100,function(){
$("#theDivToPopulate").html(data).fadeIn(100,function(){
//Do your last call back after showing the content
});
});
});
});

Categories

Resources