Redefining a value for each statement? - javascript

In the project that I'm working on I want for different elements to fade in and out as you scroll along.
I defined the opacity of the element as f(x)=a ( x - d ) ^ 2 + e where the opacity would be f(x) and x would be $(window).scrollTop (). e would be >=1.
The elements should fade in and out after each other with slight overlap, so for each element the parabola would have to move further along the x axis.
var alpha = -0.000009 * ((Math.pow($(window).scrollTop () + delta), 2)) + 1;
$('#content').css({'opacity':alpha});
That would be part of a function triggered by scrolling.
This works for element #1 but for the following elements I'd have to change delta. Is there a way to define it's value differently for each element? Or would I have to manually change it for each one? I was hoping to keep this as simple as possible.

Is there a way to define it's value differently for each element?
Yes, you could use an attribute data-delta on each element, and read that as part of your function
<div id="content" data-delta="1.23">Content here</div>
read it with .data("delta") given an element reference
var $elem = $('#content');
var delta = $elem.data("delta");
var alpha = -0.000009 * ((Math.pow($(window).scrollTop () + delta), 2)) + 1;
$elem.css({'opacity':alpha});

Related

Increment style.marginLeft with each click?

I'm building a basic slider with JavaScript. Each time button is clicked, div slide should increment its margin-left "-100px".
I have this code:
document.getElementById('core-next').onclick = function() {
document.getElementById('slides').style.marginLeft = "-100px";
}
And it works in a way that when I click #core-next margin gets set to -100px.
But what I want to achieve is that every time I click a button, margin increases by -100px.
So it looks like: -100px, -200px, -300px...
Is this possible in pure JavaScript? jQuery has "+="! Can I do this in Javascript wihout adding additional variable?
I tried this:
document.getElementById('core-next').onclick = function() {
document.getElementById('slides').style.marginLeft -= 200 + 'px';
}
But its not working...
Is there a way to achieve this in JavaScript, without creating additional variable that will hold margin value?
Thanks!
That property is a string so first you need to read it, parse it to a int and then change the value and reset it. Something like this:
document.getElementById('core-next').onclick = function() {
var slides = document.getElementById('slides');
// Read it and parse to an int
var marginLeft = parseInt(slides.style.marginLeft, 10);
// Subtract value, add pixel back in and reset property
slides.style.marginLeft = (marginLeft - 100) + 'px';
}
If you really need it in one line you could do this:
document.getElementById('slides').style.marginLeft = (parseInt(document.getElementById('slides').style.marginLeft, 10) - 100) + 'px';
But this solution while it doesn't have a variable holding the value and is one line isn't great since it calls getElementById twice for same value.
you can use parseInt function to remove px from marginLeft string. First parameter is the input string and the second one is the radix.
var slides = document.getElementById('slides');
document.getElementById('core-next').onclick = function() {
slides.style.marginLeft = (parseInt(slides.style.marginLeft, 10) - 100) + 'px';
}

Javascript: Recursion, jQuery Error

