using 'this' property in jquery to make code reusable - javascript

Hi a have created a code that adds a class when the element comes in view, parallax if you like. however i want the items to come in at different speeds the next slower than the one before. I however cant seem to make this code reusable using the 'this' property so that I don't have to rewrite it for each instance I want to use it.
if (!jQuery('#thumbnail-section-1 #thumbnail-preview.thumbnail-preview-fade-in').hasClass("is-showing")) {
if(wScroll > $('#thumbnail-section-1').offset().top - ($(window).height() / 1.2)) {
$('#thumbnail-section-1 #thumbnail-preview.thumbnail-preview-fade-in').each(function(i){
setTimeout(function(){
$('#thumbnail-preview.thumbnail-preview-fade-in').eq(i).addClass('is-showing');
}, (700 * (Math.exp(i * 0.35))) - 700);
setTimeout(function(){
$('#thumbnail-section-1 .overlay2 h2').eq(i).addClass('showing');
}, (700 * (Math.exp(i * 0.35))) - 700);
});
}
}

There's no real need to use this since your .each call can also pass the current element:
var $sect = $('#thumbnail-section-1');
var $sel = $sect.find('#thumbnail-preview.thumbnail-preview-fade-in');
var $h2 = $sect.find('.overlay2 h2');
if (!$sel.hasClass('is-showing')) {
if (wScroll > $sect.offset().top - ($(window).height() / 1.2)) {
$sel.each(function(i, el) { // <-- here
var delay = 700 * (Math.exp(i * 0.35) - 1);
setTimeout(function() {
$(el).addClass('is-showing');
$h2.eq(i).addClass('showing');
}, delay);
});
}
}

Related

How to fix jQuery Image Sequence on Scroll

