I'm trying to find a very simple and smooth, lightweight javascript or jquery marquee. I already tried silk marquee or something, but it wouldn't work with the application I was using. So the simpler and shorter, the better - and easier to debug. Does anybody know of a easy to implement javascript replacement for the marquee?
Pastebin
Code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type="text/javascript">
var tWidth='300px'; // width (in pixels)
var tHeight='25px'; // height (in pixels)
var tcolour='#ffffcc'; // background colour:
var moStop=true; // pause on mouseover (true or false)
var fontfamily = 'arial,sans-serif'; // font for content
var tSpeed=3; // scroll speed (1 = slow, 5 = fast)
// enter your ticker content here (use \/ and \' in place of / and ' respectively)
var content='Are you looking for loads of useful information <a href="http:\/\/javascript.about.com\/">About Javascript<\/a>? Well now you\'ve found it.';
var cps=-tSpeed; var aw, mq; var fsz = parseInt(tHeight) - 4; function startticker(){if (document.getElementById) {var tick = '<div style="position:relative;width:'+tWidth+';height:'+tHeight+';overflow:hidden;background-color:'+tcolour+'"'; if (moStop) tick += ' onmouseover="cps=0" onmouseout="cps=-tSpeed"'; tick +='><div id="mq" style="position:absolute;right:0px;top:0px;font-family:'+fontfamily+';font-size:'+fsz+'px;white-space:nowrap;"><\/div><\/div>'; document.getElementById('ticker').innerHTML = tick; mq = document.getElementById("mq"); mq.style.right=(10+parseInt(tWidth))+"px"; mq.innerHTML='<span id="tx">'+content+'<\/span>'; aw = document.getElementById("tx").offsetWidth; lefttime=setInterval("scrollticker()",50);}} function scrollticker(){mq.style.right = (parseInt(mq.style.right)>(-10 - aw)) ?
mq.style.right = parseInt(mq.style.right)+cps+"px": parseInt(tWidth)+10+"px";} window.onload=startticker;
</script>
</head>
<body>
<div id="ticker">
this is a simple scrolling text!
</div>
</body>
</html>
hiya simple demo from recommendations in above comments: http://jsfiddle.net/FWWEn/
with pause functionality on mouseover: http://jsfiddle.net/zrW5q/
hope this helps, have a nice one, cheers!
html
<h1>Hello World!</h1>
<h2>I'll marquee twice</h2>
<h3>I go fast!</h3>
<h4>Left to right</h4>
<h5>I'll defer that question</h5>
Jquery code
(function($) {
$.fn.textWidth = function(){
var calc = '<span style="display:none">' + $(this).text() + '</span>';
$('body').append(calc);
var width = $('body').find('span:last').width();
$('body').find('span:last').remove();
return width;
};
$.fn.marquee = function(args) {
var that = $(this);
var textWidth = that.textWidth(),
offset = that.width(),
width = offset,
css = {
'text-indent' : that.css('text-indent'),
'overflow' : that.css('overflow'),
'white-space' : that.css('white-space')
},
marqueeCss = {
'text-indent' : width,
'overflow' : 'hidden',
'white-space' : 'nowrap'
},
args = $.extend(true, { count: -1, speed: 1e1, leftToRight: false }, args),
i = 0,
stop = textWidth*-1,
dfd = $.Deferred();
function go() {
if(!that.length) return dfd.reject();
if(width == stop) {
i++;
if(i == args.count) {
that.css(css);
return dfd.resolve();
}
if(args.leftToRight) {
width = textWidth*-1;
} else {
width = offset;
}
}
that.css('text-indent', width + 'px');
if(args.leftToRight) {
width++;
} else {
width--;
}
setTimeout(go, args.speed);
};
if(args.leftToRight) {
width = textWidth*-1;
width++;
stop = offset;
} else {
width--;
}
that.css(marqueeCss);
go();
return dfd.promise();
};
})(jQuery);
$('h1').marquee();
$('h2').marquee({ count: 2 });
$('h3').marquee({ speed: 5 });
$('h4').marquee({ leftToRight: true });
$('h5').marquee({ count: 1, speed: 2 }).done(function() { $('h5').css('color', '#f00'); })
I've made very simple function for marquee. See: http://jsfiddle.net/vivekw/pHNpk/2/
It pauses on mouseover & resumes on mouseleave. Speed can be varied. Easy to understand.
function marquee(a, b) {
var width = b.width();
var start_pos = a.width();
var end_pos = -width;
function scroll() {
if (b.position().left <= -width) {
b.css('left', start_pos);
scroll();
}
else {
time = (parseInt(b.position().left, 10) - end_pos) *
(10000 / (start_pos - end_pos)); // Increase or decrease speed by changing value 10000
b.animate({
'left': -width
}, time, 'linear', function() {
scroll();
});
}
}
b.css({
'width': width,
'left': start_pos
});
scroll(a, b);
b.mouseenter(function() { // Remove these lines
b.stop(); //
b.clearQueue(); // if you don't want
}); //
b.mouseleave(function() { // marquee to pause
scroll(a, b); //
}); // on mouse over
}
$(document).ready(function() {
marquee($('#display'), $('#text')); //Enter name of container element & marquee element
});
I just created a simple jQuery plugin for that. Try it ;)
https://github.com/aamirafridi/jQuery.Marquee
The following works:
http://jsfiddle.net/xAGRJ/4/
The problem with your original code was you are calling scrollticker() by passing a string to setInterval, where you should just pass the function name and treat it as a variable:
lefttime = setInterval(scrollticker, 50);
instead of
lefttime = setInterval("scrollticker()", 50);
Why write custom jQuery code for Marquee... just use a plugin for jQuery - marquee() and use it like in the example below:
First include :
<script type='text/javascript' src='//cdn.jsdelivr.net/jquery.marquee/1.3.1/jquery.marquee.min.js'></script>
and then:
//proporcional speed counter (for responsive/fluid use)
var widths = $('.marquee').width()
var duration = widths * 7;
$('.marquee').marquee({
//speed in milliseconds of the marquee
duration: duration, // for responsive/fluid use
//duration: 8000, // for fixed container
//gap in pixels between the tickers
gap: $('.marquee').width(),
//time in milliseconds before the marquee will start animating
delayBeforeStart: 0,
//'left' or 'right'
direction: 'left',
//true or false - should the marquee be duplicated to show an effect of continues flow
duplicated: true
});
If you can make it simpler and better I dare you all people :). Don't make your life more difficult than it should be. More about this plugin and its functionalities at: http://aamirafridi.com/jquery/jquery-marquee-plugin
I made my own version, based in the code presented above by #Tats_innit .
The difference is the pause function. Works a little better in that aspect.
(function ($) {
var timeVar, width=0;
$.fn.textWidth = function () {
var calc = '<span style="display:none">' + $(this).text() + '</span>';
$('body').append(calc);
var width = $('body').find('span:last').width();
$('body').find('span:last').remove();
return width;
};
$.fn.marquee = function (args) {
var that = $(this);
if (width == 0) { width = that.width(); };
var textWidth = that.textWidth(), offset = that.width(), i = 0, stop = textWidth * -1, dfd = $.Deferred(),
css = {
'text-indent': that.css('text-indent'),
'overflow': that.css('overflow'),
'white-space': that.css('white-space')
},
marqueeCss = {
'text-indent': width,
'overflow': 'hidden',
'white-space': 'nowrap'
},
args = $.extend(true, { count: -1, speed: 1e1, leftToRight: false, pause: false }, args);
function go() {
if (!that.length) return dfd.reject();
if (width <= stop) {
i++;
if (i <= args.count) {
that.css(css);
return dfd.resolve();
}
if (args.leftToRight) {
width = textWidth * -1;
} else {
width = offset;
}
}
that.css('text-indent', width + 'px');
if (args.leftToRight) {
width++;
} else {
width=width-2;
}
if (args.pause == false) { timeVar = setTimeout(function () { go() }, args.speed); };
if (args.pause == true) { clearTimeout(timeVar); };
};
if (args.leftToRight) {
width = textWidth * -1;
width++;
stop = offset;
} else {
width--;
}
that.css(marqueeCss);
timeVar = setTimeout(function () { go() }, 100);
return dfd.promise();
};
})(jQuery);
usage:
for start: $('#Text1').marquee()
pause: $('#Text1').marquee({ pause: true })
resume: $('#Text1').marquee({ pause: false })
My text marquee for more text,
and position absolute enabled
http://jsfiddle.net/zrW5q/2075/
(function($) {
$.fn.textWidth = function() {
var calc = document.createElement('span');
$(calc).text($(this).text());
$(calc).css({
position: 'absolute',
visibility: 'hidden',
height: 'auto',
width: 'auto',
'white-space': 'nowrap'
});
$('body').append(calc);
var width = $(calc).width();
$(calc).remove();
return width;
};
$.fn.marquee = function(args) {
var that = $(this);
var textWidth = that.textWidth(),
offset = that.width(),
width = offset,
css = {
'text-indent': that.css('text-indent'),
'overflow': that.css('overflow'),
'white-space': that.css('white-space')
},
marqueeCss = {
'text-indent': width,
'overflow': 'hidden',
'white-space': 'nowrap'
},
args = $.extend(true, {
count: -1,
speed: 1e1,
leftToRight: false
}, args),
i = 0,
stop = textWidth * -1,
dfd = $.Deferred();
function go() {
if (that.css('overflow') != "hidden") {
that.css('text-indent', width + 'px');
return false;
}
if (!that.length) return dfd.reject();
if (width <= stop) {
i++;
if (i == args.count) {
that.css(css);
return dfd.resolve();
}
if (args.leftToRight) {
width = textWidth * -1;
} else {
width = offset;
}
}
that.css('text-indent', width + 'px');
if (args.leftToRight) {
width++;
} else {
width--;
}
setTimeout(go, args.speed);
};
if (args.leftToRight) {
width = textWidth * -1;
width++;
stop = offset;
} else {
width--;
}
that.css(marqueeCss);
go();
return dfd.promise();
};
// $('h1').marquee();
$("h1").marquee();
$("h1").mouseover(function () {
$(this).removeAttr("style");
}).mouseout(function () {
$(this).marquee();
});
})(jQuery);
Responsive resist jQuery marquee simple plugin. Tutorial:
// start plugin
(function($){
$.fn.marque = function(options, callback){
// check callback
if(typeof callback == 'function'){
callback.call(this);
} else{
console.log("second argument (callback) is not a function");
// throw "callback must be a function"; //only if callback for some reason is required
// return this; //only if callback for some reason is required
}
//set and overwrite default functions
var defOptions = $.extend({
speedPixelsInOneSecound: 150, //speed will behave same for different screen where duration will be different for each size of the screen
select: $('.message div'),
clickSelect: '', // selector that on click will redirect user ... (optional)
clickUrl: '' //... to this url. (optional)
}, options);
//Run marque plugin
var windowWidth = $(window).width();
var textWidth = defOptions.select.outerWidth();
var duration = (windowWidth + textWidth) * 1000 / defOptions.speedPixelsInOneSecound;
var startingPosition = (windowWidth + textWidth);
var curentPosition = (windowWidth + textWidth);
var speedProportionToLocation = curentPosition / startingPosition;
defOptions.select.css({'right': -(textWidth)});
defOptions.select.show();
var animation;
function marquee(animation){
curentPosition = (windowWidth + defOptions.select.outerWidth());
speedProportionToLocation = curentPosition / startingPosition;
animation = defOptions.select.animate({'right': windowWidth+'px'}, duration * speedProportionToLocation, "linear", function(){
defOptions.select.css({'right': -(textWidth)});
});
}
var play = setInterval(marquee, 200);
//add onclick behaviour
if(defOptions.clickSelect != '' && defOptions.clickUrl != ''){
defOptions.clickSelect.click(function(){
window.location.href = defOptions.clickUrl;
});
}
return this;
};
}(jQuery));
// end plugin
Use this custom jQuery plugin as bellow:
//use example
$(window).marque({
speedPixelsInOneSecound: 150, // spped pixels/secound
select: $('.message div'), // select an object on which you want to apply marquee effects.
clickSelect: $('.message'), // select clicable object (optional)
clickUrl: 'services.php' // define redirection url (optional)
});
Marquee using CSS animations.
`<style>
.items-holder {
animation: moveSlideshow 5s linear infinite;
}
.items-holder:hover {
animation-play-state: paused;
}
#keyframes moveSlideshow {
100% {
transform: translateX(100%);
}
}
</style>`
I try use only css for it this link.
<style>
.header {
background: #212121;
overflow: hidden;
height: 65px;
position: relative;
}
.header div {
display: flex;
flex-direction: row;
align-items: center;
overflow: hidden;
height: 65px;
transform: translate(100%, 0);
}
.header div * {
font-family: "Roboto", sans-serif;
color: #fff339;
text-transform: uppercase;
text-decoration: none;
}
.header div img {
height: 60px;
margin-right: 20px;
}
.header .ticker-wrapper__container{
display: flex;
flex-direction: row;
align-items: center;
position: absolute;
top: 0;
right: 0;
animation: ticker 30s infinite linear forwards;
}
.header:hover .ticker-wrapper__container{
animation-play-state: paused;
}
.ticker-wrapper__container a{
display: flex;
margin-right: 60px;
align-items: center;
}
#keyframes ticker {
0% {
transform: translate(100%, 0);
}
50% {
transform: translate(0, 0);
}
100% {
transform: translate(-100%, 0);
}
}
</style>
Related
Hey everyone! I tried to make number-counter when i will see it, everything great until the moment when i saw that the number raised from 1 to 85 and then from 85 to 1 (It should increases and then stop). I tried to fix that by adding the feature which launches counter function only once, but that did't work out.
If you have offers, i beg you to share with me please)
// Persent-counter
var isResizeble_1 = false;
var isResizeble_2 = false;
function first_num_count(){
if(!isResizeble_2) {
// The count function
$('#count-num').each(function(){
$(this).prop('Counter', 0).animate({
Counter: $(this).text()
},{
duration: 2000,
easing: 'swing',
step: function(now){
$(this).text(Math.ceil(now));
}
});
});
isRezeble_2 = true;
}
}
// The trigger element
var firstPersent = document.querySelector('#persent');
var Visible = function (target) {
// Get elem's positions
var targetPosition = {
top: window.pageYOffset + target.getBoundingClientRect().top,
left: window.pageXOffset + target.getBoundingClientRect().left,
right: window.pageXOffset + target.getBoundingClientRect().right,
bottom: window.pageYOffset + target.getBoundingClientRect().bottom
},
// Get window's positions
windowPosition = {
top: window.pageYOffset,
left: window.pageXOffset,
right: window.pageXOffset + document.documentElement.clientWidth,
bottom: window.pageYOffset + document.documentElement.clientHeight
};
if (targetPosition.bottom > windowPosition.top &&
targetPosition.top < windowPosition.bottom &&
targetPosition.right > windowPosition.left &&
targetPosition.left < windowPosition.right) {
// If we see the elem
// Do our counting function only once
if(!isResizeble_1) {
first_num_count();
isRezeble_1 = true;
}
}
};
// Start function onscroll
window.addEventListener('scroll', function() {
Visible(firstPersent);
});
body{
height 900px;
}
.number-persent{
margin-top: 600px;
display: flex;
}
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<body>
<div class="number-persent">
<p id="count-num">85</p>
<p id="persent">%</p>
</div>
</body>
Move var isResizeble_2 = false; outside the function otherwise it will always run what's in the if. And fix your variable name typos.
var isResizeble_2 = false;
// Persent-counter
function first_num_count(){
if(!isResizeble_2) {
// The count function
$('#count-num').each(function(){
$(this).prop('Counter', 0).animate({
Counter: $(this).text()
},{
duration: 2000,
easing: 'swing',
step: function(now){
$(this).text(Math.ceil(now));
}
});
});
isResizeble_2 = true;
}
}
// The trigger element
var firstPersent = document.querySelector('#persent');
var Visible = function (target) {
// Get elem's positions
var targetPosition = {
top: window.pageYOffset + target.getBoundingClientRect().top,
left: window.pageXOffset + target.getBoundingClientRect().left,
right: window.pageXOffset + target.getBoundingClientRect().right,
bottom: window.pageYOffset + target.getBoundingClientRect().bottom
},
// Get window's positions
windowPosition = {
top: window.pageYOffset,
left: window.pageXOffset,
right: window.pageXOffset + document.documentElement.clientWidth,
bottom: window.pageYOffset + document.documentElement.clientHeight
};
if (targetPosition.bottom > windowPosition.top &&
targetPosition.top < windowPosition.bottom &&
targetPosition.right > windowPosition.left &&
targetPosition.left < windowPosition.right) {
// If we see the elem
// Do our counting function only once
var isResizeble_1 = false;
if(!isResizeble_1) {
first_num_count();
isResizeble_1 = true;
}
} else {
// If we don't see the elem
};
};
// Start function onscroll
window.addEventListener('scroll', function() {
Visible(firstPersent);
});
body{
height 900px;
}
.number-persent{
margin-top: 600px;
display: flex;
}
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<body>
<div class="number-persent">
<p id="count-num">85</p>
<p id="persent">%</p>
</div>
</body>
I am using the lightbox jquery plugin to open a lightbox when a user clicks on a product. Often the lightbox content stretches below the fold, and at the moment the right scrollbar moves the entire page when you scroll down.
I'd like it to work like the pinterest lightbox, whereby the right scrollbar only scrolls the lightbox, and the rest of the page stays fixed. I've seen a few posts on this, but nothing seems to work for me.
Problem is I want the lightbox to scroll if the content is bigger than the viewport of the browser but not the background.
CSS:
#lightbox{ position: absolute; left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;}
#lightbox img{ width: auto; height: auto;}
#lightbox a img{ border: none; }
#outerImageContainer{ position: relative; background-color: #fff; width: 250px; height: 250px; margin: 0 auto; }
#imageContainer{ padding: 10px; }
#loading{ position: absolute; top: 40%; left: 0%; height: 25%; width: 100%; text-align: center; line-height: 0; }
#hoverNav{ position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 10; }
#imageContainer>#hoverNav{ left: 0;}
#hoverNav a{ outline: none;}
#prevLink, #nextLink{ width: 49%; height: 100%; background-image: url(data:image2/gif;base64,AAAA); /* Trick IE into showing hover */ display: block; }
#prevLink { left: 0; float: left;}
#nextLink { right: 0; float: right;}
#prevLink:hover, #prevLink:visited:hover { background: url(../images2/prevlabel.gif) left 15% no-repeat; }
#nextLink:hover, #nextLink:visited:hover { background: url(../images2/nextlabel.gif) right 15% no-repeat; }
#imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #fff; margin: 0 auto; line-height: 1.4em; overflow: auto; width: 100% ; }
#imageData{ padding:0 10px; color: #666; }
#imageData #imageDetails{ width: 70%; float: left; text-align: left; }
#imageData #caption{ font-weight: bold; }
#imageData #numberDisplay{ display: block; clear: left; padding-bottom: 1.0em; }
#imageData #bottomNavClose{ width: 66px; float: right; padding-bottom: 0.7em; outline: none;}
#overlay{ position: absolute; top: 0; left: 0; z-index: 90; width: 100%; height: 500px; background-color: #000; }
JS:
// -----------------------------------------------------------------------------------
//
// Lightbox v2.04
// by Lokesh Dhakar - http://www.lokeshdhakar.com
// Last Modification: 2/9/08
//
// For more information, visit:
// http://lokeshdhakar.com/projects/lightbox2/
//
// Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
// - Free for use in both personal and commercial projects
// - Attribution requires leaving author name, author link, and the license info intact.
//
// Thanks: Scott Upton(uptonic.com), Peter-Paul Koch(quirksmode.com), and Thomas Fuchs(mir.aculo.us) for ideas, libs, and snippets.
// Artemy Tregubenko (arty.name) for cleanup and help in updating to latest ver of proto-aculous.
//
// -----------------------------------------------------------------------------------
/*
Table of Contents
-----------------
Configuration
Lightbox Class Declaration
- initialize()
- updateImageList()
- start()
- changeImage()
- resizeImageContainer()
- showImage()
- updateDetails()
- updateNav()
- enableKeyboardNav()
- disableKeyboardNav()
- keyboardAction()
- preloadNeighborImages()
- end()
Function Calls
- document.observe()
*/
// -----------------------------------------------------------------------------------
//
// Configurationl
//
LightboxOptions = Object.extend({
fileLoadingImage: 'images2/loading.gif',
fileBottomNavCloseImage: 'images2/closelabel.gif',
overlayOpacity: 0.8, // controls transparency of shadow overlay
animate: true, // toggles resizing animations
resizeSpeed: 7, // controls the speed of the image resizing animations (1=slowest and 10=fastest)
borderSize: 10, //if you adjust the padding in the CSS, you will need to update this variable
// When grouping images this is used to write: Image # of #.
// Change it for non-english localization
labelImage: "Image",
labelOf: "of"
}, window.LightboxOptions || {});
// -----------------------------------------------------------------------------------
var Lightbox = Class.create();
Lightbox.prototype = {
imageArray: [],
activeImage: undefined,
// initialize()
// Constructor runs on completion of the DOM loading. Calls updateImageList and then
// the function inserts html at the bottom of the page which is used to display the shadow
// overlay and the image container.
//
initialize: function() {
this.updateImageList();
this.keyboardAction = this.keyboardAction.bindAsEventListener(this);
if (LightboxOptions.resizeSpeed > 10) LightboxOptions.resizeSpeed = 10;
if (LightboxOptions.resizeSpeed < 1) LightboxOptions.resizeSpeed = 1;
this.resizeDuration = LightboxOptions.animate ? ((11 - LightboxOptions.resizeSpeed) * 0.15) : 0;
this.overlayDuration = LightboxOptions.animate ? 0.2 : 0; // shadow fade in/out duration
// When Lightbox starts it will resize itself from 250 by 250 to the current image dimension.
// If animations are turned off, it will be hidden as to prevent a flicker of a
// white 250 by 250 box.
var size = (LightboxOptions.animate ? 250 : 1) + 'px';
// Code inserts html at the bottom of the page that looks similar to this:
//
// <div id="overlay"></div>
// <div id="lightbox">
// <div id="outerImageContainer">
// <div id="imageContainer">
// <img id="lightboxImage">
// <div style="" id="hoverNav">
//
//
// </div>
// <div id="loading">
// <a href="#" id="loadingLink">
// <img src="images/loading.gif">
// </a>
// </div>
// </div>
// </div>
// <div id="imageDataContainer">
// <div id="imageData">
// <div id="imageDetails">
// <span id="caption"></span>
// <span id="numberDisplay"></span>
// </div>
// <div id="bottomNav">
// <a href="#" id="bottomNavClose">
// <img src="images/close.gif">
// </a>
// </div>
// </div>
// </div>
// </div>
var objBody = $$('body')[0];
objBody.appendChild(Builder.node('div',{id:'overlay'}));
objBody.appendChild(Builder.node('div',{id:'lightbox'}, [
Builder.node('div',{id:'outerImageContainer'},
Builder.node('div',{id:'imageContainer'}, [
Builder.node('img',{id:'lightboxImage'}),
Builder.node('div',{id:'hoverNav'}, [
Builder.node('a',{id:'prevLink', href: '#' }),
Builder.node('a',{id:'nextLink', href: '#' })
]),
Builder.node('div',{id:'loading'},
Builder.node('a',{id:'loadingLink', href: '#' },
Builder.node('img', {src: LightboxOptions.fileLoadingImage})
)
)
])
),
Builder.node('div', {id:'imageDataContainer'},
Builder.node('div',{id:'imageData'}, [
Builder.node('div',{id:'imageDetails'}, [
Builder.node('span',{id:'caption'}),
Builder.node('span',{id:'numberDisplay'})
]),
Builder.node('div',{id:'bottomNav'},
Builder.node('a',{id:'bottomNavClose', href: '#' },
Builder.node('img', { src: LightboxOptions.fileBottomNavCloseImage })
)
)
])
)
]));
$('overlay').hide().observe('click', (function() { this.end(); }).bind(this));
$('lightbox').hide().observe('click', (function(event) { if (event.element().id == 'lightbox') this.end(); }).bind(this));
$('outerImageContainer').setStyle({ width: size, height: size });
$('prevLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage - 1); }).bindAsEventListener(this));
$('nextLink').observe('click', (function(event) { event.stop(); this.changeImage(this.activeImage + 1); }).bindAsEventListener(this));
$('loadingLink').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
$('bottomNavClose').observe('click', (function(event) { event.stop(); this.end(); }).bind(this));
var th = this;
(function(){
var ids =
'overlay lightbox outerImageContainer imageContainer lightboxImage hoverNav prevLink nextLink loading loadingLink ' +
'imageDataContainer imageData imageDetails caption numberDisplay bottomNav bottomNavClose';
$w(ids).each(function(id){ th[id] = $(id); });
}).defer();
},
//
// updateImageList()
// Loops through anchor tags looking for 'lightbox' references and applies onclick
// events to appropriate links. You can rerun after dynamically adding images w/ajax.
//
updateImageList: function() {
this.updateImageList = Prototype.emptyFunction;
document.observe('click', (function(event){
var target = event.findElement('a[rel^=lightbox]') || event.findElement('area[rel^=lightbox]');
if (target) {
event.stop();
this.start(target);
}
}).bind(this));
},
//
// start()
// Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
//
start: function(imageLink) {
$$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'hidden' });
// stretch overlay to fill page and fade in
var arrayPageSize = this.getPageSize();
$('overlay').setStyle({ width: arrayPageSize[0] + 'px', height: arrayPageSize[1] + 'px' });
new Effect.Appear(this.overlay, { duration: this.overlayDuration, from: 0.0, to: LightboxOptions.overlayOpacity });
this.imageArray = [];
var imageNum = 0;
if ((imageLink.rel == 'lightbox')){
// if image is NOT part of a set, add single image to imageArray
this.imageArray.push([imageLink.href, imageLink.title]);
} else {
// if image is part of a set..
this.imageArray =
$$(imageLink.tagName + '[href][rel="' + imageLink.rel + '"]').
collect(function(anchor){ return [anchor.href, anchor.title]; }).
uniq();
while (this.imageArray[imageNum][0] != imageLink.href) { imageNum++; }
}
// calculate top and left offset for the lightbox
var arrayPageScroll = document.viewport.getScrollOffsets();
var lightboxTop = arrayPageScroll[1] + (document.viewport.getHeight() / 10);
var lightboxLeft = arrayPageScroll[0];
this.lightbox.setStyle({ top: lightboxTop + 'px', left: lightboxLeft + 'px' }).show();
this.changeImage(imageNum);
},
//
// changeImage()
// Hide most elements and preload image in preparation for resizing image container.
//
changeImage: function(imageNum) {
this.activeImage = imageNum; // update global var
// hide elements during transition
if (LightboxOptions.animate) this.loading.show();
this.lightboxImage.hide();
this.hoverNav.hide();
this.prevLink.hide();
this.nextLink.hide();
// HACK: Opera9 does not currently support scriptaculous opacity and appear fx
this.imageDataContainer.setStyle({opacity: .0001});
this.numberDisplay.hide();
var imgPreloader = new Image();
// once image is preloaded, resize image container
imgPreloader.onload = (function(){
this.lightboxImage.src = this.imageArray[this.activeImage][0];
this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
}).bind(this);
imgPreloader.src = this.imageArray[this.activeImage][0];
},
//
// resizeImageContainer()
//
resizeImageContainer: function(imgWidth, imgHeight) {
// get current width and height
var widthCurrent = this.outerImageContainer.getWidth();
var heightCurrent = this.outerImageContainer.getHeight();
// get new width and height
var widthNew = (imgWidth + LightboxOptions.borderSize * 2);
var heightNew = (imgHeight + LightboxOptions.borderSize * 2);
// scalars based on change from old to new
var xScale = (widthNew / widthCurrent) * 100;
var yScale = (heightNew / heightCurrent) * 100;
// calculate size difference between new and old image, and resize if necessary
var wDiff = widthCurrent - widthNew;
var hDiff = heightCurrent - heightNew;
if (hDiff != 0) new Effect.Scale(this.outerImageContainer, yScale, {scaleX: false, duration: this.resizeDuration, queue: 'front'});
if (wDiff != 0) new Effect.Scale(this.outerImageContainer, xScale, {scaleY: false, duration: this.resizeDuration, delay: this.resizeDuration});
// if new and old image are same size and no scaling transition is necessary,
// do a quick pause to prevent image flicker.
var timeout = 0;
if ((hDiff == 0) && (wDiff == 0)){
timeout = 100;
if (Prototype.Browser.IE) timeout = 250;
}
(function(){
this.prevLink.setStyle({ height: imgHeight + 'px' });
this.nextLink.setStyle({ height: imgHeight + 'px' });
this.imageDataContainer.setStyle({ width: widthNew + 'px' });
this.showImage();
}).bind(this).delay(timeout / 1000);
},
//
// showImage()
// Display image and begin preloading neighbors.
//
showImage: function(){
this.loading.hide();
new Effect.Appear(this.lightboxImage, {
duration: this.resizeDuration,
queue: 'end',
afterFinish: (function(){ this.updateDetails(); }).bind(this)
});
this.preloadNeighborImages();
},
//
// updateDetails()
// Display caption, image number, and bottom nav.
//
updateDetails: function() {
// if caption is not null
if (this.imageArray[this.activeImage][1] != ""){
this.caption.update(this.imageArray[this.activeImage][1]).show();
}
// if image is part of set display 'Image x of x'
if (this.imageArray.length > 1){
this.numberDisplay.update( LightboxOptions.labelImage + ' ' + (this.activeImage + 1) + ' ' + LightboxOptions.labelOf + ' ' + this.imageArray.length).show();
}
new Effect.Parallel(
[
new Effect.SlideDown(this.imageDataContainer, { sync: true, duration: this.resizeDuration, from: 0.0, to: 1.0 }),
new Effect.Appear(this.imageDataContainer, { sync: true, duration: this.resizeDuration })
],
{
duration: this.resizeDuration,
afterFinish: (function() {
// update overlay size and update nav
var arrayPageSize = this.getPageSize();
this.overlay.setStyle({ height: arrayPageSize[1] + 'px' });
this.updateNav();
}).bind(this)
}
);
},
//
// updateNav()
// Display appropriate previous and next hover navigation.
//
updateNav: function() {
this.hoverNav.show();
// if not first image in set, display prev image button
if (this.activeImage > 0) this.prevLink.show();
// if not last image in set, display next image button
if (this.activeImage < (this.imageArray.length - 1)) this.nextLink.show();
this.enableKeyboardNav();
},
//
// enableKeyboardNav()
//
enableKeyboardNav: function() {
document.observe('keydown', this.keyboardAction);
},
//
// disableKeyboardNav()
//
disableKeyboardNav: function() {
document.stopObserving('keydown', this.keyboardAction);
},
//
// keyboardAction()
//
keyboardAction: function(event) {
var keycode = event.keyCode;
var escapeKey;
if (event.DOM_VK_ESCAPE) { // mozilla
escapeKey = event.DOM_VK_ESCAPE;
} else { // ie
escapeKey = 27;
}
var key = String.fromCharCode(keycode).toLowerCase();
if (key.match(/x|o|c/) || (keycode == escapeKey)){ // close lightbox
this.end();
} else if ((key == 'p') || (keycode == 37)){ // display previous image
if (this.activeImage != 0){
this.disableKeyboardNav();
this.changeImage(this.activeImage - 1);
}
} else if ((key == 'n') || (keycode == 39)){ // display next image
if (this.activeImage != (this.imageArray.length - 1)){
this.disableKeyboardNav();
this.changeImage(this.activeImage + 1);
}
}
},
//
// preloadNeighborImages()
// Preload previous and next images.
//
preloadNeighborImages: function(){
var preloadNextImage, preloadPrevImage;
if (this.imageArray.length > this.activeImage + 1){
preloadNextImage = new Image();
preloadNextImage.src = this.imageArray[this.activeImage + 1][0];
}
if (this.activeImage > 0){
preloadPrevImage = new Image();
preloadPrevImage.src = this.imageArray[this.activeImage - 1][0];
}
},
//
// end()
//
end: function() {
this.disableKeyboardNav();
this.lightbox.hide();
new Effect.Fade(this.overlay, { duration: this.overlayDuration });
$$('select', 'object', 'embed').each(function(node){ node.style.visibility = 'visible' });
},
//
// getPageSize()
//
getPageSize: function() {
var xScroll, yScroll;
if (window.innerHeight && window.scrollMaxY) {
xScroll = window.innerWidth + window.scrollMaxX;
yScroll = window.innerHeight + window.scrollMaxY;
} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
xScroll = document.body.scrollWidth;
yScroll = document.body.scrollHeight;
} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
xScroll = document.body.offsetWidth;
yScroll = document.body.offsetHeight;
}
var windowWidth, windowHeight;
if (self.innerHeight) { // all except Explorer
if(document.documentElement.clientWidth){
windowWidth = document.documentElement.clientWidth;
} else {
windowWidth = self.innerWidth;
}
windowHeight = self.innerHeight;
} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
windowWidth = document.documentElement.clientWidth;
windowHeight = document.documentElement.clientHeight;
} else if (document.body) { // other Explorers
windowWidth = document.body.clientWidth;
windowHeight = document.body.clientHeight;
}
// for small pages with total height less then height of the viewport
if(yScroll < windowHeight){
pageHeight = windowHeight;
} else {
pageHeight = yScroll;
}
// for small pages with total width less then width of the viewport
if(xScroll < windowWidth){
pageWidth = xScroll;
} else {
pageWidth = windowWidth;
}
return [pageWidth,pageHeight];
}
}
document.observe('dom:loaded', function () { new Lightbox(); });
Here's a class that'll allow you to do just that:
class ScrollLock {
constructor () {
this.pageBody = document.querySelector('body');
this.scrollY = 0;
}
saveScrollY = (num) => {
this.scrollY = num;
}
setScrollY = (num) => {
window.scroll(0, num);
}
setScrollOffset = (vOffset) => {
this.pageBody.style.top = `-${vOffset}px`;
}
freezeBodyScroll = () => {
this.saveScrollY(window.scrollY);
this.setScrollOffset(this.scrollY);
this.pageBody.classList.add('is-fixed');
}
unfreezeBodyScroll = () => {
this.pageBody.classList.remove('is-fixed');
// Don't reset scroll position if lock hasn't occurred
if (this.scrollY === 0) return;
this.setScrollOffset(0);
this.setScrollY(this.scrollY);
this.saveScrollY(0);
}
}
Include the following style declaration:
// In your CSS
body.is-fixed {
position: fixed;
max-width: 100%;
}
Use:
const { freezeBodyScroll, unfreezeBodyScroll } = new ScrollLock();
// Call when you open your modal
freezeBodyScroll();
// Call when you close your modal
unfreezeBodyScroll();
For a photographic website and want to display panoramic photos moving side to side within a viewport. At the moment it goes left to right when the page loads but stops when it runs out of image. Instead of stopping I want it to reverse direction and go right to left, and then left to right, right to left infintum.
It is probable something very simple but I'm a complete newbie to jquery (sorry).
This is the code which I've adapted from Arnault PACHOT:
Any help would be greatly appreciated. Thanks in advance.
/* =========================================================
// jquery.panorama.js
// Author: OpenStudio (Arnault PACHOT)
// Mail: apachot#openstudio.fr
// Web: http://www.openstudio.fr
// Copyright (c) 2008 Arnault Pachot
// licence : GPL
========================================================= */
(function($) {
$.fn.panorama = function(options) {
this.each(function(){
var settings = {
viewport_width: 669,
speed: 20000,
direction: 'left',
control_display: 'auto',
start_position: 0,
auto_start: true,
mode_360: false
};
if(options) $.extend(settings, options);
var elemWidth = parseInt($(this).attr('width'));
var elemHeight = parseInt($(this).attr('height'));
var currentElement = this;
var panoramaViewport, panoramaContainer;
var bMouseMove = false;
var mouseMoveStart = 0;
var mouseMoveMarginStart = 0;
$(this).attr('unselectable','on')
.css('position', 'relative')
.css('-moz-user-select','none')
.css('-webkit-user-select','none')
.css('margin', '0')
.css('padding', '0')
.css('border', 'none')
.wrap("<div class='panorama-container'></div>");
if (settings.mode_360)
$(this).clone().insertAfter(this);
panoramaContainer = $(this).parent();
panoramaContainer.css('height', elemHeight+'px').css('overflow', 'hidden').wrap("<div class='panorama-viewport'></div>").parent().css('width',settings.viewport_width+'px')
.append("<div class='panorama-control'><a href='#' class='panorama-control-left'><<</a> <a href='#' class='panorama-control-pause'>x</a> <a href='#' class='panorama-control-right'>>></a> </div>");
panoramaViewport = panoramaContainer.parent();
panoramaViewport.mousedown(function(e){
if (!bMouseMove) {
bMouseMove = true;
mouseMoveStart = e.clientX;
}
return false;
}).mouseup(function(){
bMouseMove = false;
mouseMoveStart = 0;
return false;
}).mousemove(function(e){
if (bMouseMove){
var delta = parseInt((mouseMoveStart - e.clientX)/30);
if ((delta>10) || (delta<10)) {
var newMarginLeft = parseInt(panoramaContainer.css('marginLeft')) + (delta);
if (settings.mode_360) {
if (newMarginLeft > 0) {newMarginLeft = -elemWidth;}
if (newMarginLeft < -elemWidth) {newMarginLeft = 0;}
} else {
if (newMarginLeft > 0) {newMarginLeft = 0;}
if (newMarginLeft < -elemWidth) {newMarginLeft = -elemWidth;}
}
panoramaContainer.css('marginLeft', newMarginLeft+'px');
}
}
}).bind('contextmenu',function(){return false;});
panoramaViewport.css('height', elemHeight+'px').css('overflow', 'hidden').find('a.panorama-control-left').bind('click', function() {
$(panoramaContainer).stop();
settings.direction = 'right';
panorama_animate(panoramaContainer, elemWidth, settings);
return false;
});
panoramaViewport.bind('click', function() {
$(panoramaContainer).stop();
});
panoramaViewport.find('a.panorama-control-right').bind('click', function() {
$(panoramaContainer).stop();
settings.direction = 'left';
panorama_animate(panoramaContainer, elemWidth, settings);
return false;
});
panoramaViewport.find('a.panorama-control-pause').bind('click', function() {
$(panoramaContainer).stop();
return false;
});
if (settings.control_display == 'yes') {
panoramaViewport.find('.panorama-control').show();
} else if (settings.control_display == 'auto') {
panoramaViewport.bind('mouseover', function(){
$(this).find('.panorama-control').show();
return false;
}).bind('mouseout', function(){
$(this).find('.panorama-control').hide();
return false;
});
}
$(this).parent().css('margin-left', '-'+settings.start_position+'px');
if (settings.auto_start)
panorama_animate(panoramaContainer, elemWidth, settings);
});
function panorama_animate(element, elemWidth, settings) {
currentPosition = 0-parseInt($(element).css('margin-left'));
if (settings.direction == 'right') {
$(element).animate({marginLeft: 0}, ((settings.speed / elemWidth) * (currentPosition)) , 'linear', function (){
if (settings.mode_360) {
$(element).css('marginLeft', '-'+(parseInt(parseInt(elemWidth))+'px'));
panorama_animate(element, elemWidth, settings);
}
});
} else {
var rightlimit;
if (settings.mode_360)
rightlimit = elemWidth;
else
rightlimit = elemWidth-settings.viewport_width;
$(element).animate({marginLeft: -rightlimit}, ((settings.speed / rightlimit) * (rightlimit - currentPosition)), 'linear', function (){
if (settings.mode_360) {
$(element).css('margin-left', 0);
panorama_animate(element, elemWidth, settings);
}
});
}
}
};
$(document).ready(function(){
$("img.panorama").panorama();
});
in})(jQuery);
https://jsfiddle.net/pm6swLxa/
You code use css animations
HTML
<div id="img_container" class="pano slide"></div>
CSS
#img_container {
width:400px;
height: 200px;
overflow: hidden;
background: url('http://www.the-farm.net/piccies/pano2.jpg');
background-size: auto 100%;
background-position: right;
animation: back-and-forth 5s infinite;
}
#keyframes back-and-forth {
0% {
background-position: right;
}
50% {
background-position: left;
}
100% {
background-position: right;
}
}
I'm creating an animation of a ring rotating.
On hover the right rotates 180 degrees, pauses and rotates back to the starting position. If the user removes the cursor off the ring while its animating it needs to reverse from the frame its currently on.
I haven't had much extensive experience with animation in my career as a front end developer so any advice on tech to use would be appreciated.
Currently I'm using CSS Animation with a sprite, as below but it lacks the ability to reverse from the frame it was on when the user leaves the ring.
Here is my working example, It's inspired by http://renren.com/
Example using CSS
$('body').on('mouseenter', '.item', function() {
$(this).removeClass('unactive').addClass('active');
});
$('body').on('mouseleave', '.item', function() {
$(this).removeClass('active').addClass('unactive');
});
.content {
width: 150px;
height: 150px;
background-color: #EBEBEB;
}
.content.ring {
background: url(http://a.xnimg.cn/nx/apps/login/cssimg/qrcode1-t.jpg) 0 0 no-repeat
}
.active .content {
background-position: 0 -1800px;
-moz-animation: movedown 2000ms steps(12) forwards;
-webkit-animation: movedown 2000ms steps(12) forwards
}
.unactive .content {
-moz-animation: moveup 2000ms steps(7) forwards;
-webkit-animation: moveup 2000ms steps(7) forwards
}
#-moz-keyframes movedown {
0% {
background-position: 0 0
}
100% {
background-position: 0 -1800px
}
}
#-moz-keyframes moveup {
0% {
background-position: 0 -1800px
}
100% {
background-position: 0 -2850px
}
}
#-webkit-keyframes movedown {
0% {
background-position: 0 0
}
100% {
background-position: 0 -1800px
}
}
#-webkit-keyframes moveup {
0% {
background-position: 0 -1800px
}
100% {
background-position: 0 -2850px
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HTML
<div class="item active">
<div class="content ring">
</div>
</div>
I've also found plugins like:
motio
So my question is, is CSS able to have this much control or would a CANVAS or other jQuery plugin be better suited?
EDIT
I'm still having difficulties figuring this one out although I started writing a script to help control the animation.
I'm trying to control the background position to gain control of the sprite rotating.
Example using Javascript
;(function($) {
var Ring = function (options) {
// context
var self = this;
// defaults
var currFrame = 1, totalFrames, width, height, timeout;
// default frame array
var framesObj = {};
// option defaults
self.class = "";
self.spriteHeight = "";
//properties based on options
if (typeof options != 'undefined' && options != undefined && options != null)
{
self.class = options.class;
self.spriteHeight = options.spriteHeight;
self.speed = options.speed;
}
// fire off everything you need
self.init = function ()
{
self.buildArr();
}
// check for the container dimentions
self.frameDimentions = function ()
{
// double check we have a class to select the container with
var container = self.class ? true : false;
// I know I could just write self.class in the if..
if ( container )
{
var container = $("." + self.class + "");
var containerHeight = container.outerHeight();
var containerWidth = container.outerWidth();
return [containerHeight,containerWidth];
}
console.log("Please provide a class");
}
// calculate frames e.g. 3000 into 150 per frame is 20..
self.calcFrames = function()
{
var totalFrames = parseInt(self.spriteHeight) / self.frameDimentions()[0];
return totalFrames;
}
self.buildArr = function()
{
// these values need to be pushed in to the arr
for (var i = 0; i < self.calcFrames(); i++) {
framesObj[(i+1)] = self.frameDimentions()[0]*i;
}
}
self.startForwardAnimation = function(){
// to stop manic clicking../hover..
if( currFrame <= 1 )
{
timeout = setInterval( updateFrameForward, self.speed);
}
}
self.startBackwardAnimation = function(){
// to stop manic clicking../hover..
console.log("start backward animation");
if( currFrame != 1 )
{
backTimeout = setInterval( updateFrameBackward, self.speed);
}
}
self.stopAnimation = function(){
//currFrame = 1;
clearTimeout(timeout);
}
self.reset = function(){
clearTimeout(timeout);
clearTimeout(backTimeout);
currFrame = 1;
}
self.info = function(){
$('.info').html(currFrame);
}
// if currFrame less than total frames
// add one to it
// update the current frame variable
// stop and clear timer when reach the end
function updateFrameForward(){
//check if we are in available frames..
if ( currFrame == self.calcFrames() )
{
self.stopAnimation();
self.reset();
}
$("." + self.class + "").css({
'background-position-y': "-" + framesObj[currFrame] + "px"
});
self.info();
currFrame = currFrame + 1;
}
function updateFrameBackward(){
if( currFrame <= 1 )
{
self.stopAnimation();
self.reset();
}
$("." + self.class + "").css({
'background-position-y': framesObj[currFrame] + "px"
});
self.info();
console.log(currFrame);
currFrame = currFrame - 1;
}
}
var ringAniamtion = new Ring({
class: "animate",
spriteHeight: "3000",
speed: "20"
});
$('body').on('mouseenter', '.animate', function(event){
event.preventDefault();
console.log("mouse enter");
ringAniamtion.buildArr();
ringAniamtion.startForwardAnimation();
});
$('body').on('mouseleave', '.animate', function(event){
event.preventDefault();
console.log("mouse leave");
ringAniamtion.stopAnimation();
ringAniamtion.startBackwardAnimation();
});
$('body').on('click', '.stop', function(event){
event.preventDefault();
ringAniamtion.reset();
});
})( jQuery );
// timeout = setTimeout('timeout_trigger()', 3000);
// clearTimeout(timeout);
.content
{
width: 150px;
height: 150px;
background: url(http://a.xnimg.cn/nx/apps/login/cssimg/qrcode1-t.jpg) 0 0 no-repeat;
cursor: pointer;
}
<div class="content animate">
</div>
<div class="info">
</div>
stop
I figured out how to do it in the second code snippet..
;(function($) {
var Ring = function (options) {
// context
var self = this;
// defaults
var currFrame = 1, totalFrames, width, height, timeout;
// default frame array
var framesObj = {};
// option defaults
self.class = "";
self.spriteHeight = "";
//properties based on options
if (typeof options != 'undefined' && options != undefined && options != null)
{
self.class = options.class;
self.spriteHeight = options.spriteHeight;
self.speed = options.speed;
}
// fire off everything you need
self.init = function ()
{
self.buildArr();
}
// check for the container dimentions
self.frameDimentions = function ()
{
// double check we have a class to select the container with
var container = self.class ? true : false;
// I know I could just write self.class in the if..
if ( container )
{
var container = $("." + self.class + "");
var containerHeight = container.outerHeight();
var containerWidth = container.outerWidth();
return [containerHeight,containerWidth];
}
console.log("Please provide a class");
}
// calculate frames e.g. 3000 into 150 per frame is 20..
self.calcFrames = function()
{
var totalFrames = parseInt(self.spriteHeight) / self.frameDimentions()[0];
return totalFrames;
}
self.buildArr = function()
{
// these values need to be pushed in to the arr
for (var i = 0; i < self.calcFrames(); i++) {
framesObj[(i+1)] = self.frameDimentions()[0]*i;
}
}
self.startForwardAnimation = function(){
// to stop manic clicking../hover..
if( currFrame <= 1 )
{
timeout = setInterval( updateFrameForward, self.speed);
}
}
self.startBackwardAnimation = function(){
// to stop manic clicking../hover..
console.log("start backward animation");
if( currFrame != 1 )
{
backTimeout = setInterval( updateFrameBackward, self.speed);
}
}
self.stopAnimation = function(){
//currFrame = 1;
clearTimeout(timeout);
}
self.reset = function(){
clearTimeout(timeout);
clearTimeout(backTimeout);
currFrame = 1;
}
self.info = function(){
$('.info').html(currFrame);
}
// if currFrame less than total frames
// add one to it
// update the current frame variable
// stop and clear timer when reach the end
function updateFrameForward(){
//check if we are in available frames..
if ( currFrame == self.calcFrames() )
{
self.stopAnimation();
self.reset();
}
$("." + self.class + "").css({
'background-position-y': "-" + framesObj[currFrame] + "px"
});
self.info();
currFrame = currFrame + 1;
}
function updateFrameBackward(){
if( currFrame <= 1 )
{
self.stopAnimation();
self.reset();
}
$("." + self.class + "").css({
'background-position-y': framesObj[currFrame] + "px"
});
self.info();
console.log(currFrame);
currFrame = currFrame - 1;
}
}
var ringAniamtion = new Ring({
class: "animate",
spriteHeight: "3000",
speed: "20"
});
$('body').on('mouseenter', '.animate', function(event){
event.preventDefault();
console.log("mouse enter");
ringAniamtion.buildArr();
ringAniamtion.startForwardAnimation();
});
$('body').on('mouseleave', '.animate', function(event){
event.preventDefault();
console.log("mouse leave");
ringAniamtion.stopAnimation();
ringAniamtion.startBackwardAnimation();
});
$('body').on('click', '.stop', function(event){
event.preventDefault();
ringAniamtion.reset();
});
})( jQuery );
For page loader i have used the plugin. Following is js:
var QueryLoader = {
overlay: "",
loadBar: "",
preloader: "",
items: new Array(),
doneStatus: 0,
doneNow: 0,
selectorPreload: "body",
ieLoadFixTime: 2000,
ieTimeout: "",
init: function() {
if (navigator.userAgent.match(/MSIE (\d+(?:\.\d+)+(?:b\d*)?)/) == "MSIE 6.0,6.0") {
//break if IE6
return false;
}
if (QueryLoader.selectorPreload == "body") {
QueryLoader.spawnLoader();
QueryLoader.getImages(QueryLoader.selectorPreload);
QueryLoader.createPreloading();
} else {
$(document).ready(function() {
QueryLoader.spawnLoader();
QueryLoader.getImages(QueryLoader.selectorPreload);
QueryLoader.createPreloading();
});
}
//help IE drown if it is trying to die :)
QueryLoader.ieTimeout = setTimeout("QueryLoader.ieLoadFix()", QueryLoader.ieLoadFixTime);
},
ieLoadFix: function() {
var ie = navigator.userAgent.match(/MSIE (\d+(?:\.\d+)+(?:b\d*)?)/);
if (ie[0].match("MSIE")) {
while ((100 / QueryLoader.doneStatus) * QueryLoader.doneNow < 100) {
QueryLoader.imgCallback();
}
}
},
imgCallback: function() {
QueryLoader.doneNow ++;
QueryLoader.animateLoader();
},
getImages: function(selector) {
var everything = $(selector).find("*:not(script)").each(function() {
var url = "";
if ($(this).css("background-image") != "none") {
var url = $(this).css("background-image");
} else if (typeof($(this).attr("src")) != "undefined" && $(this).attr("tagName").toLowerCase() == "img") {
var url = $(this).attr("src");
}
url = url.replace("url(\"", "");
url = url.replace("url(", "");
url = url.replace("\")", "");
url = url.replace(")", "");
if (url.length > 0) {
QueryLoader.items.push(url);
}
});
},
createPreloading: function() {
QueryLoader.preloader = $("<div></div>").appendTo(QueryLoader.selectorPreload);
$(QueryLoader.preloader).css({
height: "0px",
width: "0px",
overflow: "hidden"
});
var length = QueryLoader.items.length;
QueryLoader.doneStatus = length;
for (var i = 0; i < length; i++) {
var imgLoad = $("<img></img>");
$(imgLoad).attr("src", QueryLoader.items[i]);
$(imgLoad).unbind("load");
$(imgLoad).bind("load", function() {
QueryLoader.imgCallback();
});
$(imgLoad).appendTo($(QueryLoader.preloader));
}
},
spawnLoader: function() {
if (QueryLoader.selectorPreload == "body") {
var height = $(window).height();
var width = $(window).width();
var position = "fixed";
} else {
var height = $(QueryLoader.selectorPreload).outerHeight();
var width = $(QueryLoader.selectorPreload).outerWidth();
var position = "absolute";
}
var left = $(QueryLoader.selectorPreload).offset()['left'];
var top = $(QueryLoader.selectorPreload).offset()['top'];
QueryLoader.overlay = $("<div></div>").appendTo($(QueryLoader.selectorPreload));
$(QueryLoader.overlay).addClass("QOverlay");
$(QueryLoader.overlay).css({
position: position,
top: top,
left: left,
width: width + "px",
height: height + "px"
});
QueryLoader.loadBar = $("<div></div>").appendTo($(QueryLoader.overlay));
$(QueryLoader.loadBar).addClass("QLoader");
$(QueryLoader.loadBar).css({
position: "relative",
top: "50%",
width: "0%"
});
},
animateLoader: function() {
var perc = (100 / QueryLoader.doneStatus) * QueryLoader.doneNow;
if (perc > 99) {
$(QueryLoader.loadBar).stop().animate({
width: perc + "%"
}, 500, "linear", function() {
QueryLoader.doneLoad();
});
} else {
$(QueryLoader.loadBar).stop().animate({
width: perc + "%"
}, 500, "linear", function() { });
}
},
doneLoad: function() {
//prevent IE from calling the fix
clearTimeout(QueryLoader.ieTimeout);
//determine the height of the preloader for the effect
if (QueryLoader.selectorPreload == "body") {
var height = $(window).height();
} else {
var height = $(QueryLoader.selectorPreload).outerHeight();
}
//The end animation, adjust to your likings
$(QueryLoader.loadBar).animate({
height: height + "px",
top: 0
}, 500, "linear", function() {
$(QueryLoader.overlay).fadeOut(800);
$(QueryLoader.preloader).remove();
});
}
}
In my html file, I used following Javascript:
<script type='text/javascript'>
QueryLoader.init();
</script>
And css is as following:
.QOverlay {
background-color: #000000;
z-index: 9999;
}
.QLoader {
background-color: #CCCCCC;
height: 1px;
}
I used this for simple example it works well.
But when I used this for my site it is giving error in js file as following:
TypeError: $(...).offset(...) is undefined
var left = $(QueryLoader.selectorPreload).offset()['left'];
So please can you help out from this issue:
Thanks in advance..
Your plugin is not really one. Go see the documentation to see more details.
Anyway, even if it's not a plugin, it could work as an object using some jQuery functions.
First, you shouldn't call the object inside the object function.
IE :
QueryLoader.ieTimeout = setTimeout("QueryLoader.ieLoadFix()", QueryLoader.ieLoadFixTime);
Here, you got your first error which you could have seen in the console. It should be :
this.ieTimeout = setTimeout(this.ieLoadFix, this.ieLoadFixTime);
You can start debugging like this, up to your initial error here.