Working on a navigation menu script with jQuery. The script is being designed with recursion so that there is no hard coded limit to the number of levels the menu has.
I'll start with the code:
navigationMenu.prototype.reset = function ( ulElement, colorIndex, colors ) { //Color index should always be 1 when directly calling this function
var listItems = $(ulElement.children);
var numItems = listItems.length;
var targetWidth = (100 / numItems) + '%';
listItems.each( function ( x ) {
var children = $(listItems[x].children);
var xT = $(listItems[x]).prop('tagName');
var subMenu = null;
children.each( function ( y ) {
var yT = $(children[y]).prop('tagName');
if (yT == 'UL') {
subMenu = $(children[y]);
} else if (yT == 'A') {
$(children[y]).css('background-color', colors[colorIndex-1]); //Offset by 1 to facilitate for 0 indexed arrays
$(children[y]).hover( function () { //Set hover color to the opposite
$(children[y]).css('background-color',colors[(3-colorIndex)-1]); //3-1 = 2 and 3-2 = 1, subtract 1 to facilitate 0 indexed arrays
}, function() {
$(children[y]).css('background-color',colors[colorIndex-1]); //3-1 = 2 and 3-2 = 1, subtract 1 to facilitate 0 indexed arrays
}); //Rest of style SHOULD be handled by css (width 100%, text color, text align)
}
});
if (subMenu !== null) { //Recurse
navigationMenu.prototype.reset(subMenu, (3 - colorIndex), colors); //Not defined?
}
if (xT == 'LI') { //Format the element
$(listItems[x]).css('width',targetWidth);
$(listItems[x]).css('background-color', colors[colorIndex]);
}
});
};
Next, The error:
Uncaught TypeError: Cannot read property 'firstChild' of null <-whitespace-> jquery-1.11.1.min.js:2
What concerns me is that the error does not seem to come directly from my code, rather, a function within the jQuery library; however, I'm placing good money on the fact that it is because of something I did wrong.
A live demo can be found here:
http://proofoftheilluminati.com/test/test.html
For an idea of the final look of the menu you can see the top level with hover effect and a simple JS script that maths the link widths here:
http://proofoftheilluminati.com/test/index.html
Script:
http://proofoftheilluminati.com/test/scripts/menu.js
I'm hosting a freshly downloaded copy of jQuery version 1.11.1:
http://proofoftheilluminati.com/test/scripts/jquery-1.11.1.min.js
What it should be doing:
Top level list should be orange with black over effect
second level list should be black with orange hover effect
third level list should be same as first, etc.
Positioning is handled by external css file
What it is doing:
Handles top level list correctly, seems to error before style second level list.
Please let me know if I left anything out. I try to be thorough.
Edit: The supplied code has a comment on the line that calls itself:
//Not defined?
This was left over from a previous error, I was having trouble getting it to recognize the recursive function call. I tried the following lines here and they would not allow the function to progress:
this.reset(subMenu, (3 - colorIndex), colors);
reset(subMenu, (3 - colorIndex), colors);
navigationMenu.reset(subMenu, (3 - colorIndex), colors);
Additionally, this function is called when the document is ready:
$(document).ready(function() {
s = new navigationMenu('#NavMenu', '#884106', '#000000', -1);
});
Edit: modified code to use x/y instead of index and xT/yT instead of tag (removed nested variables with same name)
When you first call navigationMenu.prototype.reset, I'm guessing ulElement is a DOM element, but when you call it recursively, you are passing it subMenu, which is a jQuery object. That will be a problem for the following line:
var listItems = $(ulElement.children);
Try changing the following line of code:
navigationMenu.prototype.reset(subMenu, (3 - colorIndex), colors);
To:
navigationMenu.prototype.reset(subMenu[0], (3 - colorIndex), colors);
I prefer to always prefix variables that refer to jQuery objects with "$" to keep them straight.
You could also use this inside the functions given to .each(). So instead of:
children.each(function(index) {
var tag = $(children[index]).prop('tagName');
You could have:
children.each(function() {
var $child = $(this),
tag = $child.prop('tagName');
You could also consider using the jQuery .children() method, instead of the children DOM element property

Find distance between two DIVs using jQuery?

I have two DIVs that I need to know the calculated browser distance (in height) of them.
I have read about the offset feature but the examples were not written for the way I am trying to do this.
Example usage:
<div class="foo"></div>
<div class="bar"></div>
I want to know the distance between these two.
Please help me to find the distance dynamically with jQuery.
Something like this should work:
$('.foo').offset().top - $('.bar').offset().top
As long as each class only has one element on the page.
If they are not unique, give the two elements an ID and reference with that.
Use .offset():
$('.foo').offset().top - $('.bar').offset().top
This function finds the distance in pixels between the centre of two elements, no jquery:
function distanceBetweenElems(elem1, elem2) {
var e1Rect = elem1.getBoundingClientRect();
var e2Rect = elem2.getBoundingClientRect();
var dx = (e1Rect.left+(e1Rect.right-e1Rect.left)/2) - (e2Rect.left+(e2Rect.right-e2Rect.left)/2);
var dy = (e1Rect.top+(e1Rect.bottom-e1Rect.top)/2) - (e2Rect.top+(e2Rect.bottom-e2Rect.top)/2);
var dist = Math.sqrt(dx * dx + dy * dy);
return dist;
}
I use it like this:
var target1 = document.querySelector('#foo');
var target2 = document.querySelector('#bar');
if (distanceBetweenElems(target1,target2)<100){
target1.classList.add('active');
}

Using JavaScript to increment top/left/bottom/right values

I am trying to increment the position of an element by, say, x pixels. Here is what I've tried so far:
var top = document.getElementById("something").style.top;
top = top + "300px"
I know that this is not going to work, but I was wondering if it was possible to increment a position value like this.
Because style.top is a string with units on the end of it like "300px" you can only do math with it when you convert just the numeric part to an actual number.
Assuming you have a positioned element (so setting the top value will do something) and you already have a top style set directly on the element and not set via CSS (so getting obj.style.top will actually get you something), you can do it by parsing the number out of the style value like this:
var obj = document.getElementById("something");
var topVal = parseInt(obj.style.top, 10);
obj.style.top = (topVal + 300) + "px";
Working example: http://jsfiddle.net/jfriend00/pt46X/
That won't work fine because, for example, if top had a value of 200px, it would become "200px300px". Try this:
var elem = document.getElementById("something");
elem.style.top = parseInt(elem.style.top, 10) + 300 + "px"
Demo WEEEE!!!!
let top = 0;
let left = 0;
let text = document.getElementById("TextToTranslate");
text.setAttribute("style","top:"+top+"px; "+left+":px;");
use this in a while loop and it works fine, i'm just figuring out how to slow it down so i can see the transition

Javascript style.left is empty string

next.onclick = function() {
move('left', li_items[0]);
};
var move = function(direction, el) {
pos = el.style[direction].split('px')[0];
pos = parseInt(pos, 10) + 10;
el.style[direction] = pos + 'px';
};
I'm using the simple code above to try and move an element. Now when I breakpoint on this, the value of el.style[direction] is: " ". So then when i try to do anything with it, it breaks. Why would this be? Isn't style.left supposed to return an integer?
Why would this be?
Presumably because it hasn't been set to anything.
Isn't style.left supposed to return an integer?
No. It is supposed to return a string containing the value of the CSS left property as set directly on the element (either by setting the JS property itself or by using a style attribute). It does not get a value from the cascade and it should only be an integer if the value is 0 (since all other lengths require units).
See How to get computed style of a HTMLElement if you want to get the computed value for the property rather than what I described in the previous paragraph.
style provides the original style as calculated from the CSS, not the updated and possibly dynamic style. You probably want currentStyle instead.
next.onclick = function() {
move('left', li_items[0]);
};
var move = function(direction, el) {
var lft = document.defaultView.getComputedStyle(el)[direction];
pos = parseFloat(lft);
pos = parseInt(pos, 10) + 10;
el.style[direction] = pos + 'px';
};
Note: like Elliot said you'll have to get the currentStyle/computedStyle. Here's a way to make it cross-browser, however when applying styles via JS, this is one good case where some sort of framework (eg Prototype [Scriptaculous], jQuery) would be useful.
Just a comment.
In your code:
> pos = el.style[direction].split('px')[0];
> pos = parseInt(pos, 10) + 10;
The split in the first line is superfluous, in the second line parseInt will convert (say) 10px to the number 10 just as effectively (and more efficiently) than what you have.
pos = parseInt(el.style[direction], 10);

Categories

Resources