I try to implement a javascript function that animate an image sequence while scrolling.
I try to create the animation with the script from this link: https://www.jqueryscript.net/animation/jQuery-Plugin-To-Create-Image-Sequence-Animation-On-Scroll-Sequencer.html
My problem is that this script is already three years old and does not work with jQuery 3.2.1. But I have to use this much newer jQuery version.
The code of the script looks like this:
/**
* jQuery-Sequencer
* https://github.com/skruf/jQuery-sequencer
*
* Created by Thomas Låver
* http://www.laaver.com
*
* Version: 2.0.0
* Requires: jQuery 1.6+
*
*/
(function($) {
$.fn.sequencer = function(options, cb) {
var self = this,
paths = [],
load = 0,
sectionHeight,
windowHeight,
currentScroll,
percentageScroll,
index;
if(options.path.substr(-1) === "/") {
options.path = options.path.substr(0, options.path.length - 1)
}
for (var i = 0; i <= options.count; i++) {
paths.push(options.path + "/" + i + "." + options.ext);
}
$("<div class='jquery-sequencer-preload'></div>").appendTo("body").css("display", "none");
$(paths).each(function() {
$("<img>").attr("src", this).load(function() {
$(this).appendTo("div.jquery-sequencer-preload");
load++;
if (load === paths.length) {
cb();
}
});
});
$(window).scroll(function() {
sectionHeight = $(self).height();
windowHeight = $(this).height();
currentScroll = $(this).scrollTop();
percentageScroll = 100 * currentScroll / (sectionHeight - windowHeight);
index = Math.round(percentageScroll / 100 * options.count);
if(index < options.count) {
$("img.sequencer").attr("src", paths[index]);
}
});
return this;
};
}(jQuery));
So I already changed the line 37 from
$("<img>").attr("src", this).load(function() {
to
$("<img>").attr("src", this).on("load", function() {
With this change all my images are loaded but I still get the error message: Uncaught TypeError: cb is not a function
What do I have to change as well, so the script is working again?
Thanks for any tip.
cb() is a Callback function will be called once the preloader is done fetching images.
From the example you have linked to, the callback is:
function() {
$("div#preload").hide();
}
which quite simply hides the preloader message.
In context, the plugin is initialised as:
$("div#images").sequencer({
count: 128,
path: "./images",
ext: "jpg"
}, function() {
$("div#preload").hide();
});
As you have not supplied how you are calling this function, I suspect you are missing this function callback.

scroll to anchor without jquery or smoothscroll [duplicate]

I want to have 4 buttons/links on the beginning of the page, and under them the content.
On the buttons I put this code:
Scroll to element 1
Scroll to element 2
Scroll to element 3
Scroll to element 4
And under links there will be content:
<h2 id="idElement1">Element1</h2>
content....
<h2 id="idElement2">Element2</h2>
content....
<h2 id="idElement3">Element3</h2>
content....
<h2 id="idElement4">Element4</h2>
content....
It is working now, but cannot make it look more smooth.
I used this code, but cannot get it to work.
$('html, body').animate({
scrollTop: $("#elementID").offset().top
}, 2000);
Any suggestions? Thank you.
Edit: and the fiddle: http://jsfiddle.net/WxJLx/2/
Super smoothly with requestAnimationFrame
For smoothly rendered scrolling animation one could use window.requestAnimationFrame() which performs better with rendering than regular setTimeout() solutions.
A basic example looks like this. Function step is called for browser's every animation frame and allows for better time management of repaints, and thus increasing performance.
function doScrolling(elementY, duration) {
var startingY = window.pageYOffset;
var diff = elementY - startingY;
var start;
// Bootstrap our animation - it will get called right before next frame shall be rendered.
window.requestAnimationFrame(function step(timestamp) {
if (!start) start = timestamp;
// Elapsed milliseconds since start of scrolling.
var time = timestamp - start;
// Get percent of completion in range [0, 1].
var percent = Math.min(time / duration, 1);
window.scrollTo(0, startingY + diff * percent);
// Proceed with animation as long as we wanted it to.
if (time < duration) {
window.requestAnimationFrame(step);
}
})
}
For element's Y position use functions in other answers or the one in my below-mentioned fiddle.
I set up a bit more sophisticated function with easing support and proper scrolling to bottom-most elements:
https://jsfiddle.net/s61x7c4e/
Question was asked 5 years ago and I was dealing with smooth scroll and felt giving a simple solution is worth it to those who are looking for. All the answers are good but here you go a simple one.
function smoothScroll(){
document.querySelector('.your_class or #id here').scrollIntoView({
behavior: 'smooth'
});
}
just call the smoothScroll function on onClick event on your source element.
DOCS: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Note: Please check compatibility here
3rd Party edit
Support for Element.scrollIntoView() in 2020 is this:
Region full + partial = sum full+partial Support
Asia 73.24% + 22.75% = 95.98%
North America 56.15% + 42.09% = 98.25%
India 71.01% + 20.13% = 91.14%
Europe 68.58% + 27.76% = 96.35%
Just made this javascript only solution below.
Simple usage:
EPPZScrollTo.scrollVerticalToElementById('signup_form', 20);
Engine object (you can fiddle with filter, fps values):
/**
*
* Created by Borbás Geri on 12/17/13
* Copyright (c) 2013 eppz! development, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
var EPPZScrollTo =
{
/**
* Helpers.
*/
documentVerticalScrollPosition: function()
{
if (self.pageYOffset) return self.pageYOffset; // Firefox, Chrome, Opera, Safari.
if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop; // Internet Explorer 6 (standards mode).
if (document.body.scrollTop) return document.body.scrollTop; // Internet Explorer 6, 7 and 8.
return 0; // None of the above.
},
viewportHeight: function()
{ return (document.compatMode === "CSS1Compat") ? document.documentElement.clientHeight : document.body.clientHeight; },
documentHeight: function()
{ return (document.height !== undefined) ? document.height : document.body.offsetHeight; },
documentMaximumScrollPosition: function()
{ return this.documentHeight() - this.viewportHeight(); },
elementVerticalClientPositionById: function(id)
{
var element = document.getElementById(id);
var rectangle = element.getBoundingClientRect();
return rectangle.top;
},
/**
* Animation tick.
*/
scrollVerticalTickToPosition: function(currentPosition, targetPosition)
{
var filter = 0.2;
var fps = 60;
var difference = parseFloat(targetPosition) - parseFloat(currentPosition);
// Snap, then stop if arrived.
var arrived = (Math.abs(difference) <= 0.5);
if (arrived)
{
// Apply target.
scrollTo(0.0, targetPosition);
return;
}
// Filtered position.
currentPosition = (parseFloat(currentPosition) * (1.0 - filter)) + (parseFloat(targetPosition) * filter);
// Apply target.
scrollTo(0.0, Math.round(currentPosition));
// Schedule next tick.
setTimeout("EPPZScrollTo.scrollVerticalTickToPosition("+currentPosition+", "+targetPosition+")", (1000 / fps));
},
/**
* For public use.
*
* #param id The id of the element to scroll to.
* #param padding Top padding to apply above element.
*/
scrollVerticalToElementById: function(id, padding)
{
var element = document.getElementById(id);
if (element == null)
{
console.warn('Cannot find element with id \''+id+'\'.');
return;
}
var targetPosition = this.documentVerticalScrollPosition() + this.elementVerticalClientPositionById(id) - padding;
var currentPosition = this.documentVerticalScrollPosition();
// Clamp.
var maximumScrollPosition = this.documentMaximumScrollPosition();
if (targetPosition > maximumScrollPosition) targetPosition = maximumScrollPosition;
// Start animation.
this.scrollVerticalTickToPosition(currentPosition, targetPosition);
}
};
Smooth scrolling - look ma no jQuery
Based on an article on itnewb.com i made a demo plunk to smoothly scroll without external libraries.
The javascript is quite simple. First a helper function to improve cross browser support to determine the current position.
function currentYPosition() {
// Firefox, Chrome, Opera, Safari
if (self.pageYOffset) return self.pageYOffset;
// Internet Explorer 6 - standards mode
if (document.documentElement && document.documentElement.scrollTop)
return document.documentElement.scrollTop;
// Internet Explorer 6, 7 and 8
if (document.body.scrollTop) return document.body.scrollTop;
return 0;
}
Then a function to determine the position of the destination element - the one where we would like to scroll to.
function elmYPosition(eID) {
var elm = document.getElementById(eID);
var y = elm.offsetTop;
var node = elm;
while (node.offsetParent && node.offsetParent != document.body) {
node = node.offsetParent;
y += node.offsetTop;
} return y;
}
And the core function to do the scrolling
function smoothScroll(eID) {
var startY = currentYPosition();
var stopY = elmYPosition(eID);
var distance = stopY > startY ? stopY - startY : startY - stopY;
if (distance < 100) {
scrollTo(0, stopY); return;
}
var speed = Math.round(distance / 100);
if (speed >= 20) speed = 20;
var step = Math.round(distance / 25);
var leapY = stopY > startY ? startY + step : startY - step;
var timer = 0;
if (stopY > startY) {
for ( var i=startY; i<stopY; i+=step ) {
setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
leapY += step; if (leapY > stopY) leapY = stopY; timer++;
} return;
}
for ( var i=startY; i>stopY; i-=step ) {
setTimeout("window.scrollTo(0, "+leapY+")", timer * speed);
leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
}
return false;
}
To call it you just do the following. You create a link which points to another element by using the id as a reference for a destination anchor.
<a href="#anchor-2"
onclick="smoothScroll('anchor-2');">smooth scroll to the headline with id anchor-2<a/>
...
... some content
...
<h2 id="anchor-2">Anchor 2</h2>
Copyright
In the footer of itnewb.com the following is written: The techniques, effects and code demonstrated in ITNewb articles may be used for any purpose without attribution (although we recommend it) (2014-01-12)
You could also check this great Blog - with some very simple ways to achieve this :)
https://css-tricks.com/snippets/jquery/smooth-scrolling/
Like (from the blog)
// Scroll to specific values
// scrollTo is the same
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// Scroll certain amounts from current position
window.scrollBy({
top: 100, // could be negative value
left: 0,
behavior: 'smooth'
});
// Scroll to a certain element
document.querySelector('.hello').scrollIntoView({
behavior: 'smooth'
});
and you can also get the element "top" position like below (or some other way)
var e = document.getElementById(element);
var top = 0;
do {
top += e.offsetTop;
} while (e = e.offsetParent);
return top;
Why not use CSS scroll-behavior property
html {
scroll-behavior: smooth;
}
The browser support is also good
https://caniuse.com/#feat=css-scroll-behavior
For a more comprehensive list of methods for smooth scrolling, see my answer here.
To scroll to a certain position in an exact amount of time, window.requestAnimationFrame can be put to use, calculating the appropriate current position each time. To scroll to an element, just set the y-position to element.offsetTop.
/*
#param pos: the y-position to scroll to (in pixels)
#param time: the exact amount of time the scrolling will take (in milliseconds)
*/
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
Demo:
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
document.getElementById("toElement").addEventListener("click", function(e){
scrollToSmoothly(document.querySelector('div').offsetTop, 500 /* milliseconds */);
});
document.getElementById("backToTop").addEventListener("click", function(e){
scrollToSmoothly(0, 500);
});
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
<button id="backToTop">Scroll back to top</button>
</div>
The SmoothScroll.js library can also be used, which supports scrolling to an element on the page in addition to more complex features such as smooth scrolling both vertically and horizontally, scrolling inside other container elements, different easing behaviors, scrolling relatively from the current position, and more.
document.getElementById("toElement").addEventListener("click", function(e){
smoothScroll({toElement: document.querySelector('div'), duration: 500});
});
document.getElementById("backToTop").addEventListener("click", function(e){
smoothScroll({yPos: 'start', duration: 500});
});
<script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll#1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script>
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
<button id="backToTop">Scroll back to top</button>
</div>
Alternatively, you can pass an options object to window.scroll which scrolls to a specific x and y position and window.scrollBy which scrolls a certain amount from the current position:
// Scroll to specific values
// scrollTo is the same
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// Scroll certain amounts from current position
window.scrollBy({
top: 100, // could be negative value
left: 0,
behavior: 'smooth'
});
If you only need to scroll to an element, not a specific position in the document, you can use Element.scrollIntoView with behavior set to smooth.
document.getElementById("elemID").scrollIntoView({
behavior: 'smooth'
});
I've been using this for a long time:
function scrollToItem(item) {
var diff=(item.offsetTop-window.scrollY)/8
if (Math.abs(diff)>1) {
window.scrollTo(0, (window.scrollY+diff))
clearTimeout(window._TO)
window._TO=setTimeout(scrollToItem, 30, item)
} else {
window.scrollTo(0, item.offsetTop)
}
}
usage:
scrollToItem(element) where element is document.getElementById('elementid') for example.
Variation of #tominko answer.
A little smoother animation and resolved problem with infinite invoked setTimeout(), when some elements can't allign to top of viewport.
function scrollToItem(item) {
var diff=(item.offsetTop-window.scrollY)/20;
if(!window._lastDiff){
window._lastDiff = 0;
}
console.log('test')
if (Math.abs(diff)>2) {
window.scrollTo(0, (window.scrollY+diff))
clearTimeout(window._TO)
if(diff !== window._lastDiff){
window._lastDiff = diff;
window._TO=setTimeout(scrollToItem, 15, item);
}
} else {
console.timeEnd('test');
window.scrollTo(0, item.offsetTop)
}
}
you can use this plugin. Does exactly what you want.
http://flesler.blogspot.com/2007/10/jqueryscrollto.html
If one need to scroll to an element inside a div there is my solution based on Andrzej Sala's answer:
function scroolTo(element, duration) {
if (!duration) {
duration = 700;
}
if (!element.offsetParent) {
element.scrollTo();
}
var startingTop = element.offsetParent.scrollTop;
var elementTop = element.offsetTop;
var dist = elementTop - startingTop;
var start;
window.requestAnimationFrame(function step(timestamp) {
if (!start)
start = timestamp;
var time = timestamp - start;
var percent = Math.min(time / duration, 1);
element.offsetParent.scrollTo(0, startingTop + dist * percent);
// Proceed with animation as long as we wanted it to.
if (time < duration) {
window.requestAnimationFrame(step);
}
})
}
Why not use this easy way
Native JS
document.querySelector(".layout").scrollIntoView({
behavior: "smooth",
});
Smooth scrolling with jQuery.ScrollTo
To use the jQuery ScrollTo plugin you have to do the following
Create links where href points to another elements.id
create the elements you want to scroll to
reference jQuery and the scrollTo Plugin
Make sure to add a click event handler for each link that should do smooth scrolling
Creating the links
<h1>Smooth Scrolling with the jQuery Plugin .scrollTo</h1>
<div id="nav-list">
Scroll to element 1
Scroll to element 2
Scroll to element 3
Scroll to element 4
</div>
Creating the target elements here only the first two are displayed the other headings are set up the same way. To see another example i added a link back to the navigation a.toNav
<h2 id="idElement1">Element1</h2>
....
<h2 id="idElement1">Element1</h2>
...
<a class="toNav" href="#nav-list">Scroll to Nav-List</a>
Setting the references to the scripts. Your path to the files may be different.
<script src="./jquery-1.8.3.min.js"></script>
<script src="./jquery.scrollTo-1.4.3.1-min.js"></script>
Wiring it all up
The code below is borrowed from jQuery easing plugin
jQuery(function ($) {
$.easing.elasout = function (x, t, b, c, d) {
var s = 1.70158; var p = 0; var a = c;
if (t == 0) return b;
if ((t /= d) == 1) return b + c;
if (!p) p = d * .3;
if (a < Math.abs(c)) {
a = c; var s = p / 4;
} else var s = p / (2 * Math.PI) * Math.asin(c / a);
// line breaks added to avoid scroll bar
return a * Math.pow(2, -10 * t) * Math.sin((t * d - s)
* (2 * Math.PI) / p) + c + b;
};
// important reset all scrollable panes to (0,0)
$('div.pane').scrollTo(0);
$.scrollTo(0); // Reset the screen to (0,0)
// adding a click handler for each link
// within the div with the id nav-list
$('#nav-list a').click(function () {
$.scrollTo(this.hash, 1500, {
easing: 'elasout'
});
return false;
});
// adding a click handler for the link at the bottom
$('a.toNav').click(function () {
var scrollTargetId = this.hash;
$.scrollTo(scrollTargetId, 1500, {
easing: 'elasout'
});
return false;
});
});
Fully working demo on plnkr.co
You may take a look at the soucre code for the demo.
Update May 2014
Based on another question i came across another solution from kadaj. Here jQuery animate is used to scroll to an element inside a <div style=overflow-y: scroll>
$(document).ready(function () {
$('.navSection').on('click', function (e) {
debugger;
var elemId = ""; //eg: #nav2
switch (e.target.id) {
case "nav1":
elemId = "#s1";
break;
case "nav2":
elemId = "#s2";
break;
case "nav3":
elemId = "#s3";
break;
case "nav4":
elemId = "#s4";
break;
}
$('.content').animate({
scrollTop: $(elemId).parent().scrollTop()
+ $(elemId).offset().top
- $(elemId).parent().offset().top
}, {
duration: 1000,
specialEasing: { width: 'linear'
, height: 'easeOutBounce' },
complete: function (e) {
//console.log("animation completed");
}
});
e.preventDefault();
});
});

get object position as specified in CSS to modify in jQuery

First question, so please let me know if I could/should be asking this more succinctly/clearly...
I'm working on an experimental script that vibrates objects with a given class with increasing intensity over time. I'm working with jRumble as a base. My script needs to get the initial CSS position of objects to be vibrated and then add the modifying var. I set this up like so at first:
$this.animate({
'left': parseFloat($this.css( "left" )) + rx + 'px',
which works great in Chrome, but Safari and iOS return different values. This explained the problem: jquery $('selector').css('top') returns different values for IE, firefox and Chrome, so I switched to using .offset:
offset = $(".offreg").offset();
...
'left': offset.left + rx + 'px',
but this is problematic because the script iterates-- .offset returns the current position each time instead of the initial one. I tried placing the var outside of the iterating section, but this (obviously) doesn't work because it is no longer associated with the "this" of the rumble script. The var is then set at the value of the first element with class .offreg.
The page itself is here: http://sallymaier.github.io/off-register/
I'm going to revert to the last version that worked in Chrome. My github is public, so you can see my mess-making there I think.
Full script as it works in Chrome below:
var offRegister = function() {
if (!($ = window.jQuery)) { // see if jQuery is already called, if not, calling script
script = document.createElement( 'script' );
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
script.onload=runRumbler;
document.body.appendChild(script);
}
else {
runRumbler();
}
function runRumbler() {
$(document).ready(function(){
var count = 0;
$(function addone(){
count = count+1;
(function($) {
$.fn.jrumble = function(options){ // jRumble by Jack Rugile. http://jackrugile.com/jrumble/
/*========================================================*/
/* Options
/*========================================================*/
var defaults = {
x: count/5,
y: count/5,
rotation: 0,
speed: 200,
opacity: false,
opacityMin: .5
},
opt = $.extend(defaults, options);
return this.each(function(){
/*========================================================*/
/* Variables
/*========================================================*/
var $this = $(this),
x = opt.x*2,
y = opt.y*2,
rot = opt.rotation*2,
speed = (opt.speed === 0) ? 1 : opt.speed,
opac = opt.opacity,
opacm = opt.opacityMin,
inline,
interval;
/*========================================================*/
/* Rumble Function
/*========================================================*/
var rumbler = function(){
var rx = Math.floor(Math.random() * (x+1)) -x/2,
ry = Math.floor(Math.random() * (y+1)) -y/2,
rrot = Math.floor(Math.random() * (rot+1)) -rot/2,
ropac = opac ? Math.random() + opacm : 1;
/*========================================================*/
/* Ensure Movement From Original Position
/*========================================================*/
rx = (rx === 0 && x !== 0) ? ((Math.random() < .5) ? 1 : -1) : rx;
ry = (ry === 0 && y !== 0) ? ((Math.random() < .5) ? 1 : -1) : ry;
/*========================================================*/
/* Check Inline
/*========================================================*/
if($this.css('display') === 'inline'){
inline = true;
$this.css('display', 'inline-block');
}
/*========================================================*/
/* Rumble Element
/*========================================================*/
$this.animate({
'left': parseFloat($this.css( "left" )) + rx + 'px', // move from declared position
'top': parseFloat($this.css( "top" )) + ry+'px',
'-ms-filter':'progid:DXImageTransform.Microsoft.Alpha(Opacity='+ropac*100+')',
'filter':'alpha(opacity='+ropac*100+')',
'-moz-opacity':ropac,
'-khtml-opacity':ropac,
'opacity':ropac,
'-webkit-transform':'rotate('+rrot+'deg)',
'-moz-transform':'rotate('+rrot+'deg)',
'-ms-transform':'rotate('+rrot+'deg)',
'-o-transform':'rotate('+rrot+'deg)',
'transform':'rotate('+rrot+'deg)'
});
}; /* close rumble function */
/*========================================================*/
/* Rumble CSS Reset
/*========================================================*/
var reset = {
'left':0,
'top':0,
'-ms-filter':'progid:DXImageTransform.Microsoft.Alpha(Opacity=100)',
'filter':'alpha(opacity=100)',
'-moz-opacity':1,
'-khtml-opacity':1,
'opacity':1,
'-webkit-transform':'rotate(0deg)',
'-moz-transform':'rotate(0deg)',
'-ms-transform':'rotate(0deg)',
'-o-transform':'rotate(0deg)',
'transform':'rotate(0deg)'
};
/*========================================================*/
/* Rumble Start/Stop Trigger
/*========================================================*/
$this.bind({
'startRumble': function(e){
e.stopPropagation();
clearInterval(interval);
interval = setInterval(rumbler, speed)
},
'stopRumble': function(e){
e.stopPropagation();
clearInterval(interval);
if(inline){
$this.css('display', 'inline');
}
$this.css(reset);
}
});
});// End return this.each
};// End $.fn.jrumble
})(jQuery);
/*===============================================================*/
/* Specify selector to vibrate below.
/* For bookmarklet, 'div' will vibrate all elements,
/* in plugin this can be specifically targeted to a class or id.
/*===============================================================*/
$('.offreg').jrumble();
$('.offreg').trigger('startRumble');
setTimeout(addone, 1000); // how many seconds to wait before adding to count, increasing vibration
}); // end addone()
});
};
};
offRegister();
I've been playing around with this source code the last couple minutes, and it seems to me the problem stems from the use of position: absolute on the rumbling elements themselves. In the jRumble docs http://jackrugile.com/jrumble/#documentation it says that 'For rumble elements that are position fixed/absolute, they should instead be wrapped in an element that is fixed/absolute'.
So if you set your container element to position: absolute and then position all the interior divs relative to the container, you'll no longer need to alter the jRumble source code and redefine the plugin every iteration to change the default position or compute the offset of each element - all you'll have to do is increment the x and y values in the jRumble call itself.
The code below is UNTESTED, but I think you want something closer to this (again, this all hinges on the .offreg elements being position: relative):
$(document).ready(function(){
var count = 0;
function addone(){
count++;
$('.offreg').jrumble({
x: count,
y: count,
rotation: 1
});
$('.offreg').trigger('startRumble');
setTimeout(addone, 1000);
}
});
I like Sean's answer of sidestepping the need for adding code to override $.fn.jrumble, which creates a brittle maintenance point and makes $.fn.jrumble unusable outside this code block (since it depends on the variable "count").
For the immediate issue of the variable scope, if you still need to solve that problem, I'd suggest moving the redefinition of $.fn.jrumble out of addone(), and then scoping a variable, "offset", outside of said redefinition. Then refer to that variable in your call to $this.animate(). Code is below, but again, Sean's answer should make this unnecessary.
var offRegister = function() {
if (!($ = window.jQuery)) { // see if jQuery is already called, if not, calling script
script = document.createElement( 'script' );
script.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js';
script.onload=runRumbler;
document.body.appendChild(script);
}
else {
runRumbler();
}
};
function runRumbler() {
$(document).ready(function(){
var count = 0;
var offset;
function addone() {
...
$('.offreg').jrumble();
$('.offreg').trigger('startRumble');
offset = $('.offreg').offset();
setTimeout(addone, 1000); // how many seconds to wait before adding to
}
(function($){
$.fn.jrumble = function(options){
...
$this.animate({
'left': parseFloat(offset) + rx + 'px',
...
});
...
};
)(jQuery);
...
}
offRegister();
Another suggestion: make the whole thing an anonymous function. Instead of:
var offRegister = function() {
...
}
offRegister();
Try:
(function(){
...
})();
That way you don't stick a variable "offRegister" in the global namespace. In this case, doing so isn't a problem, but in general code that you want to reuse elsewhere is cleaner if it doesn't introduce new globals.

Proper deleting HTML DOM nodes

I'm trying to create a star shining animation.
function ShowStars()
{
//if ($('img.star').length > 5)
// return;
var x = Math.floor(Math.random() * gameAreaWidth) - 70;
var y = Math.floor(Math.random() * gameAreaHeight);
var star = document.createElement("img");
star.setAttribute("class", "star");
star.setAttribute("src", imagesPath + "star" + GetRandom(1, 3) + ".png");
star.style.left = x + "px";
star.style.top = y + "px";
gameArea.appendChild(star);
// Light.
setTimeout(function () { star.setAttribute("class", "star shown"); }, 0);
// Put out.
setTimeout(function () { star.setAttribute("class", "star"); }, 2000);
// Delete.
setTimeout(function () { gameArea.removeChild(star); }, 4000);
setTimeout(function () { ShowStars(); }, 500);
}
It works fine until I uncomment the following code which is supposed to regulate star count:
//if ($('img.star').length > 5)
// return;
Then it stops to work as if the created stars are not removed (the first 5 stars blink then nothing happens). Why do the jQuery selector select them after gameArea.removeChild(star);? Isn't it enough to remove them from the parent node?
Browser: Google Chrome 17.
Regards,
Change the commented out lines to
if ($('img.star').length > 5) {
setTimeout(function () { ShowStars(); }, 500);
return;
}
to keep the ShowStars recursion going.
I see a workaround: do not create stars dynamically, but insert them in HTML (<img id="star1">...<img id="starN">, where N is total count) then light and put out the existing nodes. Nevertheless, I'd like to understand, what's wrong with removing nodes in the question above.

JavaScript make value of variable public

Here is excerpt from my larger JavaScript file:
function dashboardConfig()
{
$(window).on('resize', function () {
var viewport = {
width : $(this).width(),
height : $(this).height()
};
el.siteContainer.css(
{
marginTop : (viewport.height - 652) / 2
});
el.dashboardSlide.css(
{
marginLeft : (viewport.width - 1024) / 2,
marginRight : (viewport.width - 1024) / 2
});
//Calculate how many nav elements
el.navElements.each(function(i)
{
el.dashboard.css(
{
width : viewport.width * (i + 1)
});
$(this).click(function()
{
//HERE IS THE VARIABLE I WOULD LIKE TO USE
var dashboardSlidePosition = viewport.width * i;
el.navElements.removeClass('active');
$(this).addClass('active');
el.dashboard.animate(
{
left : -dashboardSlidePosition
},500, function()
{
el.dashboard.css(
{
left : -dashboardSlidePosition
});
});
});
});
//I WANT TO PERFORM ANOTHER FUNCTION HERE AND HAVE IT USE THE VALUE OF dashboardSlidePosition
}).trigger('resize');
}
I want to know how I can pass the value of the variable, dashboardSlidePosition, to another function. Please can anyone explain how?
Many thanks in advance.
You can declare it at the outer edge of your scope. Make sure to give it an initial value so that you don't try to use it before it has been set properly.
function dashboardConfig()
{
var dashboardSlidePosition = null;
function anotherFunction() {
if (dashboardSlidePosition != null) {
// ...
}
}
$(this).click(function()
{
dashboardSlidePosition = viewport.width * i;
}
}
Put it into the proper scope:
function dashboardConfig()
{
var dashboardSlidePosition = 0;
Next, remove var when redefining it.
Now you can use it because it's in the scope of the function.

Categories

Resources