Im looking for an elegant solution for a fade in and out of an HTML element onmouseover on mouseout without using jQuery (call me old fashioned).
In theory the below js solution should work however I am having problems with it working could someone point me in the right direction or offer an alternative solution??
My Js functions are and the HTML which is inserted is the same as which is on the page...
function fadeIn(element) {
for (i = 0; i < 100; i++) {
var value = 0 + i;
element.style.opacity = value;
element.style.filter = 'alpha(opacity=' + value + ')';
}
}
function fadeOut(element) {
for (i = 0; i < 100; i++) {
var value = 100 - i;
element.style.opacity = value;
element.style.filter = 'alpha(opacity=' + value + ')';
element.innerHTML = "<div class='container' id='container' onmouseover='fadeOut(this)'><img src='./images/myImage.jpg' onload='fadeIn(this.parent)' /></div>";
}
}
Your fadeIn/Out doesn't work right because you haven't done anything to control the rate of change. That will just execute immediately and show/hide the elements.
Try something like this:
function fadeIn(el) {
var opac = 0;
var i = setInterval(function() {
opac += 10;
if (opac >= 100) {
clearInterval(i);
opac = 100;
}
el.style.opacity = opac;
el.style.filter = 'alpha(opacity=' + opac + ')';
}, 20);
}
That should fade in over 200ms (20 * 100 / 10). Play with the numbers to adjust the speed.
As for mouseover/out, you can just bind the events like anything else.
Generally, attaching JS events like you have, using HTML attributes, is frowned upon. Usually you'd have a helper like this: https://gist.github.com/955642
You want to write your own method that will check which of the main methods, addEventListener or attachEvent your browser supports.
Related
So here is an example of the function I need to replicate:
document.getElementById('img1').onmouseover = function() {
document.getElementById('img1').style.width = expandTo + '%';
expandCompensate(1);
}
document.getElementById('img1').onmouseout = function() {
expandReset();
}
The situation is that I have a for loop creating some div elements, and the number of them is dynamic. As of right now, I have it creating 4 div elements, so I created 4 iterations of the above functions for img1, img2, img3 and img4. But what I would like to do is to have the onmouseover and onmouseout functions created dynamically based on how many div elements I've decided to create (based on a variable).
Is there any way to do this? Here is all the code for context (it's not much), there are comments in the JS with explanations for everything. The part I'm trying to automate is at the bottom:
https://jsfiddle.net/4w0714su/3/
And here is the working example for context of what I'm trying to achieve:
http://www.ericsartor.ca/imgwide
FYI: The image is I picked were random, I just needed high res images. Just doing this for practice! Thanks to anyone that can help me figure this out!
I can't understand your code very well, but I'll answer particularly what you're asking.
You can achieve what you want by doing a loop:
for (var i = 0; i < 4; i++) {
document.getElementById('img' + i).onmouseover = function() {
this.style.width = expandTo + '%';
expandCompensate(Number(this.id.replace('img', '')));
};
document.getElementById('img' + i).onmouseout = function() {
expandReset();
}
}
Note: you can't use the i variable inside the event handlers' functions, because it will always be 4, since it will finish the loop, and will never be changed again.
Another way of doing that is by using an IIFE (Immediately-invoked function expression), e.g:
for (var i = 0; i < 4; i++) {
(function(n) {
document.getElementById('img' + n).onmouseover = function() {
this.style.width = expandTo + '%';
expandCompensate(n);
};
document.getElementById('img' + n).onmouseout = function() {
expandReset();
}
})(i);
}
Doing that, you're passing to a function the current i value, so in that scope, the value of n will be a different one for each execution, e.g 0, 1, 2 and 3.
An immediately-invoked function expression (or IIFE, pronounced
"iffy") is a JavaScript design pattern which produces a lexical scope
using JavaScript's function scoping.
This could be achieved by iterating all those DOM elements and binding events in a loop.
As we bind events in loop, and event callback is being executed later when loop would be iterated completely, we need to maintaing the value of current iteration using CLOSURE.
Try this snippet:
var pageHeight = document.getElementById('findBottom').getBoundingClientRect().bottom,
numOfPics = 4; //the number of div elements to create
//creates the div elements within a container div in the HTML document
for (var i = 1; i <= numOfPics; i++) {
document.getElementById('imgContain').innerHTML += '<div id="img' + i + '" class="imgPane"></div>';
}
//used to resize all divs if the window changes size
window.onresize = function() {
pageHeight = document.getElementById('findBottom').getBoundingClientRect().bottom;
for (var i = 1; i <= imgClasses.length; i++) {
document.getElementById('img' + i).style.height = pageHeight + 'px';
}
for (var i = 1; i <= imgClasses.length; i++) {
document.getElementById('img' + i).style.width = 100 / imgClasses.length + '%';
}
};
//sets the height of each div to be the mximum height of the page (without scrolling)
for (var i = 1; i <= numOfPics; i++) {
document.getElementById('img' + i).style.height = pageHeight + 'px';
}
//makes all the divs equal percentage widths
for (var i = 1; i <= numOfPics; i++) {
document.getElementById('img' + i).style.width = 100 / numOfPics + '%';
}
//the percentage of the page the hovered image will expand to
var expandTo = 40;
//function for when an image is hovered over
function expandCompensate(whichImg) {
for (var i = 1; i <= numOfPics; i++) {
if (i != whichImg)
document.getElementById('img' + i).style.width = (100 - expandTo) / (numOfPics - 1) + '%';
}
}
//function for when the hovered image is left to reset the widths
function expandReset() {
for (var i = 1; i <= numOfPics; i++) {
document.getElementById('img' + i).style.width = 100 / numOfPics + '%';
}
}
(function bindEvents() {
for (var i = 1; i <= numOfPics; i++) {
document.getElementById('img' + i).onmouseover = (function(i) {
return function() {
document.getElementById('img' + i).style.width = expandTo + '%';
expandCompensate(i);
}
})(i);
document.getElementById('img' + i).onmouseout = function() {
expandReset();
};
}
})();
body,
p,
div {
margin: 0;
padding: 0;
}
body {} #findBottom {
position: absolute;
bottom: 0;
}
.imgPane {
float: left;
background-position: center;
transition: width 0.25s;
}
#img1 {
background-image: url('http://www.ericsartor.ca/imgwide/img//1.jpg');
}
#img2 {
background-image: url('http://www.ericsartor.ca/imgwide/img//2.jpg');
}
#img3 {
background-image: url('http://www.ericsartor.ca/imgwide/img//3.jpg');
}
#img4 {
background-image: url('http://www.ericsartor.ca/imgwide/img//4.jpg');
}
<div id="imgContain"></div>
<!-- ABSOLUTE ELEMENTS -->
<div id="findBottom"></div>
<!-- ABSOLUTE ELEMENTS -->
I'm trying to create a menu of social media icons that slides into and out of the page. The following code works, but it is too fast. It doesn't look like sliding. I think I could adjust the timing using the setInterval() method, but I can't get it to work. This is the code so far:
var socialMedia = document.getElementById("socialmedia");
var stalkMe = document.getElementById("pleasestalkme");
function SM() {
socialMedia.style.position = "fixed";
socialMedia.style.right = "-330px";
}
SM();
stalkMe.addEventListener("click", function(){
if (socialMedia.style.right === "-330px") {
for (i = -330; i <= -30; i++) {
var j = i +"px";
socialMedia.style.right = j;
}
} else if (socialMedia.style.right === "-30px"){
for (i = -30; i >= -330; i--){
var j = i +"px";
socialMedia.style.right = j;
}
}
}, false);
You should have a look at CSS transitions. Basically you just need to change the right style from 300px to 0px and using transition: right 1s; you would see your element being animated
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Using_CSS_transitions
Otherwise, you could have a look at jQuery.... (I feel bad).
Prior to the solution, a word of warning: you actually should not use this code snippet. Instead heed the advice of floribon and look into css transitions.
However, if you absolutely must do it the outmoded way:
for (i = -330; i <= -30; i++) {
var j = i +"px";
socialMedia.style.right = j;
}
write
var hnd;
i = -330;
hnd = setInterval ( function () {
var j = i +"px";
socialMedia.style.right = j;
i++;
if (i > -30) {
clearInterval(hnd); // end activity
}
}, 50 ); // interval length in ms
I want to make my list in my nav to have the transition applied.
The call
animate(0,"mainNav",.04,0.03);
The function
function animate(num, element, transitionUnit, delayUnit){
var transition = 0;
var delay = 0;
var x = document.querySelectorAll('nav > ul > li');
for (i=0; i<x.length; i++){
x[i].style.WebkitTransform = "translate3d("+num+"px,0px,0)";
x[i].style.opacity = "1";
x[i].style.transition = transition + "s " + delay +"s !important";
delay += delayUnit;
transition += transitionUnit;
}
}
This function applies changes to everything except that It just completely misses x[i].style.transition = ""; and x[i].innerHTML = "";
What could be the problem? I've tried changing everything including the querySelector, but this is what I've had found to work except the two I have mentioned above.
P.S. It works with
animate(0,"viewNav",.04,0.03);
I just need it to work with mainNav
I want to select all the elements of a class. Then change that class to another class . After 0.5 seconds i want to revert the elements back to their original class. I must do this 8 times in a row. Even though my code achieves that(in a way) i can't see the color changes in the buttons . Can anyone help me ? it's a timing problem i guess. Here is the js code :
$(document).ready(function(){
$('#start').click(function(){
game();
})
function game(){
var ordine = new Array();
for(var t = 1; t <= 8; t++){
var y = 0;
for (var k = 0; k < t; k++) {
var x = Math.floor((Math.random() * 4) + 1);
ordine[y++] = x;
change1(x);
setTimeout(change2(x), 500);
}
}
}
function change1(y){
var z = 'cls' + y;
var t = 'cls' + y + 2;
$("." + z).removeClass(z).addClass(t);
}
function change2(y){
var z = 'cls' + y + 2;
var t = 'cls' + y;
$("." + z).removeClass(z).addClass(t);
}
})
Here you can find the full code(html,css and js)
http://jsfiddle.net/Cx5VK/2/
The problem is in the following line:
setTimeout(change2(x), 500);
You are calling the function change2 here, passing its return value to setTimeout.
What you actually want though is to call the change2 function after 500ms. Change your code to:
setTimeout(function() { change2(x); }, 500);
That way, you are passing an anonymous function to setTimout, which will then be executed by it after 500ms.
EDIT: I've modified your JSFiddle: http://jsfiddle.net/Cx5VK/7/ stripping out a lot of code that didn't do anything in that sample (you quite possibly need it elsewhere):
$(document).ready(function () {
$('#start').click(function () {
game();
})
function game() {
var x = Math.floor((Math.random() * 4) + 1);
change1(x);
}
function change1(y) {
var z = 'cls' + y;
var t = 'cls' + y + 2;
$("." + z).removeClass(z).addClass(t);
setTimeout(function() { change2(y); }, 500);
}
function change2(y) {
var z = 'cls' + y + 2;
var t = 'cls' + y;
$("." + z).removeClass(z).addClass(t);
game();
}
});
Now, the game function simply gets a random number and calls change1 with that number as parameter. change1 itself will set the timeout to reset the color for that square via change2. At the end of that function, the game is "restarted" by a simple call to game(), to get another random number and so on and so forth. I hope this is what you were looking for.
Here's the html part...
<body ng-controller="homeController">
<div id="happyValentines" ng-model="myText"> {{ myText }}
I don't get why this works...
$scope.myText = "fksdm kdsmfk msldfkm kdfm ksdmf lsmdflm ";
$scope.changeHeight = function(elem) {
var body = document.body;
var height = 0;
var right = 0;
var opacity = 0; ...
But this doesn't...
$scope.changeHeight = function(elem) {
var body = document.body;
var height = 0;
var right = 0;
var opacity = 0;
body.style.opacity = 0;
var index = 0;
var str = "fksdm kdsmfk msldfkm kdfmksdmf lsmdflm ";
function frame() {
index += 2;
$scope.myText = str.substr(0, index);
height += 4;
if (right < 60) {
right += 1;
elem.style.marginRight = right + "px";
}
opacity += .01;
elem.style.height = height + "px";
elem.style.opacity = opacity;
body.style.opacity = opacity;
if (opacity >= 1) {
clearInterval(id);
$scope.addButtons();
// document.createElement....
}
}
var id = setInterval(frame, 30);
}
I'm quite new to angular and would like to know what angular construct is behind this, or why this is the case.
In the 2nd code you have declared function 'changeHeight', and inside that you are setting the value of 'myText'. but on the page you have not called 'changeHeight' function so it'll not call that function and the value of 'mytext' won't be set.
try calling function 'changeHeight' on the page using ng-init or ng-click or ng-change a/c to situation.
First of all: ng-model is mainly used for form elements and is basically a deluxe version of using onchange events for get value from forms to the model and a $watch to get the value from the model to the form element. You don't need it just to display a value on the screen.
Second: You shouldn't modify the document or DOM in the controller. That's the directives responsibility (or maybe a service if it's document element modifications).
Regarding your second code block I don't get why you have a "function frame()" inside the changeHeight method. And the code is incomplete and you never actually call the frame() method that sets the $scope.myText.
Please provide complete code to get better help.