Script Outside of $(document).ready - javascript

I have built a site for a client and when the user clicks on a navigation link, the content of the linked page is dynamically loaded and transitioned in with JQuery, instead of loading the new page.
The problem I am having is that because it is not loading a new page, $(document).ready doesn't fire again and any JS on the individual pages gets broken. For example, if you visit http://www.woodlandexotica.com/species.php the page works correctly, but if you try to navigate to the page from http://www.woodlandexotica.com/index_dev.php, the JS won't work.
I'm not an expert in JS and I really appreciate any and all help!

The problem is that when you call ".load()", you're using a URL string and a selector suffix to extract from the loaded content. When you use ".load()" that way, jQuery strips out all the scripts and does not run them. There's nothing you can do about that other than to implement your own version of ".load()" yourself, or (better) have the other pages you load not be complete HTML pages. If you use ".load()" without the selector suffix on the URL string, then jQuery does run the scripts.
See jQuery bug 6307 for more. The bug will not be fixed but hopefully the documentation will be improved.

The way you organized this code is wrong
Keep only binding's inside document.ready and move the logic outside to a functions..which can be accessed by any page.
$(document).ready(function() {
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// CONTENT BG SLIDESHOW
//////////////////////////////////////////////////
var photos = ["images/bg01.jpg", "images/bg02.jpg", "images/bg03.jpg"];
var slideshowSpeed = 8000;
var interval;
var activeContainer = 1;
var currentImg = 0;
var navigate = function(direction) {
currentImg++;
if(currentImg == photos.length + 1) {
currentImg = 1;
}
// Check which container we need to use
var currentContainer = activeContainer;
if(activeContainer == 1) {
activeContainer = 2;
} else {
activeContainer = 1;
}
showImage(photos[currentImg - 1], currentContainer, activeContainer);
};
var currentZindex = 1;
var showImage = function(photoObject, currentContainer, activeContainer) {
// Make sure the new container is always on the background
currentZindex--;
// Set the background image of the new active container
$("#bgimg" + activeContainer).css({
"background-image" : "url(" + photoObject + ")",
"display" : "block",
"z-index" : currentZindex
});
// Fade out the current container
// and display the header text when animation is complete
$("#bgimg" + currentContainer).fadeOut(function() {
setTimeout(function() {
animating = false;
}, 500);
});
$("#bgimg" + currentContainer).css({
"z-index" : "1"
});
currentZindex = 1;
};
function photoLoaded() {
if(!--numPhotosLeft) {
navigate("next");
interval = setInterval(function() {
navigate("next");
}, slideshowSpeed);
$('#bg_load').fadeOut('fast');
$('#page_bg').animate({opacity: 1, marginLeft: '-=860'}, 500);
}
}
var photos = ["images/bg01.jpg", "images/bg02.jpg", "images/bg03.jpg"];
var numPhotosLeft = photos.length;
for(var i = 0; i < photos.length; ++i) {
var img = new Image();
img.onload = photoLoaded;
img.src = photos[i];
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// PAGE TRANSITION
//////////////////////////////////////////////////
// ADJUST FOR DEEPLINKING
var hash = window.location.hash.substr(1);
var href = $('a.link').each(function(){
var href = $(this).attr('href');
if(hash==href.substr(0,href.length-4)){
var toLoad = hash+'.php #page_bg';
$('#page_bg').load(toLoad)
}
});
$('a.link').click(function() {
var toLoad = $(this).attr('href')+' #page_bg';
$('#page_bg').animate({opacity: 0.25, marginLeft: '-=875'}, 500, loadContent);
window.location.hash = $(this).attr('href').substr(0,$(this).attr('href').length-4); //MODIFY FOR DEEP LINKING
function loadContent() {
$('#page_wrap').prepend('<span id="load">LOADING...</span>');
$('#load').fadeIn('fast');
$('#page_bg').css('marginLeft', 860);
$('#page_bg').css('backgroundImage', 'none');
$('#page_bg').load(toLoad,'',hideLoader);
}
function hideLoader() {
$('#load').fadeOut('fast', showNewContent);
}
function showNewContent() {
$('#page_bg').animate({opacity: 1, marginLeft: '-=860'}, 500);
}
return false;
});
//set initial position and opacity
$('#page_bg').css('marginLeft', 860);
$('#page_bg').css('opacity', 0.25);
$('#page_wrap').prepend('<span id="bg_load">LOADING...</span>');
$('#bg_load').fadeIn('fast');
//////////////////////////////////////////////////
//////////////////////////////////////////////////
});

Related

How to do line preloader with jquery

I tried this code for a line preloader but it didn't work and i don't know where is the problem.
var $preload = $("<div class='preloader'><div class='percent'></div><div class='line-parent'><div class='line'></div></div></div>");
$("body").prepend($preload);
var $imgs = $("img");
var imgsLoaded = 0;
var ratio = 0;
$imgs.each(function(){
$this = $(this);
$this.load(function(){
imgsLoaded++;
ratio = imgsLoaded / $imgs.length;
$(".percent").html(ratio / 0.01 + "%");
$(".line").animate({
width : ratio / 0.01 + "%"
});
}, function(){
if(ratio === 1){
$(".preloader").fadeOut();
}
});
});
I belive you want to show 100% wenn all images are loaded and do some action. First load event will not work if is atteched after image is already loaded.
I sugest to check for each img comlete and naturalWidth property every 100ms (with setInterval).
Loader = (function() {
var list, img_length, loaded, interval;
function _check_one(i) { o = list[i]; if (o.complete == true && o.naturalWidth > 0) { loaded++; delete list[i]; } };
function _procent(l, a) { console.log((100*loaded/img_length) + '%'); }
function _check_list() { for(var i in list) {_check_one(i)};_procent();_kill(); };
function _kill() { if(img_length <= loaded) clearInterval(interval); }
function _start() { loaded = 0; list = $('img'); img_length = list.length;
if(img_length != loaded) interval = setInterval(_check_list, 100); }
return { start: _start }
})();
Now at end of the body or in $(document).ready(..) you need to call Loader.start();
Or put all images source (src) in data-src attribite, attach load events and copy data-scr to src attribite. In body all relevant images looks like this:
<img data-src="some url">...
In Script Tag:
$('img').on('load', function() {
// Your action.
}).each(function() { var img = $(this); img.attr('src', img.attr('data-src')); });

How to add slide animation for an image with JavaScript

I am trying to make a responsive image gallery in vanilla JS, I have a function and I am passing the image source as its parameter, and every time I am only changing the source on the click of next or previous button. Here is the function:
this.open = function (src) {
if (!src) {
return false;
}
for (count = 0; count <= imgSrc.length; count++) {
if (imgSrc[count] == src)
break;
var tempSrc = imgSrc[count];
}
imgRatio = false; // clear old image ratio for proper resize-values
var img = document.createElement('img');
img.setAttribute('src', src);
// hide overflow by default / if set
if (!this.opt || !isset(this.opt.hideOverflow) || this.opt.hideOverflow) {
body.setAttribute('style', 'overflow: hidden');
}
this.box.setAttribute('style', 'padding-top: 0');
this.wrapper.innerHTML = '';
this.wrapper.appendChild(img);
// console.log(this.wrapper.innerHTML);
addClass(this.box, 'jslghtbx-active');
// already show wrapper due to bug where dimensions are not
// correct in IE8
if (isIE8) {
addClass(that.wrapper, 'jslghtbx-active');
}
imgText.innerHTML = Details.static_data.gallery[count][3];
var checkClassInt = setInterval(function () {
if (hasClass(that.box, 'jslghtbx-active') && img.complete) {
// wait few ms to get correct image-dimensions
setTimeout(function () {
that.resize();
// add active-class for all other browsers
setTimeout(function () {
addClass(that.wrapper, 'jslghtbx-active');
}, 10);
clearInterval(checkClassInt);
}, 40);
}
}, 10); };
Is there any way so that I can attach animate kind of attribute to the image to have a sliding kind of animation. Please suggest your valuable feedback. [ NOTE: I am using this script https://github.com/felixhagspiel/jsOnlyLightbox ]

Onload method is calling itself more than once on successive reloads to application (var image = new Image(), javascript issue)

I don't understand why onload method(see the code below) is calling itself more than once in IE8 and IE9 browsers on consecutive reloads.
I guess, onload method is fired more than once that is causing this image to render(appear) more than once in IE8,IE9. Below js code is written by my senior Front-Ender (he is using his own written js library for all .append(), anim(), ... methods). The code is working as expected in Firefox, Chrome but the image(html code) is rendering more than once while reloading with a IE8 or IE9 browser.
Some Quick Info:
waitingFor() - Periodically scans dom for matching elements,
mdiTog - The image that is appearing more than once..
How it works:
The div attribute Class="suggestions contextSuggesions" is inserted in the body element and contains an unordered list (ul, li, ul) that toggles between opacity 0 and 1 if you click on the image (mdiTog).
Below is the image of Mditog appearing more than once and it's appearance is random:
waitingFor('.viewport .homePage', function () {
var mdiTog = new Image();
mdiTog.onload = function () {
var $mdi = M$('.mdiTabs ul'),
$contextMenu = M$($body.append('<div class="suggestions contextSuggesions" style="display:none"></div>')),
$toggle = M$($mdi.append('<li class="mdiTog" style="display:none"></li>')),
visible = false,
active = false;
var hideCtx = function () {
if (visible) {
$contextMenu.anim('', {opacity: 100}, {opacity: 0}, 250, function () {
$contextMenu.css({display: 'none'});
});
visible = false;
}
};
$toggle.css({opacity: 0, display: 'inline-block'}).anim('', {opacity: 0}, {opacity: 100}, 1000).on('click', function () {
var togOS = $toggle.offset(),
menu = '';
M$('li', $mdi.get()).each(function (el, idx) {
if (idx > 1) {
menu += '<li rel="' + idx + '">' + $mdi.text(null, el) + '</li>';
}
});
$contextMenu.css({opacity: 0, display: 'block', top: togOS.top + 'px', left: (togOS.left - 20) + 'px'}).anim('', {opacity: 0}, {opacity: 100}, 400, function () {
visible = true;
}).html('<ul>' + menu + '<li class="uiUtil hr" onclick="ApolloUI.widgets.expose.show()">' + translate('previewAll') + '</li><li class="uiUtil" onclick="ApolloUI.mdi.closeAll()">' + translate('closeAll') + '</li></ul>');
});
$contextMenu.on('click', function (e) {
var target = $contextMenu.eventTarget(e);
if (target.tagName === 'LI' && target.className.indexOf('uiUtil') === -1) {
$contextMenu.fire('click', M$('.mdiTabs li').get(parseInt(target.getAttribute('rel'), 10)));
}
hideCtx();
}).on('mouseleave', function () {
active = false;
}).on('mouseenter', function () {
active = true;
});
setInterval(function () {
if (!active && visible) {
hideCtx();
}
}, 1000);
};
mdiTog.src = 'media/img/ico_16_context.png';
});
I do have to close this issue as soon as possible, so any suggestions/modifications/addition in this code to force onload to execute only once on even on several consecutive reloads in IE8/IE9 browsers are welcome.
If the onload fires twice, you should use a guard against executing the handler more than once:
var mdiTog = new Image();
var hasFired = false;
mdiTog.onload = function () {
if (hasFired)
return;
hasFired = true;
…
};
Or, if you're using a jQuery-like library, you could try the one event binding method:
var mdiTog = new Image();
M$(mdiTog).one("load", function () {
…
});

Preloading set of images using jQuery

I have a set of images that are frames in an animation like: frame-1.jpg, frame-2.jpg and I have about 400 images.
What I want to do is preload these 400 images before the animation starts.
Usually when preloading images I use the following:
var images = [
'img/nav-one-selected.png',
'img/nav-two-selected.png',
'img/nav-three-selected.png',
'img/nav-four-selected.png'
];
$(images).each(function() {
var image = $('<img />').attr('src', this);
});
But in this instance, listing the images in the var isn't feasible, and I also wish to fire off the start animation once the images have all been loaded.
So far I have the following:
$spinner_currentFrame = 1;
$numFrames = 400;
function preloadImages() {
$($images).each(function() {
var image = $('<img />').attr('src', this);
});
startAnimation();
}
function startAnimation() {
$spinner_loadingAnim = setInterval(function () {
UpdateSpinner();
}, 140);
}
function UpdateSpinner() {
$spinner_currentFrame = $spinner_currentFrame + 1;
if($spinner_currentFrame > $numFrames) {
$spinner_currentFrame = 1;
}
console.log($spinner_currentFrame);
$('#spinner').css("background-image", "url(frame-" + $spinner_currentFrame + ".jpg)");
}
$(document).ready(function() {
preloadImages();
});
So the plan is that I preload images that are from 1 to 400 and then once that's completed then start the animation. How would I build the $images var though?
I've thought about something like:
$images = [];
$frame = 1;
$numFrames = 400;
$($frame).each(function() {
$frame = $frame + 1;
if($frame <= $numFrames) {
$images =+ 'frame-' + $frame + '.jpg';
}
});
But I'm not sure how a) efficient this is and b) how to do the callback once all images have loaded successfully.
You should use a standard javascript for loop instead of the jQuery's foreach. Foreach is wonderful for looping over an array or set of objects, but not in this case. Here is an example, please note that you have to bind the onload event handler before you set the Image object's src property.
UPDATE: added more functions to complete the entire example.
var loaded_images = 0;
var frames = 400;
var images = [];
function preloadImages() {
for (i=0; i < frames; i++) {
images[i] = new Image();
images[i].onload = function() {
loaded_images += 1;
checkLoadingFinished();
}
images[i].src = 'frame-' + i + '.jpg';
}
}
function checkLoadingFinished() {
if (loaded_images >= frames) {
startAnimation();
}
}
function startAnimation() {
var frameNumber = 0;
var timer = setInterval(function() {
$('#img-dom-element').attr('src', images[frameNumber]);
if (frameNumber > frames) {
frameNumber = 0;
else
frameNumber++;
}, (1000/30)); // (1000/30) = 30 frames per second
}
$(document).ready(function() {
preloadImages();
});
I dont know if it fits to your special case but I use
http://thinkpixellab.com/pxloader/
to preload images. You can add the paths and get one callback if all images are loaded. Afterwards you can start animation.

Javascript jQuery only shows Image element once in IE. FF works

I want to show a big Image when I press the small thumbnail. A simple Lightbox style script.
When I press the grey transparent overlay area around the image, the CSS and image is removed from view. This code is stripped down. Maybe missed something needed...
$(document).ready(function() {
$(".lightBobo").click(function(e) {
e.preventDefault(); // prevent to open link in new window
$(this).lightBobo();
});
});
jQuery.fn.lightBobo = function(e) {
if (e != undefined)
e.preventDefault();
return this.each(function() {
var img = new Image();
$(img).load(function() {
imgW = img.width;
imgH = img.height;
var overlay = $("<div />");
var container = $("<div />");
// Lots of css styling for <div> overlay and container image...
container.append(img); //add image to div
$("body").append(overlay); //add overlay to body
$("body").append(container); //add div to body
overlay.fadeIn("fast", function() {
container.show();
});
$(overlay).click(function() {
removeDivs();
});
function removeDivs() {
container.hide();
overlay.fadeOut("fast");
img = null;
container = null;
overlay = null;
openImgSrc = "";
}
});
});
}
The problem is IE(7) is not showing the image the second time I want to show it. I have to do a page reload to display the image again. It works in FF though.
When I use FireFox I can see in FireBug that the get appended to for each time I show the big image. And the "old" image get's display: none; After 20 times I show the big image, I have 40 elements of Overlay and Container(image).
I can't figure out how to rerun the lightBobo function when needed. So it workes in both IE and FF.
You should probably append the overlay and container just once when initialized, then just show/hide/append content when the user activates the modal.
Otherwise you need to do .remove() on each element ( = null is not enough ) when unloading, unless you want lots of dupes in the DOM.
I would do something like this:
(function($) {
var lightBobo = {
init: function() {
var self = this;
this.overlay = $('<div>').click(this.hide); // bind the click event just once
this.container = $('<div>');
// apply id's or styling
$(document.body).append(overlay,container);
}
hide: function(e) {
lightBobo.container.hide();
lightBobo.overlay.fadeOut('fast');
},
show: function() {
var img = new Image();
$(img).load(function() {
imgW = img.width;
imgH = img.height;
lightBobo.container.append(img); //add image to div
lightBobo.overlay.fadeIn("fast", function() {
lightBobo.container.show();
});
});
}
};
$(function() {
lightBobo.init(); // init the lightbox once
});
$.fn.lightBobo = function() {
return this.each(function() {
lightBoo.show.apply(this);
});
}
})(jQuery);
// bind the anchors here:
$(document).ready(function() {
$(".lightBobo").click(function(e) {
e.preventDefault(); // prevent to open link in new window
$(this).lightBobo();
});
});
I have found a solution. I changed lots of code. Specially the $(img).load(function() { ... } where I was having some problems. I dont really know WHY the load() function didnt want to kick the event more than one time. So I removed most code out of that function.
Remember the $(img).load(function() { ... } is for loading the image BEFORE finding its width and height. otherwise its 0.
$(document).ready(function() {
$(".lightBobo").click(function(e) {
if (e != undefined)
e.preventDefault();
$(this).lightBobo();
});
});
jQuery.fn.lightBobo = function(e) {
return this.each(function() {
var myClickedObj = $(this);
//check if we have a anchor or image tag
var src = "";
if (this.tagName.toLowerCase() == "a")
src = this.href.toLowerCase();
else if (this.tagName.toLowerCase() == "img")
src = this.src.toLowerCase();
else
return;
var winW = $(window).width();
var winH = $(window).height();
var docH = $(document).height();
if (docH < winH)
docH = winH;
//the semitransparant overlay over the whole page
var overlay = $("<div />")
.attr("class", "bobOverlay") //used as id for closing all overlays
.css("background", "#000")
.css("opacity", "0.8")
.css("display", "none")
.click(function() { hideAll(); })
$("body").append(overlay); //add overlay to body
var loadLeft = (winW / 2) - (100 / 2);
var loadTop = (winH / 2) - (20 / 2) + $(document).scrollTop();
overlay.fadeIn("fast");
//an element to hold our picture
var container = $("<div />");
container.attr("class", "bobOverlay");
container.hide();
var img = new Image();
$(img).load(function() {
var imgW = img.width;
var imgH = img.height;
container.append(this); //add the picture to the container
$("body").append(container); // add container to the body
container.fadeIn("fast"); //show container
})
.attr("src", src); //add the src to the image
function hideAll() {
$(".bobOverlay").fadeOut("fast");
}
function IsImage(filename) {
var ext = filename.split('.').pop().toLowerCase();
var allow = new Array("gif", "png", "jpg", "jpeg", "bmp");
if (jQuery.inArray(ext, allow) == -1) {
return false;
}
return true;
}
});
}
Sorry for the long code. And finding out the answer myself...

Categories

Resources