add/remove shadow via css+javascript - javascript

I have a page with a lot of Div's, and I am using the panzoom jquery script. In order to speed up the page, I would like to disable the shadow on the divs if the page is zoomed out above a specified value, and enable the shadows if the page is zoomed in. currently I have this code, that is beeing called every 0.5 seconds:
function shadow()
{
var $panzoom = $('.panzoom').panzoom();
var matrix = $panzoom.panzoom("getMatrix");
$("#zoomf").html(matrix[0])
//if zoom is bigger than 0.35 enable shadows
if (matrix[0] > 0.35)
{
var $elements = $('.machinebox').addClass('shadow');
var $elements2 = $('.playerbox').addClass('shadow');
}
else
{
$elements.removeClass('shadow');
$elements2.removeClass('shadow');
}
}
The problems I am facing are basically two:
1) the var $elements does not exist Always, it only exists as long as the shadow exists.. thus, if I zoom out, it removes the shadow and then generates a error:
SCRIPT5007: Unable to get property 'removeClass' of undefined or null reference
de (282,3)
2) when it adds/removes the shadows it freezes for about one second. can this be avoided somehow?

The first problem is caused because the variables $element and $element2 are only declared and initialized when the condition is true. The second one seems to be caused because there are a lot of elements which have the classes machinebox and playerbox.
You can fix both of them by using something like this:
function shadow() {
var matrix = $('.panzoom').panzoom("getMatrix");
$("#zoomf").html(matrix[0])
$('.machinebox:visible, .playerbox:visible').toggleClass("shadow", (matrix[0] > 0.35))
}

For point 2 since you've solved point 1.
the function is running every 0.5 seconds, this is probably why you get that delay.
try pausing it until the next time the user zooms (idk if the library you're using allows you to detect such events)

Related

Different values when debugging than in console?

I'm running an Angular application that is returning two distinct values simultaneously. I'm curious if anyone has seen this:
function updateValues() {
var activeNavButton = pageNavButtons.eq(values.currentPage);
pageNavButtons.removeClass("active");
activeNavButton.addClass("active");
pageNavButtons.each(function () {
var forceRender = $(this).get(0).offsetLeft;
});
var w = 0;
$(".pages button").each(function () {
w = w + $(this).outerWidth(true)
});
var b=0;
completeHandler();
}
This is straightforward as can be. Switch which item is "active", and then force a render refresh. You'll notice none of this code is really doing anything, but thats okay. I left out some of the less important, unrelated stuff.
Yep, I'm frustrated enough that I'm trying to force the render refresh in multiple ways at once.
In the chrome debugger, if you break on this line:
var b = 0
the following occurs:
w = 790 //Watcher
However, if you open the console while the script is still at that break point and literally copy and paste the preceding 4 lines:
var w = 0;
$(".pages button").each(function () {
w = w + $(this).outerWidth(true)
});
It returns 800 for the value of w.
An important thing to note: the .active class gives the selected element a "bold" font, thus changing the element width. I'm positive this is related to the problem but I can't for the life of me figure out what the issue really is.
As you can see, I'm accessing offsetWidth to try to force the browser to update the elements but its not working.
Any ideas? This is driving me absolutely insane.
Okay. This may seem dumb but on large code bases it might not be terribly surprising:
Turns out that the button's base CSS class (a ways up in the hierarchy) had a transition: all 150ms on it.
This caused a delay, which caused widths to return incorrectly as you might expect because, and this is the important part, font weight is included in transition all.
Because of this, the font weight would change 150ms later, and those extra couple of pixels of width (in certain cases) would register "late". No wonder my timers seemed to arbitrarily succeed: I was guessing.
Lesson learned: Don't use transition: all unless you have a good reason. Target the things you want to actually transition.
Hope this helps somebody else! Cheers.

JavaScript Div Annimation

I would like to know if there is any specific way to get javaScript code to stop executing at some point so as to allow another called function to execute, for example in a sorting algorithm using Div's you call a function which annimates the swapping of the two Div's so you can visually see the sort taking place. I have tried using the setTimeout(c,t); however it does not seem to be be waiting and the Divs do not seem to be moving, if I however place an alert(""); within the moving code it seems to allow the move to take place with thousands to alerts popping up.
The code I have is as follows:
var q;
var w;
function move(x,y)
{
q = x.style.top; // Keep a reference to the Top divs top element
w = y.style.top; // Keep a reference to the Top divs top element
doMove(x,y);
}
function doMove(topDiv, bottomDiv)
{
//alert("in doMove " + topDiv);
topDiv.style.top = parseInt(topDiv.style.top)+2+'px';
bottomDiv.style.top = parseInt(bottomDiv.style.top)-2+'px';
//alert("hi");
if(bottomDiv.style.top != q && topDiv.style.top != w) // Check if the Top and Bottom divs have finally swapped
{
setTimeout(doMove(topDiv,bottomDiv),20); // call doMove in 20msec
}
}
One problem with your code is that in this line:
setTimeout(doMove(topDiv,bottomDiv),20);
You are calling doMove immediately and passing the value undefined as the first parameter to setTimeout. Not entirely sure that the following will solve your problem, but I would recommend trying this:
setTimeout(function() { doMove(topDiv,bottomDiv); }, 20);

Sprite Animation using a for loop

I am trying to create an animation using a sprite sheet and a for loop to manipulate the background position until it has reached the total number or rows in the sheet. Ideally a reset back to the initial position would be practical, but I cannot even get the animation itself to trigger...
With the current function, no errors occur and the background position in my CSS does not change. I even recorded using Chrome DevTools Timeline and there was nothing either then everything related to my page loading. I have also tried using "background-position-y" as well as a simpler value rather then the math I currently have in place.
This is my function:
$(document).load(function() {
var $height= 324;
var $rows= 34;
for(var i=0; i<$rows; i++){
setTimeout(function() {
$('#selector').css("background-position", "0px ", "0" - ($height*i) + "px");
}, 10);
}
});
I hate to ask a question that is similar to previous issues, but I cannot seem to find another individual attempting sprite sheet animation with a for loop, so I suppose it is it's own problem.
p.s. I didn't include a snippet of my HTML and CSS because it is pretty standard and I don't see how that could be the problem. That being said, I am all ears to any potential thoughts!
I am completely revamping my answer
This issue is that the for() loop is not affected by the setTimeout so the function needs to be written on our own terms, not with a loop
Working Fiddle
Here it is..
var $height= 5;
var $rows= 25;
var i = 1; // Starting Point
(function animateMe(i){
if(i<=$rows){ // Test if var i is less than or equal to number of rows
var newHeight = 0-($height*i)+"px"; // Creat New Height Position
console.log(i); //Testing Purposes - You can Delete
$('#selector').css({"background-position": "0px "+ newHeight}); // Set New Position
i++; // Increment by 1 (For Loop Replacement)
setTimeout(function(){animateMe(i)}, 1000); // Wait 1 Second then Trigger Function
};
})(0);
Here is your solution
First Change
$(document).load() To $(document).ready()
And Change .css Syntex as
$('#selector').css("background-position",'0px '+(0 - ($height*i))+'px');
Here is fiddle Check it ihad implemented it on my recent project http://jsfiddle.net/krunalp1993/7HSFH/
Hope it helps you :)

trigger an event when an element reaches a position on the screen

I would like to trigger some functions according to a position of an element. This element's position changes every tenth second. There is two dozens functions to trigger.
I thought about this pseudo-code :
When element position changes{
Loop through all the coordinates to see if a function can be triggered{
if the current element position matches the function's triggering position
execute the function
}
}
But looping through all possible position each split seconds burdens the browser. So if there is a way to have events to do that.
Is it possible ?
Edit:
After Beetroot-Beetroot comment, I must say that the element that moves only moves on an X abscissa : so just one dimension.
It's much like a horizontal timeline moving from left to right, where some animation happen when a certain year is reached.
However the moving speed can be increased by the user, so fixed time to trigger animation is not an option.
There must be many ways to achieve what you want. The code below exploits jQuery's capability to handle custom events to provide a "loosely-coupled" observer pattern.
$(function() {
//Establish the two dozen functions that will be called.
var functionList = [
function() {...},
function() {...},
function() {...},
...
];
var gridParams = {offset:10, pitch:65};//Example grid parameters. Adjust as necessary.
//Establish a custom event and its handler.
var $myElement = $("#myID").data('lastIndex', -1).on('hasMoved', function() {
$element = $(this);
var pos = $element.position();//Position of the moved element relative to its offset parent.
var index = Math.floor((pos.left - gridParams.offset) / gridParams.pitch);//Example algorithm for converting pos.left to grid index.
if(index !== $element.data('lastIndex')) {//Has latest movement align the element with the next grid cell?
functionList[index](index, $element);//Call the selected function.
$element.data('lastIndex', index);//Remember index so it can be tested mext time.
}
});
});
$(function() {
//(Existing) function that moves the element must trigger the custom 'hasMoved' event after the postition has been changed.
function moveElement() {
...
...
...
myElement.trigger('hasMoved');//loosely coupled 'hasMoved' functionality.
}
var movementInterval = setInterval(moveElement, 100);
});
As you can see, an advantage of loose-coupling is that a function and the code that calls it can be in different scopes - .on('hasMoved', function() {...} and myElement.trigger('hasMoved') are in different $(function(){...}) structures.
If you wanted to add other functions to change the position of myElement (eg first, previous, next, last functions), then, after moving the element, they would each simply need to trigger 'hasMoved' to ensure that the appropriate one of your two dozen functions is called, without needing to worry about scopes.
The only thing you need to ensure is that your two dozen functions are scoped such that they can be called by the custom event handler (ie that they are in the same scope or an outer scope, up to and including the global scope).
I've had to make many assumptions, so the code above will not be 100% correct but hopefully it will provide you with a way ahead.

Little simulation of gravity in JS using canvas

So, I am trying to create a few circles and then I want them to fall down. Here is the code and demo: demo FireBug tells me that the method "move" is not defined for undefined objects, so something must be wrong when I want to create an array of obects. Correct my mistakes and take into consideration that I have just started learning object oriented programming in JS.
Instead of creating multiple events, create one event and loop in there:
setInterval(function(){
ctx.clearRect(0,0,1000,1000); //Clear the canvas here
for (i = 0;i<bubble.length;++i)
{
bubble[i].move();
bubble[i].redraw();
}
},32);
The problem was a scope problem.
The way you had written it i had the value of 10 in all events where they where executing.
Working fiddle: http://jsfiddle.net/some/fGChQ/16/
Your other problem is that you clear the canvas in your redraw... For every circle.
I've made a fork of this that addresses the looping issues, there also appears to have been a problem with the clearing of the canvas rectangle that was causing some interference
for (i = 0;i<bubble.length - 1; ++i)
{
console.log(bubble[i].y)
setInterval(function(){
bubble[i].move();
bubble[i].redraw();
},32);
}
bubble.length is 10, array is index 0-9. bubble[10] is undefined, so you can't call the method move on it.

Categories